langchain学习总结-Embedding 学习总结

OpenAI Embedding 学习总结

一、什么是 Embedding(嵌入)?

Embedding 是将文本转换为数值向量的技术,它能够:

  • 将文本映射到高维向量空间
  • 保留文本的语义信息
  • 使相似的文本在向量空间中距离更近

应用场景

  • 语义搜索
  • 文档相似度计算
  • 推荐系统
  • 文档聚类
  • 问答系统

二、LangChain 中的 Embedding

1. 基础嵌入模型

LangChain 提供了多种嵌入模型的统一接口,常用模型包括:

  • OpenAI Embeddings : text-embedding-3-small, text-embedding-3-large
  • 千帆 Embeddings : Embedding-V1
  • 其他本地模型

核心方法

方法 说明
embed_query(text) 将单个查询文本转换为向量
embed_documents(texts) 将多个文档文本批量转换为向量

三、示例代码与输出

示例 1:基础嵌入模型使用

python 复制代码
import dotenv
import numpy as np
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
from numpy.linalg import norm

dotenv.load_dotenv()

# 计算两个向量的余弦相似度
def cosine_similarity(vec1, vec2):
    dot_product = np.dot(vec1, vec2)
    norm_vec1 = norm(vec1)
    norm_vec2 = norm(vec2)
    return dot_product / (norm_vec1 * norm_vec2)

# 创建文本嵌入模型
embeddings = QianfanEmbeddingsEndpoint(model="Embedding-V1")

# 嵌入单个查询
query_vector = embeddings.embed_query("你好,我是一名学生")
print("查询向量维度:", len(query_vector))

# 批量嵌入文档
documents_vectors = embeddings.embed_documents([
    "你好,我是一名学生",
    "你好,我是一名老师",
    "你好,我是一名学生",  # 重复文本
])

print("文档向量数量:", len(documents_vectors))

# 计算相似度
sim1 = cosine_similarity(documents_vectors[0], documents_vectors[1])
sim2 = cosine_similarity(documents_vectors[0], documents_vectors[2])

print("向量1和向量2的相似度:", sim1)
print("向量1和向量3的相似度:", sim2)
预期输出:
makefile 复制代码
查询向量维度: 1024
文档向量数量: 3
向量1和向量2的相似度: 0.9567
向量1和向量3的相似度: 1.0000

输出分析:

  • 向量维度为 1024(千帆 Embedding-V1 模型)
  • 相同文本的向量相似度为 1.0(完全相同)
  • 相似文本的向量相似度接近 1.0(语义相近)

四、CacheBackedEmbeddings(缓存嵌入)

是什么?

CacheBackedEmbeddings 是 LangChain 提供的带缓存功能的嵌入包装器,它能够:

  • 缓存已计算过的文本向量,避免重复调用 API
  • 节省时间和成本
  • 支持多种存储后端(本地文件、Redis 等)

有什么用?

优势 说明
节省成本 避免对相同文本重复调用付费 API
提升速度 从缓存读取比调用 API 快得多
离线可用 缓存后的文本可离线使用
一致性 相同文本始终得到相同的向量

核心参数

python 复制代码
CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings,    # 底层嵌入模型
    document_store,           # 存储后端
    namespace,                # 命名空间(区分不同缓存)
    query_embedding_cache=True # 是否缓存查询向量
)

五、示例代码与输出(带缓存)

示例 2:使用 CacheBackedEmbeddings

python 复制代码
import dotenv
import numpy as np
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
from langchain_classic.embeddings import CacheBackedEmbeddings
from langchain_classic.storage import LocalFileStore
from numpy.linalg import norm

dotenv.load_dotenv()

def cosine_similarity(vec1, vec2):
    dot_product = np.dot(vec1, vec2)
    norm_vec1 = norm(vec1)
    norm_vec2 = norm(vec2)
    return dot_product / (norm_vec1 * norm_vec2)

# 创建基础嵌入模型
embeddings = QianfanEmbeddingsEndpoint(model="Embedding-V1")

# 创建带缓存的嵌入模型
embeddings_with_cache = CacheBackedEmbeddings.from_bytes_store(
    embeddings,                      # 基础嵌入模型
    LocalFileStore("./cache/"),      # 本地文件存储
    namespace=embeddings.model,      # 使用模型名作为命名空间
    query_embedding_cache=True,      # 缓存查询向量
)

# 第一次调用 - 会请求 API 并缓存
query_vector = embeddings_with_cache.embed_query("你好,我是一名学生")
print("查询向量维度:", len(query_vector))

# 第二次调用相同文本 - 从缓存读取,不请求 API
query_vector_cached = embeddings_with_cache.embed_query("你好,我是一名学生")

# 批量嵌入(部分重复,会使用缓存)
documents_vectors = embeddings_with_cache.embed_documents([
    "你好,我是一名学生",  # 已缓存
    "你好,我是一名老师",  # 新文本
    "你好,我是一名学生",  # 已缓存
])

print("文档向量数量:", len(documents_vectors))

# 计算相似度
sim1 = cosine_similarity(documents_vectors[0], documents_vectors[1])
sim2 = cosine_similarity(documents_vectors[0], documents_vectors[2])

print("向量1和向量2的相似度:", sim1)
print("向量1和向量3的相似度:", sim2)
预期输出:
makefile 复制代码
查询向量维度: 1024
文档向量数量: 3
向量1和向量2的相似度: 0.9567
向量1和向量3的相似度: 1.0000
缓存目录结构:
bash 复制代码
./cache/
└── Embedding-V1/
    ├── <hash1>  # "你好,我是一名学生" 的缓存
    └── <hash2>  # "你好,我是一名老师" 的缓存

六、余弦相似度原理

公式

css 复制代码
cosine_similarity(A, B) = (A · B) / (||A|| × ||B||)

说明

  • A · B: 两个向量的点积
  • ||A||: 向量 A 的长度(模)
  • 取值范围 : [-1, 1]
    • 1.0: 完全相同方向
    • 0.0: 正交(无关)
    • -1.0: 完全相反方向

在文本嵌入中的应用

  • 值越接近 1,文本语义越相似
  • 值越接近 0,文本语义越不相关

七、最佳实践

  1. 生产环境务必使用缓存:可节省 50%+ 的 API 调用
  2. 选择合适的存储后端
    • 本地开发:LocalFileStore
    • 生产环境:Redis 或数据库
  3. 命名空间管理:使用模型名或项目名作为 namespace
  4. 批量处理 :优先使用 embed_documents 而非多次调用 embed_query
相关推荐
IT_陈寒2 小时前
Vite 5分钟性能优化实战:从3秒到300ms的冷启动提速技巧(附可复用配置)
前端·人工智能·后端
羊小猪~~2 小时前
【QT】-- QT基础类
开发语言·c++·后端·stm32·单片机·qt
陈随易2 小时前
Vue-Router v5内置文件式路由,告别手写维护的恐惧
前端·后端·程序员
FAFU_kyp2 小时前
Rust 结构体(struct)
开发语言·后端·rust
枫叶梨花3 小时前
SpringBoot+Vue实现SM4加密传输
spring boot·后端
悟空码字3 小时前
SpringBoot整合MyBatis-Flex保姆级教程,看完就能上手!
java·spring boot·后端
qq_2500568683 小时前
SpringBoot 引入 smart-doc 接口文档插件
java·spring boot·后端
w***76553 小时前
SpringBoot Test详解
spring boot·后端·log4j
掉头发的王富贵3 小时前
【2025年终总结】对象有了,工作没了
java·后端·年终总结