LangChain向量嵌入与语义表示实战推荐榜单
在LangChain的生态系统中,向量嵌入是所有语义检索功能的核心基础设施。无论是构建RAG、智能问答系统,还是对文本进行分类,底层都依赖它——它首先将人类语言转换为机器可计算的数值。本章从最基础的概念出发,逐步梳理如何对接各类嵌入模型、在本地运行以及优化性能,最后通过实战将技术文档转化为具体的向量表示。所有代码均可直接复制运行,新手也能轻松跟上。
8.1 什么是 Embedding?为何用于检索?
8.1.1 核心定义:文本的“数值指纹”
Embedding(嵌入)本质上是一种语义编码技术。它将任何文本——单词、句子或整篇文档——映射到一个高维数值向量空间中。在这个向量空间里,语义越相似的文本,其向量的距离就越接近。
举一个直观的例子:
“猫”的向量可能是 [0.82, -0.15, 0.33, ..., 0.21]
“狗”的向量可能是 [0.79, -0.18, 0.31, ..., 0.23]
“苹果”的向量可能是 [-0.22, 0.85, -0.17, ..., 0.09]
可以看到,“猫”和“狗”在向量空间中距离很近,因为它们同属动物,语义相似;而它们与“苹果”的距离则很远,因为语义关系疏远。这正是Embedding的核心价值:将抽象的语义转化为可计算、可比较的数值。
8.1.2 为何用于检索?超越传统关键词匹配
传统的关键词检索(如MySQL的like查询)存在一个致命缺陷:它仅匹配字面字符串,无法理解语义相似性。例如,搜索“如何用LangChain做RAG”可能找不到“LangChain搭建检索增强生成系统”这篇文章,尽管两者语义相同。而Embedding检索则能解决这个问题。
Embedding检索的工作流程非常清晰:
提前将所有文档转换为嵌入向量,存储在向量数据库中;
用户提问时,将问题也转换为嵌入向量;
计算查询向量与数据库中文档向量的距离,返回距离最近(最相似)的文档。
这正是LangChain中RAG的核心流程之一。Embedding充当了连接人类语言与机器检索能力的关键桥梁。
8.1.3 关键提醒
需要明确的是:LangChain本身不生产嵌入模型,它更像一个集成平台。它提供统一的接口,让开发者能轻松对接OpenAI、Hugging Face、本地模型等。只需改动一行代码,就能切换底层模型,无需关心具体调用细节。
8.2 使用 OpenAI、Hugging Face、Sentence-Transformers 生成嵌入
本节聚焦三种最主流的嵌入方式。代码力求精简,直接复制即可运行,依赖安装和参考来源一并注明。
8.2.1 准备工作:安装核心依赖
无论使用哪种模型,先安装基础工具:
pip install langchain# 核心框架pip install python-dotenv# 管理环境变量(用于存储API密钥)
8.2.2 OpenAI Embeddings(行业标准,精度高)
OpenAI的嵌入模型(如text-embedding-ada-002)性价比高,是生产环境的主流选择。当然,前提是需要OpenAI API密钥。
代码示例(简短可运行)
from langchain.embeddings.openai import OpenAIEmbeddingsfrom dotenv import load_dotenvimport os
# 加载环境变量(.env文件中存OPENAI_API_KEY=你的密钥)load_dotenv()
# 初始化OpenAI嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-ada-002",# 推荐模型,性价比最高openai_api_key=os.getenv("OPENAI_API_KEY"))
# 生成单句嵌入text = "LangChain向量嵌入实战"embedding = embeddings.embed_query(text)# 检索时用embed_query,文档用embed_documentsprint(f"嵌入向量维度:{len(embedding)}")# 输出1536(ada-002固定维度)print(f"嵌入向量前5位:{embedding[:5]}")
关键说明
embed_query专门用于生成用户查询的嵌入,会针对检索精度进行优化;embed_documents用于生成文档的嵌入;需额外安装
openai包(pip install openai)。
8.2.3 Hugging Face Embeddings(开源免费)
Hugging Face上提供大量免费开源嵌入模型,例如all-MiniLM-L6-v2,无需API密钥,非常适合本地开发或预算有限的项目。
代码示例
from langchain.embeddings import HuggingFaceEmbeddings
# 初始化Hugging Face嵌入模型(自动下载模型)embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2",# 轻量模型,速度快,适合入门model_kwargs={"device": "cpu"},# 若有GPU,改为"cuda"encode_kwargs={"normalize_embeddings": True}# 归一化,提升检索精度)
# 批量生成文档嵌入texts = ["LangChain是一个大模型开发框架","Embedding用于将文本转为向量","Hugging Face提供开源嵌入模型"]embeddings_list = embeddings.embed_documents(texts)print(f"批量生成{len(embeddings_list)}个嵌入,每个维度:{len(embeddings_list[0])}")
关键说明
需安装
sentence-transformers包(pip install sentence-transformers);model_name可替换为其他模型(如all-MiniLM-L12-v2),精度更高但速度略慢。
8.2.4 Sentence-Transformers(专为句子嵌入优化)
Sentence-Transformers库专注于句子或段落级别的嵌入。LangChain提供了专用接口,本质上是对Hugging Face模型的一层封装,使用更简洁。
代码示例
from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings
# 初始化Sentence-Transformers嵌入模型embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
# 生成单句嵌入text = "Sentence-Transformers专注于句子语义嵌入"embedding = embeddings.embed_query(text)print(f"嵌入向量维度:{len(embedding)}")
关键说明
与直接使用HuggingFaceEmbeddings相比,SentenceTransformerEmbeddings接口更清爽,默认执行归一化,省去冗余操作。适合句子级嵌入任务。
8.3 本地嵌入模型部署(BGE、text2vec)
当数据敏感、无法调用第三方API,或需要离线运行时,本地部署嵌入模型是最佳选择。重点介绍两个对中文友好的模型:BGE(中文检索效果公认优秀)和text2vec(轻量高效),它们都能通过LangChain在本地运行。
8.3.1 本地部署核心前提
环境:Python 3.8及以上,建议安装PyTorch(CPU即可,GPU加速更佳);
依赖:一行命令搞定——
pip install sentence-transformers torch;模型获取:首次运行时自动下载(几百MB到几个GB不等),也可手动从Hugging Face下载后本地加载。
8.3.2 BGE模型部署(中文首选)
BGE(BAAI General Embedding)由智源AI推出,中文语义理解能力强,支持长文本(最长8192 token),是中文RAG场景的首选。推荐直接使用BGE-M3版本。
代码示例(本地加载)
from langchain.embeddings import HuggingFaceEmbeddings
# 本地部署BGE-M3(自动下载,首次较慢)embeddings = HuggingFaceEmbeddings(model_name="FlagAI-Open/BGE-M3",model_kwargs={"device": "cpu",# 若有GPU,替换为"cuda""trust_remote_code": True# 必须为True,BGE含自定义代码},encode_kwargs={"normalize_embeddings": True,# 务必归一化,否则相似度不准确"max_length": 8192# BGE-M3支持长文本,按需调整})
# 测试中文嵌入text = "LangChain本地部署BGE嵌入模型"embedding = embeddings.embed_query(text)print(f"BGE-M3嵌入维度:{len(embedding)}")# 输出1024维print(f"嵌入向量前5位:{embedding[:5]}")
关键说明
模型版本:推荐BGE-M3;轻量版BGE-base-zh适合算力有限的设备。
GPU加速:若安装PyTorch-GPU,将
device改为"cuda",生成速度提升5-10倍。本地加载:将
model_name改为本地路径(如"./BGE-M3"),避免重复下载。
8.3.3 text2vec模型部署(轻量高效)
text2vec是专为中文设计的轻量嵌入模型,体积约100MB,速度极快,在笔记本CPU上也能流畅运行,足以满足日常开发需求。
代码示例
from langchain.embeddings import HuggingFaceEmbeddings
# 本地部署text2vec模型embeddings = HuggingFaceEmbeddings(model_name="shibing624/text2vec-base-chinese",model_kwargs={"device": "cpu"},encode_kwargs={"normalize_embeddings": True})
# 测试中文嵌入texts = ["text2vec轻量高效", "中文嵌入模型推荐"]embeddings_list = embeddings.embed_documents(texts)print(f"text2vec嵌入维度:{len(embeddings_list[0])}")# 输出768维
关键说明
- 优势在于体积小、速度快,CPU即可高效处理。
- 特别适合中小规模中文文档检索或本地Demo开发。
8.4 嵌入维度、距离度量(余弦相似度)
生成嵌入后,必须理解两个核心概念:“嵌入维度”(向量的长度)和“距离度量”(如何判断向量相似性)——它们直接决定检索精度。
8.4.1 嵌入维度:向量的“长度”
核心定义
嵌入维度即向量中数值的个数。例如ada-002为1536维,BGE-M3为1024维。通常维度越高,承载的语义信息越丰富,但计算和存储成本也相应增加。
主流模型维度对照(重点记忆)
| 模型名称 | 嵌入维度 | 特点 |
|---|---|---|
| OpenAI text-embedding-ada-002 | 1536 | 通用、高精度、性价比高 |
| BGE-M3 | 1024 | 中文最优、支持长文本 |
| all-MiniLM-L6-v2 | 384 | 轻量、快速、适合入门 |
| text2vec-base-chinese | 768 | 中文轻量、精度与速度平衡 |
维度选择建议
生产环境(通用场景):优先1024~1536维(如BGE-M3或ada-002),精度足够。
本地Demo、低算力设备:选384~768维(如all-MiniLM-L6-v2或text2vec)。
注意:维度并非越高越好,超过一定阈值后精度提升微乎其微,反而增加成本。
8.4.2 距离度量:判断语义相似的“标尺”
距离度量用于计算两个向量之间的“距离”,距离越近语义越相似。LangChain中最常用、最推荐的是“余弦相似度”,此外还有欧氏距离、曼哈顿距离等。
余弦相似度(重点)
余弦相似度衡量两个向量之间的“夹角”,取值在-1到1之间。
等于1:方向完全一致,语义相同;
等于0:方向垂直,语义无关;
等于-1:方向相反,语义对立。
在文本检索中,通常只关心正数。相似度超过0.7即可认为文本高度相关。
LangChain中计算余弦相似度(代码示例)
from langchain.embeddings import HuggingFaceEmbeddingsfrom sklearn.metrics.pairwise import cosine_similarityimport numpy as np
# 初始化嵌入模型embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 生成两个文本的嵌入向量text1 = "LangChain向量嵌入"text2 = "LangChain Embedding实战"vec1 = np.array(embeddings.embed_query(text1)).reshape(1, -1)vec2 = np.array(embeddings.embed_query(text2)).reshape(1, -1)
# 计算余弦相似度similarity = cosine_similarity(vec1, vec2)[0][0]print(f"两个文本的余弦相似度:{similarity:.4f}")# 输出约0.8+,高度相关
关键说明
需安装
scikit-learn包(pip install scikit-learn)。实际使用中,Chroma、FAISS等向量数据库会自动计算余弦相似度,无需手动实现。
余弦相似度不受向量“长度”影响,只关注方向,非常适合文本语义匹配:长句和短句只要语义相似,计算结果就高。
8.5 缓存嵌入结果避免重复计算
生成嵌入(尤其是调用API或运行本地大模型)非常耗时。如果反复处理同一文本,浪费资源。LangChain内置缓存机制,可以巧妙避免重复计算,提升效率。
8.5.1 两种常用缓存方式
LangChain支持多种缓存,重点介绍两种:内存缓存(适合临时开发)和SQLite缓存(可持久化,程序重启后缓存仍在,适合长期项目)。
方式1:内存缓存(InMemoryCache)
缓存存储在内存中,程序重启后消失。适合临时测试或短期开发。
from langchain.embeddings import OpenAIEmbeddingsfrom langchain.cache import InMemoryCacheimport langchainfrom dotenv import load_dotenv
load_dotenv()
# 启用内存缓存langchain.llm_cache = InMemoryCache()
# 初始化OpenAI嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 第一次生成(调用API)text = "LangChain缓存嵌入实战"emb1 = embeddings.embed_query(text)print("第一次生成:完成")
# 第二次生成同一文本(从缓存读取,不调API)emb2 = embeddings.embed_query(text)print("第二次生成:完成(从缓存读取)")
# 验证结果是否一致print(f"两次嵌入是否相同:{emb1 == emb2}")# 输出True
方式2:SQLite缓存(SQLiteCache)
缓存存储在本地的SQLite数据库文件中,程序重启后依然有效。适合长期开发或生产环境。
from langchain.embeddings import OpenAIEmbeddingsfrom langchain.cache import SQLiteCacheimport langchainfrom dotenv import load_dotenv
load_dotenv()
# 启用SQLite缓存(缓存文件位于当前目录下的langchain_cache.db)langchain.llm_cache = SQLiteCache(database_path="./langchain_cache.db")
# 初始化嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 第二次同样从缓存读取text = "LangChain SQLite缓存"emb1 = embeddings.embed_query(text)emb2 = embeddings.embed_query(text)print(f"两次嵌入是否相同:{emb1 == emb2}")# 输出True
8.5.2 关键提醒
缓存生效的条件:文本必须完全一致(包括空格和大小写),否则视为新文本重新生成。
除上述两种外,LangChain还支持Redis缓存,适合分布式系统,用法相似。
8.6 批量嵌入与性能优化
当需要处理大量文本(如成千上万篇文档)时,逐条生成嵌入显然不切实际。LangChain支持批量嵌入,配合性能优化技巧,可以大幅提升处理效率。这是大型文档检索的必备技能。
8.6.1 批量嵌入(核心操作)
所有LangChain嵌入模型都提供embed_documents方法,可以一次性批量生成多个文本的嵌入。这比逐条处理快5到10倍。
from langchain.embeddings import HuggingFaceEmbeddings
# 初始化嵌入模型embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 模拟100条文本,批量处理texts = [f"LangChain批量嵌入测试{i}" for i in range(100)]
# 一次调用,完成所有batch_embeddings = embeddings.embed_documents(texts)print(f"批量生成{len(batch_embeddings)}个嵌入,每个维度:{len(batch_embeddings[0])}")
8.6.2 性能优化技巧(实战必备)
技巧1:控制批量大小
批量大小并非越大越好,需根据模型和硬件调整:
API模型(OpenAI):建议每次10~100条,避免被限流。
本地模型(BGE、text2vec):CPU上建议32~64条;GPU上可扩展至64~128条,具体视显存与内存而定。
技巧2:异步调用(提升并发效率)
LangChain嵌入模型支持异步调用(ainvoke)。处理大量文本时,异步操作能提高I/O并发效率,特别适合Web服务场景。
from langchain.embeddings import OpenAIEmbeddingsimport asynciofrom dotenv import load_dotenv
load_dotenv()
# 初始化嵌入模型embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 定义异步函数批量生成async def async_batch_embed():texts = [f"异步嵌入测试{i}" for i in range(50)]# 注意使用aembed_documentsbatch_embeddings = await embeddings.aembed_documents(texts)return batch_embeddings
# 运行if __name__ == "__main__":embeddings_list = asyncio.run(async_batch_embed())print(f"异步批量生成{len(embeddings_list)}个嵌入")
技巧3:GPU加速(本地模型首选)
本地部署模型时,使用GPU可提速5~10倍。只需将model_kwargs中的device改为"cuda"即可(需安装PyTorch-GPU)。
embeddings = HuggingFaceEmbeddings(model_name="FlagAI-Open/BGE-M3",model_kwargs={"device": "cuda"},# GPU加速配置encode_kwargs={"normalize_embeddings": True})
技巧4:文本预处理(减少无效计算)
生成嵌入前,对文本进行“清洁”:去除多余空白、换行、重复内容,甚至无效字符。文本缩短,计算成本自然降低。
def preprocess_text(text):# 去除首尾空白,替换换行和多余空格text = text.strip().replace("n", "").replace("", " ")# 剔除过短文本return text if len(text) >= 3 else ""
# 先批量预处理,再生成嵌入texts = [preprocess_text(t) for t in texts if preprocess_text(t)]batch_embeddings = embeddings.embed_documents(texts)
8.7 嵌入质量评估方法
嵌入生成后,如何判断其质量?许多开发者忽略这一步,导致后续检索精度不高。这里介绍三种实用的评估方法,从简单到复杂,适合不同场景。
8.7.1 方法1:人工评估(最简单,适合小批量)
思路:选取几对文本,凭直觉判断语义相似性,然后计算它们嵌入向量的余弦相似度,验证计算结果是否与直觉一致。
from langchain.embeddings import HuggingFaceEmbeddingsfrom sklearn.metrics.pairwise import cosine_similarityimport numpy as np
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 人工标注的文本对(标注“相似”或“不相似”)text_pairs = [("LangChain向量嵌入", "LangChain Embedding", "相似"),("猫", "狗", "相似"),("猫", "苹果", "不相似"),("Python编程", "Ja va编程", "相似"),("雨天", "晴天", "不相似")]
# 开始评估correct = 0for text1, text2, label in text_pairs:vec1 = np.array(embeddings.embed_query(text1)).reshape(1, -1)vec2 = np.array(embeddings.embed_query(text2)).reshape(1, -1)sim = cosine_similarity(vec1, vec2)[0][0]# 设置阈值0.7,大于等于视为相似pred = "相似" if sim >= 0.7 else "不相似"if pred == label:correct += 1print(f"{text1} vs {text2}:相似度{sim:.4f},预测{pred},实际{label}")
accuracy = correct / len(text_pairs)print(f"n评估准确率:{accuracy:.2f}")# 准确率高于0.8表示嵌入质量良好
8.7.2 方法2:聚类评估(检查语义簇)
逻辑:将同类文本的嵌入向量聚集,不同类文本分离。聚类效果越好,嵌入质量越高。常用K-Means聚类+UMAP或t-SNE降维可视化。
from langchain.embeddings import HuggingFaceEmbeddingsfrom sklearn.cluster import KMeansfrom sklearn.manifold import TSNEimport matplotlib.pyplot as plt
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 构造几类不同的文本texts = ["LangChain向量嵌入", "LangChain RAG实战", "LangChain文档加载","BGE嵌入模型", "text2vec模型", "OpenAI Embeddings","Python编程", "Ja va开发", "Ja vaScript入门"]
embeddings_list = embeddings.embed_documents(texts)
# 使用t-SNE将高维向量降至2维以便可视化tsne = TSNE(n_components=2, random_state=42)embeddings_2d = tsne.fit_transform(embeddings_list)
# 使用K-Means分为3类kmeans = KMeans(n_clusters=3, random_state=42)clusters = kmeans.fit_predict(embeddings_list)
# 绘制散点图plt.scatter(embeddings_2d[:, 0], embeddings_2d[:, 1], c=clusters, cmap="viridis")for i, text in enumerate(texts):plt.annotate(text, (embeddings_2d[i, 0], embeddings_2d[i, 1]), fontsize=8)plt.title("嵌入向量聚类可视化")plt.show()
评估标准
如果图中“LangChain”、“嵌入模型”、“编程语言”三类文本各自聚集、界限清晰,说明嵌入质量良好;若混杂不清,则需考虑更换模型。
8.7.3 方法3:下游任务评估(最实用,生产环境首选)
嵌入最终用于检索或问答,因此直接评估下游任务的表现最实在。例如,评估检索召回率或问答准确率。
示例:用检索召回率评估
from langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.vectorstores import Chromafrom langchain.document_loaders import TextLoader
# 1. 加载文档(假设文档分别涉及LangChain、BGE、Python)loader = TextLoader("test_doc.txt")documents = loader.load()
# 2. 生成嵌入并构建向量库embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")db = Chroma.from_documents(documents, embeddings)
# 3. 测试查询是否能命中正确文档queries = ["LangChain是什么", "BGE模型怎么用", "Python入门教程"]recall = 0for query in queries:similar_docs = db.similarity_search(query, k=1)# 简单判断:关键词是否出现在结果文档中if query.split(" ")[0] in similar_docs[0].page_content:recall += 1
print(f"检索召回率:{recall / len(queries):.2f}")# 召回率超过0.9表示嵌入质量合格
8.7.4 评估总结
小批量文本:用人工评估,简单高效。
大规模文本:用聚类评估,直观理解语义分布。
生产环境:用下游任务评估,最贴合实际用途。
8.8 【实战】为技术文档生成高质量向量表示
本节将前面所有知识点串联起来,完成一个完整实战:加载技术文档(以LangChain官方文档片段为例),预处理文本,生成嵌入,使用缓存优化,评估质量,最后将文档向量存储到向量数据库中,为后续检索做好准备。
8.8.1 实战目标
加载本地的技术文档(.txt格式);
预处理并分割文本,防止超出模型输入长度;
使用本地BGE-M3模型生成高质量嵌入;
启用缓存,避免重复计算;
评估嵌入质量;
将嵌入向量存入Chroma向量数据库(支持持久化)。
8.8.2 实战步骤(完整代码,可直接运行)
步骤1:准备工作(依赖+文档)
安装依赖:
pip install langchain sentence-transformers torch chromadb scikit-learn matplotlib准备技术文档:创建一个
langchain_docs.txt文件,写入以下内容(LangChain相关介绍):LangChain是一个用于构建大语言模型应用的框架,它提供了一系列工具和组件,帮助开发者快速搭建RAG、聊天机器人等应用。LangChain的核心组件包括:文档加载器(Document Loaders)、文本分割器(Text Splitters)、嵌入模型(Embeddings)、向量数据库(Vector Stores)、大语言模型(LLMs)等。向量嵌入(Embedding)是LangChain RAG的核心,它能将文本转化为数值向量,实现语义检索。常用的嵌入模型有OpenAI Embeddings、BGE、text2vec等。BGE-M3是智源AI推出的开源嵌入模型,中文语义理解能力强,支持长文本,适合本地部署,是中文RAG场景的首选模型。Chroma是一个轻量级向量数据库,适合本地开发和小规模数据存储,可与LangChain无缝集成,支持相似性检索。
步骤2:完整实战代码
from langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.document_loaders import TextLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.vectorstores import Chromafrom langchain.cache import SQLiteCacheimport langchainfrom sklearn.metrics.pairwise import cosine_similarityimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.manifold import TSNE
# ---------------------- 1. 启用缓存(避免重复计算) ----------------------langchain.llm_cache = SQLiteCache(database_path="./embedding_cache.db")
# ---------------------- 2. 加载并预处理技术文档 ----------------------loader = TextLoader("langchain_docs.txt")documents = loader.load()
# 文本预处理函数def preprocess_text(text):text = text.strip().replace("n", " ").replace("", " ")return text if len(text) >= 5 else ""
# 预处理内容for doc in documents:doc.page_content = preprocess_text(doc.page_content)
# 分割文本(防止过长,并保留上下文)text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)split_docs = text_splitter.split_documents(documents)print(f"文档分割后共{len(split_docs)}个文本块")
# ---------------------- 3. 本地部署BGE-M3模型,生成嵌入 ----------------------embeddings = HuggingFaceEmbeddings(model_name="FlagAI-Open/BGE-M3",model_kwargs={"device": "cpu", "trust_remote_code": True},encode_kwargs={"normalize_embeddings": True, "max_length": 8192})
# 批量生成嵌入(相同文本从缓存读取)doc_embeddings = embeddings.embed_documents([doc.page_content for doc in split_docs])print(f"生成{len(doc_embeddings)}个文档嵌入,维度:{len(doc_embeddings[0])}")
# ---------------------- 4. 嵌入质量评估(聚类可视化) ----------------------tsne = TSNE(n_components=2, random_state=42)embeddings_2d = tsne.fit_transform(doc_embeddings)
plt.scatter(embeddings_2d[:, 0], embeddings_2d[:, 1], c="blue", alpha=0.7)for i, doc in enumerate(split_docs):plt.annotate(doc.page_content[:20] + "...", (embeddings_2d[i, 0], embeddings_2d[i, 1]), fontsize=8)plt.title("技术文档嵌入向量聚类可视化")plt.show()
# 人工评估几对文本sample_texts = [split_docs[0].page_content, split_docs[2].page_content, split_docs[3].page_content]sample_embeddings = embeddings.embed_documents(sample_texts)
sim1 = cosine_similarity([sample_embeddings[0]], [sample_embeddings[1]])[0][0]sim2 = cosine_similarity([sample_embeddings[0]], [sample_embeddings[2]])[0][0]sim3 = cosine_similarity([sample_embeddings[1]], [sample_embeddings[2]])[0][0]print(f"n相似度评估:")print(f"LangChain框架 vs 向量嵌入:{sim1:.4f}")print(f"LangChain框架 vs BGE-M3:{sim2:.4f}")print(f"向量嵌入 vs BGE-M3:{sim3:.4f}")# 向量嵌入和BGE-M3应最相似,因同属嵌入话题
# ---------------------- 5. 将嵌入存入Chroma向量数据库(持久化) ----------------------vector_db = Chroma.from_documents(documents=split_docs,embedding=embeddings,persist_directory="./langchain_embedding_db")vector_db.persist()print(f"n向量数据库已持久化,存储路径:./langchain_embedding_db")
# 测试检索效果query = "BGE-M3模型适合什么场景"similar_docs = vector_db.similarity_search(query, k=2)print(f"n检索结果(与'{query}'最相关的2个文本块):")for i, doc in enumerate(similar_docs):print(f"n--- 结果{i+1} ---")print(doc.page_content)
8.8.3 实战结果说明
文档分割:将长文档切成短块,既能适配模型输入限制,又通过重叠保留上下文信息。
嵌入生成:使用BGE-M3本地模型,开启缓存,重复文本不再重复计算。
质量评估:聚类图显示语义相关文本聚集在一起;人工抽查结果符合预期,例如“向量嵌入”与“BGE-M3”相似度最高,因为它们都围绕嵌入话题。
向量存储:最终存入Chroma数据库并持久化,下次启动可直接加载,无需重新生成。
8.8.4 实战拓展
切换模型:只需修改
embeddings初始化代码即可换成OpenAI等模型。加载其他格式:使用
PyPDFLoader加载PDF,WebBaseLoader抓取网页。大规模文档:结合批量嵌入与GPU加速,大幅提升处理效率。
本章总结
本章从Embedding基础概念出发,到动手实战,全面覆盖了嵌入的核心原理、多种模型调用、本地部署、性能优化和效果评估。最后通过完整示例,将技术文档转化为向量表示。
关键要点回顾:
Embedding的本质:将文字转换为机器可计算的向量,这是语义检索的基石。
模型选择:通用高精度选OpenAI,中文场景首选BGE,轻量需求用text2vec,按需抉择。
性能提升:批量处理、启用缓存、GPU加速——三招让效率成倍增长。
质量评估:人工、聚类、下游任务——三选一,确保嵌入可靠而非盲目。
实战闭环:文本预处理→生成嵌入→质量评估→存入数据库,掌握完整流程。
下一章将重点讲解向量数据库的使用,届时可借助本章生成的文档向量,实现完整的LangChain RAG检索功能。
