LangChain:数据增强之嵌入模型包装器

LangChain框架中,嵌入模型包装器(Embedding Model Wrappers) 是用于将文本转换为向量表示的标准化接口,支持多种底层模型和服务。

嵌入(Embedding )

嵌入(Embedding):核心目标是将离散的符号(如文字)转化为连续的数值向量。是文本到向量的映射技术,通过词嵌入技术可以分析两段文本之间的相关性。

嵌入(Embedding )是连接人类语言与机器计算的桥梁。它通过将文本转化为数值向量,通过计算向量之间的余弦度来量化,使得计算机能够:

  • 理解语义:捕捉词与词、句与句之间的关系。
  • 支持复杂任务:如搜索、推荐、翻译等。
  • 适应不同场景:通过调整嵌入模型,优化特定应用的效果。

更多参考理解嵌入(Embedding)的定义、原理及意义

嵌入模型

官方资料:LangChain Embedding models

嵌入模型将人类语言转化为机器可理解、可高速精准比对的格式。这些模型接收文本输入后,会生成固定长度的数值数组,形成文本语义的”数值指纹“。通过语义理解(而非仅关键词匹配),嵌入技术使搜索系统能精准定位相关文档。

嵌入模型将原始文本——例如句子、段落或推文——转换为固定长度的数字向量,以捕捉其语义含义。这些向量使得机器能够基于含义而非精确词语来比较和搜索文本。在实践中,这意味着具有相似思想的文本在向量空间中会彼此靠近。

用单一、紧凑的数值表示捕捉任何文本(一条推文、一份文档或一本书)的语义本质——这正是嵌入模型的核心能力,也是众多检索系统的基石。

工作原因

  • 将文本嵌入为向量:模型将每个输入字符串编码为一个高维向量。
  • 度量相似性:使用数学度量比较向量,以衡量底层文本之间的关联程度。

历史背景

嵌入模型的发展格局历经多年演变,已发生显著变革。2018年成为关键转折点——谷歌在这一年推出了BERT(基于Transformer的双向编码器表征模型)。BERT通过Transformer架构将文本编码为简洁的向量表征,在各类自然语言处理任务中实现了前所未有的性能突破。然而,BERT在生成高效的句子向量方面存在局限,这直接推动了SBERT(Sentence-BERT/句子BERT)的诞生。SBERT对BERT架构进行优化,专注于生成语义丰富的句子向量表征,借助余弦相似度等度量方法即可快速比对语义相关性,从而将相似句检索等任务的计算开销降低数个量级

如今,嵌入模型生态呈现多元化态势,众多技术服务商提供各具特色的实现方案。为客观评估不同模型的性能优劣,研究者和开发者常参考MTEB(海量文本嵌入基准测试)等权威测评体系。

扩展阅读

嵌入模型包装器

接口使用

LangChain 为各类文本嵌入模型提供统一接口,针对常见操作提供标准化方法,通过两大核心方法,这一通用接口可显著简化与不同嵌入服务提供商的交互流程:

  • embed_documents: 将多个文本(文档)嵌入为向量,返回一个嵌入向量列表。
  • embed_query: 将单个文本(查询)嵌入向量,返回一个嵌入向量列表。

这一技术区分至关重要,因为部分服务提供商对文档(被检索对象)与查询语句(搜索输入本身)采用差异化的嵌入策略。

以下为具体实例,演示如何运用LangChain的.embed_documents方法对字符串列表进行向量化编码:

1
2
3
4
5
6
7
8
9
10
11
12
13
from langchain_openai import OpenAIEmbeddings
embeddings_model = OpenAIEmbeddings()
embeddings = embeddings_model.embed_documents(
[
"Hi there!",
"Oh, hello!",
"What's your name?",
"My friends call me World",
"Hello World!"
]
)
len(embeddings), len(embeddings[0])
(5, 1536)

该例子返回一个嵌入向量列表,其中每个嵌入向量由 1536个浮点数构成。

API 参考:OpenAIEmbeddings

为了方便,还可以使用embed_query方法嵌入单个文本:

1
query_embedding = embeddings_model.embed_query("What is the meaning of life?")

扩展阅读

嵌入集成

LangChain提供了许多嵌入模型集成,可以在嵌入模型(Embedding models)集成页面上找到。

用户可以根据自己的具体需要,选择适合的文本嵌入模型。

相似性度量

每个嵌入本质上是一组坐标,通常位于高维空间中。在这个空间里,每个点(嵌入)的位置反映了其对应文本的语义。正如相似的词语在词典中可能彼此接近,相似的概念在这个嵌入空间里也会彼此靠近。这使得不同文本之间的直观比较成为可能。

通过将文本转换为这些数值表示,我们可以使用简单的数学运算快速衡量两段文本的相似程度,而无需考虑其原始长度或结构。常见的相似性度量方法包括:

  • 余弦相似度:测量两个向量之间夹角的余弦值。
  • 欧氏距离:测量两点之间的直线距离。
  • 点积:测量一个向量在另一个向量上的投影量值。

相似性度量的选择应基于模型。例如,OpenAI建议它们的嵌入采用余弦相似性,这很容易实现:

1
2
3
4
5
6
7
8
9
10
import numpy as np

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

similarity = cosine_similarity(query_result, document_result)
print("Cosine Similarity:", similarity)

扩展阅读

  • 关于嵌入技术与相似性度量,参考 Simon Willison’s nice blog post and video 博客、视频。
  • 对嵌入向量相似性度量的选择建议,参考Google this documentation 指南。
  • 对相似性度量方法的全面解析,参考 Pinecone’s blog post 博客。
  • 关于嵌入向量最佳相似性度量方法的常见问题解答,参考OpenAI’s FAQ

缓存

嵌入可以被存储或临时缓存,以避免重复计算。可以使用 CacheBackedEmbeddings 来实现嵌入缓存。这个包装器将嵌入存储在键值存储中,其中文本被哈希处理,哈希值用作缓存中的键。
初始化 CacheBackedEmbeddings 主要支持的方式是 from_bytes_store。它接受以下参数:

  • underlying_embedder:用于嵌入的底层嵌入器。
  • document_embedding_cache:任何用于缓存文档嵌入的 ByteStore
  • batch_size:(可选,默认为 None)在两次存储更新之间要嵌入的文档数量。
  • namespace:(可选,默认为 “”)用于文档缓存的命名空间。有助于避免冲突(例如,将其设置为嵌入模型名称)。
  • query_embedding_cache:(可选,默认为 None)一个用于缓存查询嵌入的 ByteStore,或者设置为 True 以重用与 document_embedding_cache 相同的存储。

在生产环境中,通常会使用更健壮的持久化存储,例如数据库或云存储。有关选项,请参阅存储集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import time
from langchain_classic.embeddings import CacheBackedEmbeddings
from langchain_classic.storage import LocalFileStore
from langchain_core.vectorstores import InMemoryVectorStore

# 创建你的底层嵌入模型
underlying_embeddings = ... # 例如:OpenAIEmbeddings(), HuggingFaceEmbeddings() 等。

# 存储将嵌入持久化到本地文件系统
# 这不适用于生产环境,但对本地测试很有用
store = LocalFileStore("./cache/")

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
underlying_embeddings,
store,
namespace=underlying_embeddings.model
)

# 示例:缓存查询嵌入
tic = time.time()
print(cached_embedder.embed_query("Hello, world!"))
print(f"第一次调用耗时: {time.time() - tic:.2f} 秒")

# 后续调用使用缓存
tic = time.time()
print(cached_embedder.embed_query("Hello, world!"))
print(f"第二次调用耗时: {time.time() - tic:.2f} 秒")

嵌入模型集成

嵌入模型 所在的包
OpenAIEmbeddings langchain-openai
AzureOpenAIEmbeddings langchain-openai
GoogleGenerativeAIEmbeddings langchain-google-genai
OllamaEmbeddings langchain-ollama
TogetherEmbeddings langchain-together
FireworksEmbeddings langchain-fireworks
MistralAIEmbeddings langchain-mistralai
VoyageAIEmbeddings langchain-voyageai
CohereEmbeddings langchain-cohere
NomicEmbeddings langchain-nomic
FakeEmbeddings langchain-core
DatabricksEmbeddings databricks-langchain
WatsonxEmbeddings langchain-ibm
NVIDIAEmbeddings langchain-nvidia
AIMLAPIEmbeddings langchain-aimlapi

LangChain:数据增强之嵌入模型包装器

http://blog.gxitsky.com/2025/05/25/AI-LangChain-012-Embedding-Mode/

作者

光星

发布于

2025-05-25

更新于

2026-03-15

许可协议

评论