RAG 入门:LangChain Embedding 介绍与使用
Embedding 介绍
词向量(Word Embedding)是自然语言处理(NLP)中的一种核心表示形式。它将词汇表中的单词或短语映射到实数向量空间中,用于捕获高维空间内单词之间的语义和句法相似性。
在词嵌入的背景下,我们可以将单词表示为高维空间中的向量。每个维度对应一个特定的特征,例如'生物'、'猫科动物'、'人类'、'性别'等。每个单词在每个维度上都被分配有一个数值,通常在 -1 到 1 之间,表示该词与该特征的关联程度。
例如,'猫'这个词在'猫科动物'维度上可能具有较高的正值,而在'人类'维度上具有接近于零的值,这反映了它与猫科动物的紧密关联性,而与人类的关联性较低。
这种数值表示使我们能够捕捉单词之间的语义关系,并对其执行数学运算,例如计算单词之间的相似度或将其用作 NLP 任务中机器学习模型的输入。对于检索增强生成(RAG)系统而言,Embedding 是将非结构化文本转化为可被向量数据库检索的关键步骤。
LangChain 框架提供了丰富的接口,支持来自不同来源的多种嵌入模型,方便开发者根据需求选择。
LangChain 支持的 Embedding 模型
OpenAI Embeddings
OpenAI 提供的嵌入模型(如 text-embedding-ada-002)在通用语义理解方面表现优异。使用 LangChain 集成 OpenAI 模型非常简单。
import os
from langchain_openai import OpenAIEmbeddings
os.environ["OPENAI_API_KEY"] = "your-api-key-here"
embeddings = OpenAIEmbeddings()
text = "This is a test document."
text_embedding = embeddings.embed_query(text)
print(f"Vector length: {len(text_embedding)}")
print(f"First 5 dimensions: {text_embedding[:5]}")
OpenAI 的 embedding-ada-002 通常输出 1536 维的向量。这些向量可以直接用于后续的距离计算或存入向量数据库。
HuggingFace Embeddings
Hugging Face 托管了大量开源的预训练模型,适合需要私有化部署或对特定领域进行微调的场景。
from langchain_community.embeddings import HuggingFaceEmbeddings
embedding_path = r'H:\pretrained_models\bert\english\paraphrase-multilingual-mpnet-base-v2'
embeddings = HuggingFaceEmbeddings(model_name=embedding_path)
text = "This is a test document."
text_embedding = embeddings.embed_query(text)
print(f"Vector length: {len(text_embedding)}")
使用本地模型时,请确保已下载相应的权重文件,并满足环境依赖(如 PyTorch)。
Google Generative AI Embeddings
Google 也提供了专门的嵌入模型,适用于其生态系统的集成。
from langchain_google_genai import GoogleGenerativeAIEmbeddings
import os
os.environ["GOOGLE_API_KEY"] = "your-google-api-key"
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
text_embedding = embeddings.embed_query("hello, world!")
print(f"Vector length: {len(text_embedding)}")
更多可用的 Embedding 集成可以在 LangChain 官方文档中查看。
计算文本相似性
Embedding 的核心价值在于可以通过向量距离来衡量文本的语义相似度。最常用的指标是余弦相似度(Cosine Similarity)。
基础相似度计算
我们可以通过计算两个向量之间的余弦相似度来判断它们的语义接近程度。值越接近 1,表示语义越相似。
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from langchain_openai import OpenAIEmbeddings
word_list = ["Cat", "Dog", "Car", "Truck", "Computer", "Laptop", "Apple", "Orange", "Music", "Dance"]
embedding_model = OpenAIEmbeddings()
embeds = [embedding_model.embed_query(word) for word in word_list]
input_word = "Lion"
input_embed = embedding_model.embed_query(input_word)
def cosine_similarity_custom(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
similarity = cosine_similarity_custom(embeds[0], input_embed)
print(f"Similarity with 'Cat': {similarity:.4f}")
sims = []
for emb in embeds:
sim = cosine_similarity(np.array([emb]), np.array([input_embed]))[0][0]
sims.append(sim)
print(f"Similarities: {sims}")
在这个示例中,"Lion" 与 "Cat" 的相似度通常会很高,因为它们都属于动物类别,而与其他类别的词相似度较低。
结合向量数据库进行检索
在实际的 RAG 应用中,我们通常需要将大量文本向量化后存储起来,以便快速检索。FAISS(Facebook AI Similarity Search)是一个高效的向量搜索库,常与 LangChain 配合使用。
加载数据
假设我们将待查询的文本存储在 CSV 文件中。
from langchain_community.document_loaders import CSVLoader
loader = CSVLoader(file_path='data.csv', csv_args={
'delimiter': ',',
'quotechar': '"',
'fieldnames': ['Words']
})
data = loader.load()
for doc in data[:3]:
print(doc.page_content)
创建 FAISS 向量存储
利用 LangChain 的 FAISS 类,我们可以直接将文档列表转换为向量数据库。
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
db = FAISS.from_documents(data, embeddings)
db.save_local("faiss_index")
相似性搜索
用户输入查询后,系统会在向量数据库中查找最相似的文档片段。
user_input = "Lion"
results = db.similarity_search(user_input)
for i, res in enumerate(results):
print(f"Result {i+1}: {res.page_content} (Score: {res.metadata.get('score', 'N/A')})")
通过这种方式,系统能够基于语义而非关键词匹配找到相关的信息。例如,即使 CSV 中没有包含 "Lion" 这个词,只要它所在的上下文与 "Cat" 或 "Animal" 语义相近,也能被检索出来。
最佳实践与注意事项
- 模型选择:根据应用场景选择 Embedding 模型。通用场景可用 OpenAI 或 BGE 等大模型;对隐私要求高的场景建议使用本地部署的 HuggingFace 模型。
- 分块策略:在进行 Embedding 之前,建议对长文本进行合理的分块(Chunking),避免单个向量包含过多信息导致检索精度下降。
- 归一化:部分向量数据库要求向量经过归一化处理,FAISS 通常会自动处理,但需注意具体配置。
- 成本考量:API 调用的 Embedding 服务通常按 token 计费,大规模应用时需评估成本预算。
通过合理使用 LangChain 的 Embedding 功能,开发者可以快速构建具备语义理解能力的检索系统,为后续的 LLM 问答提供精准的知识支撑。