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
相关推荐
2601_962055976 小时前
跟据spring boot版本,查看对应的tomcat,并查看可支持的tomcat的版本范围
spring boot·后端·tomcat
Lost of 程序猿7 小时前
ASP.NET Core API 幂等性设计深度实战:从一次重复申领事故说起
后端·asp.net
QQ_21696290968 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端
郑州光合科技余经理10 小时前
本地生活服务系统:模块边界与结算字段怎么拆
java·开发语言·前端·后端·系统架构·uni-app·php
IT_陈寒10 小时前
Vue的嵌套组件竟然吃掉了我的事件?
前端·人工智能·后端
大辉狼_音频架构11 小时前
进阶:从源码编译 SOF 固件与 topology
后端
大辉狼_音频架构11 小时前
上板:让 SOF 在 FRDM-i.MX8MP 上跑起来
后端
大辉狼_音频架构11 小时前
FRDM-IMX8MP UUU 烧录 eMMC 指南
后端
运行时异常12 小时前
【WMS 仓储系统集成 AI Agent 实战】第 3 讲:Spring Security 6 + JWT——addFilterBefore 一词之差,全站 401
java·后端
LinMINGJing00712 小时前
PageHeaderData:Page 的页面头
后端