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 联网 数据敏感用本地,快速开发用联网

如果觉得有帮助,欢迎点赞收藏~

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐