LangChain嵌入模型入门
·
LangChain 嵌入模型入门:从概念到代码实战
本文适合 LangChain 初学者,用最直白的语言讲清楚嵌入模型是什么、怎么用,以及 RAG 检索的完整流程。
一、什么是嵌入模型?
嵌入模型(Embedding Model)的作用是把文字变成向量,让计算机能计算两段文字之间的语义相似度。
"苹果手机" → [0.12, -0.83, 0.45, ...] ← 1536 个数字
"iPhone" → [0.11, -0.81, 0.43, ...] ← 两个向量很接近 → 语义相似
"香蕉" → [-0.6, 0.22, 0.91, ...] ← 差很远 → 语义无关
这串数字叫向量,数字的个数叫维度。维度越多,语义描述越精细,但计算成本也越高。
二、两个核心方法
在 LangChain 里,嵌入模型只有两个方法需要记:
| 方法 | 用途 | 输入 | 输出 |
|---|---|---|---|
embed_query() |
嵌入用户问题 | 单个字符串 | 一个向量 |
embed_documents() |
嵌入知识库文档 | 字符串列表 | 向量列表 |
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)
# 嵌入单个查询(用户提问)
query_vec = embeddings.embed_query("我的订单到哪了")
# 嵌入一批文档(知识库内容)
doc_vecs = embeddings.embed_documents([
"ORD-001 已发货,预计明天到达",
"退款政策:7天无理由退换",
"客服热线:400-888-8888",
])
print(len(query_vec)) # 384(该模型的向量维度)
三、RAG 完整流程实战
RAG(检索增强生成)分两个阶段:
【建库阶段(一次性)】 文档 → 切片 → Embedding → 存向量库
【查询阶段(每次请求)】 用户提问 → Embedding → 检索相似片段 → 返回结果
完整代码
import os
from dotenv import load_dotenv
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
load_dotenv()
# 1. 准备知识库文档
docs = [
"ORD-001 已发货,预计明天到达",
"退款政策:收到商品7天内可无理由退换",
"客服热线 400-888-8888,工作时间 9:00-21:00",
]
# 2. 切分长文档(每块不超过500字符)
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50, # 块间重叠,防止语义被截断
)
chunks = splitter.create_documents(docs)
# 3. 向量化 + 存入向量库
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)
vectorstore = FAISS.from_documents(chunks, embeddings)
# 4. 检索:找最相似的3条(附带相似度分数)
results = vectorstore.similarity_search_with_score("退款怎么申请?", k=3)
for doc, score in results:
print(f"相似度: {score:.4f} | {doc.page_content}")
输出结果
相似度: 1.0089 | 客服热线 400-888-8888,工作时间 9:00-21:00
相似度: 1.0160 | 退款政策:收到商品7天内可无理由退换
相似度: 1.1837 | ORD-001 已发货,预计明天到达
注意:FAISS 默认返回的是 L2 距离(欧氏距离),分数越小表示越相似,和余弦相似度的高分=相似刚好相反,不要搞混。
四、相似度是什么?
相似度就是两段文字在语义上有多像,用数字表示:
1.00 完全一样 "退款申请" vs "退款申请"
0.90 几乎同义 "退款申请" vs "我要退钱"
0.75 相关但不同 "退款申请" vs "售后服务"
0.50 有点关系 "退款申请" vs "订单查询"
0.20 基本无关 "退款申请" vs "今天天气"
向量库做 similarity_search 时,内部会对所有文档计算相似度,返回分数最高的 k 条:
# 向量库内部做的事:
# "退款政策7天无理由" → 相似度 0.91 ✅ 返回
# "物流配送时间" → 相似度 0.43 ✗ 不返回
# "客服电话400" → 相似度 0.38 ✗ 不返回
五、联网模型 vs 本地模型
LangChain 设计最爽的地方:两种模型接口完全一样,换模型只改一行。
# 联网版(OpenAI,按 token 收费)
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 本地版(HuggingFace,完全免费,数据不出门)
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-zh-v1.5")
# 后面这段代码两种方式完全一样,不需要改
vectorstore = FAISS.from_documents(chunks, embeddings)
results = vectorstore.similarity_search("用户问题", k=3)
| 对比项 | 联网(OpenAI) | 本地(HuggingFace) |
|---|---|---|
| 费用 | 按 token 计费 | 免费 |
| 数据隐私 | 数据发送到外部 | 数据不出本机 |
| 中文效果 | 一般 | bge-large-zh 更好 |
| 部署难度 | 开箱即用 | 需下载模型(几百MB) |
六、向量维度怎么选?
学习练习 → text-embedding-3-small(1536维)
中文项目 → BAAI/bge-large-zh-v1.5(1024维)
数据量大 → BAAI/bge-small-zh-v1.5(512维)
高精度需求 → text-embedding-3-large(3072维)
重要原则:建库和查询必须用同一个模型,维度不一致会直接报错。
# ✅ 正确:始终用同一个 embeddings 对象
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = FAISS.from_documents(chunks, embeddings)
results = vectorstore.similarity_search("问题", k=3)
# similarity_search 内部自动复用同一个 embeddings
七、安装依赖
# 本地模型
pip install langchain-huggingface sentence-transformers faiss-cpu langchain-text-splitters
# OpenAI 模型
pip install langchain-openai faiss-cpu langchain-text-splitters
总结
| 知识点 | 一句话记忆 |
|---|---|
| 嵌入模型 | 把文字变成向量,用来计算语义相似度 |
embed_query vs embed_documents |
前者嵌入单个问题,后者嵌入一批文档 |
chunk_overlap |
块间重叠,防止语义在切割处断裂 |
| FAISS 分数 | 越小越相似(L2距离,不是余弦) |
| 建库和查询 | 必须用同一个模型,维度要一致 |
| 本地 vs 联网 | 数据敏感用本地,快速开发用联网 |
如果觉得有帮助,欢迎点赞收藏~
更多推荐
所有评论(0)