LangChain 06:RAG 概要
前言
模型参数里没有你们的内部文档、工单与产品说明;硬塞进提示词又容易超上下文、难更新。
RAG(Retrieval-Augmented Generation) 先按问题检索相关片段,再让模型据此生成,适合私有知识库问答。
本文给 LangChain 1.x 下的 RAG 概要:流水线阶段、哪一步要用哪种模型、重排序插在何处,以及最小 LCEL 链与 Agent 检索 Tool。
加载、切分、嵌入、入库、重排的细节分别见后续专文;更短的入门片段见《LangChain 02:入门教程》。
聊天模型继续对接 火山方舟 Coding Plan(ark-code-latest);嵌入演示用 DeterministicFakeEmbedding,避免未开通嵌入模型时脚本跑不通。
下文需要 Python 3.12+,依赖用 uv 管理。
各示例都是完整可运行脚本:复制到项目根目录(与 .env 同级)后执行 uv run python xxx.py 即可。
依赖
建议使用 Python 3.12 及以上。
用 uv 初始化工程并声明基础依赖(版本请按项目实际调整)。
演示向量库用 langchain-core 自带的 InMemoryVectorStore,无需再装 langchain-community(该包已日落)。
1 | uv init langchain-rag-overview |
若已在空目录内初始化,也可写 uv init --name langchain-rag-overview,再执行 uv venv 与 uv add。
后续运行示例脚本时,可直接 uv run python demo.py,一般不必手动 activate 虚拟环境。
若习惯激活,Windows 使用 .venv\Scripts\activate,macOS / Linux 使用 source .venv/bin/activate。
rich 用于查看检索命中与最终答案。
示例里常用 from rich import print as rprint。
在项目根目录创建 .env,写入 Coding Plan 的 API Key 与专用 Base URL。
不要把 .env 提交进 Git。
1 | OPENAI_API_KEY=你的火山方舟 API Key |
示例脚本开头用 load_dotenv() 加载该文件。
请勿把 Base URL 写成普通方舟 .../api/v3,以免无法抵扣 Coding Plan 额度。
实现
流程概览
RAG 可拆成 离线索引 与 在线问答 两段。
离线(语料变更时重跑或增量更新):
- 加载:文件/网页 →
Document。 - 切分:长文 → 带
metadata的小块。 - 嵌入:文本 → 向量。
- 入库:写入向量库(演示用内存库;生产可用 Milvus、云厂商库等)。
在线(每次用户提问):
- 检索:问题向量(或关键词)→ Top-K 相关块。
- 重排(可选):对候选块精排并截断到 Top-N。
- 增强:把块拼进提示词上下文。
- 生成:聊天模型据上下文作答;要求「无依据则说不知道」。
索引质量大致决定「找不找得到」;重排与提示词、生成模型一起决定「找得到之后说得对不对」。
各环节与模型
不是每一步都要调模型。
聊天、嵌入、重排是三类不同能力,不要混用同一个模型名。
| 环节 | 是否用模型 | 模型类型 | 用什么 |
|---|---|---|---|
| 加载 | Loader / 解析库读文件 | ||
| 切分 | ⍻ | 嵌入模型 | 字符/递归等规则切分;语义切分才要嵌入模型 |
| 嵌入(离线) | ✓ | 嵌入模型 | 文本 → 向量(如 bge-m3) |
| 入库 | 向量库写接口 | ||
| 检索 | ⍻ | 嵌入模型 | 向量检索要把问题向量化后才能与库中向量比相似度(须与入库同一嵌入模型);纯关键词检索可不用 |
| 重排 | ✓ | Rerank 模型 | 对候选块精排并截断(如 bge-reranker-v2-m3),不是聊天模型 |
| 增强 | 拼字符串 / 提示词模板 | ||
| 生成 | ✓ | 聊天模型 | 据上下文作答(如 ark-code-latest) |
说明:✓ 表示该环节需要模型;⍻ 表示仅特定做法需要(语义切分、向量检索要嵌入模型)。
普通字符/递归切分、纯关键词检索不用模型;重排为可选环节,启用时才调用 Rerank。
可记三条边界:
ark-code-latest这类聊天模型 不能 当嵌入,也 不能 当 Rerank。- 嵌入模型负责「向量相似度召回」;Rerank 负责「问题与文档成对打分」。
- 语义切分、向量检索、离线入库,共用同一嵌入模型与同一向量维度。
本地还是在线
嵌入与 Rerank 多数情况优先在线 API(如硅基流动);只有隐私、内网或大规模成本有硬约束时再上本地。
| 场景 | 更合适 |
|---|---|
| 学习、原型、流量不大 | 在线 |
| 语料/问题敏感、不能出内网 | 本地或私有化部署 |
| QPS 很高、长期 API 更贵 | 本地(最好有 GPU) |
| 本机只有 CPU、要快速跑通 | 在线 |
嵌入和 Rerank 都是短文本、可批量的推理:在线开通快,模型名与维数也好对齐。
本地要扛模型体积、显存或内存与运维,收益主要在隐私与高流量时的单位成本。
常见开源模型体量(半精度权重粗算):
| 类型 | 例子 | 参数量 | 磁盘约 |
|---|---|---|---|
| 嵌入(小) | bge-small、all-MiniLM-L6-v2 |
几千万级 | 几十~200 MB |
| 嵌入(常用) | BAAI/bge-m3 |
约 0.57B | 约 2 GB |
| Rerank(小) | ms-marco-MiniLM-L6-v2 |
约 22M | 约 100 MB |
| Rerank(常用) | BAAI/bge-reranker-v2-m3 |
约 0.57B | 约 2 GB |
| Rerank(更大) | Qwen3-Reranker-4B/8B 等 |
数 B | 数 GB~十余 GB |
推理显存通常大于权重体积(还与 batch、序列长度有关);仅 CPU 也能跑中等模型,但延迟往往明显高于 GPU 或在线 API。
本地至少按「模型体积 + 余量」准备内存或显存。
聊天模型可继续用在线(如 Coding Plan);嵌入 / Rerank 不必与聊天同一家服务。
无论在线还是本地,入库与检索必须同一套嵌入模型。
本系列演示默认在线;生产再按上表选型即可。
重排序位置
向量召回追求覆盖,Top-K 里常有「语义近但答非所问」的块。
重排序接在 检索之后、拼上下文之前:先取较大 k(如 10~20),再用 Rerank 压到 top_n(如 3~5)再生成。
概要阶段代码仍可只做「检索 → 生成」;上线噪声大时再加精排。
实现见《LangChain 11:检索重排序》。
索引入库
概要阶段用内存语料即可;真实项目把切分结果换成 Loader + Splitter 的产物。
本地演示用 InMemoryVectorStore + DeterministicFakeEmbedding(相同文本得到相同向量,便于抽查检索)。
下面完成切分、嵌入与建库,并抽查一次相似度检索。
1 | from langchain_core.embeddings import DeterministicFakeEmbedding |
DeterministicFakeEmbedding 只保证链路与「同文同向量」可测,不保证真实语义检索质量。
上线请换成真实嵌入模型(见下文「嵌入注意」)。
最小问答链
固定「先检索再生成」时,用 LCEL 把 retriever、提示词与模型串成链即可。
此处只用到 聊天模型;检索侧演示仍用假嵌入。as_retriever 把向量库变成可 invoke(问题) 的检索器。
1 | import os |
提示词里写清「仅根据上下文」,可降低模型脱离语料胡编的概率(不能完全消除)。
若要在链中插入重排,把 retriever | format_docs 换成「召回 → Rerank → format」即可。
Agent 检索
需要聊天模型自行决定「要不要查库、查什么」时,把检索封成 @tool,交给 create_agent。
这是常见的 Agentic RAG 形态:多工具、多轮追问时更灵活。
这里工具内部做向量检索;需要精排时在 search_knowledge 里先召回再 Rerank。
1 | import os |
LCEL 链适合固定流水线;Agent 适合「检索 + 计算 + 其它 API」混用。
工具 docstring 要写清楚何时调用,否则模型可能跳过检索。
嵌入注意
聊天模型与嵌入模型是两套能力:ark-code-latest 不能当嵌入用。
生产环境用 init_embeddings 按厂商文档选择嵌入模型名,并继续走兼容的 api_key / base_url(若该端点支持嵌入)。
示意(模型名请换成你账号已开通的嵌入模型):
1 | import os |
若 Coding Plan 端点暂不提供嵌入,可改用其它已开通的嵌入服务,或本地 sentence-transformers 等方案;向量维度须与库中已有索引一致。
扩展
上线前可按优先级补强,本文不展开实现。
- 语料:Loader 读真实文件;切分参数按召回效果调(见《LangChain 07:文档加载器》《LangChain 08:文本切分器》)。
- 元数据:保留
source/ 页码,答案中引用出处。 - 检索与重排:
k、相似度阈值、混合检索,以及 Rerank 精排(见《LangChain 11:检索重排序》)。 - 评估:固定问答集看命中率与幻觉率,而不是只看单次 demo。
- 更新:文档变更后的重建或增量索引策略。
验证
按下面顺序确认概要链路可用。
- 配置
.env,跑「索引入库」,应打印与 RAG 步骤相关的片段。 - 跑「最小问答链」,答案应提到加载、切分、向量化、检索等要点;若提示词或语料写了重排,也可出现。
- 跑「Agent 检索」,消息历史中应出现工具调用,最终回答仍依据语料。
总结
- RAG = 离线(加载 → 切分 → 嵌入 → 入库)+ 在线(检索 → 可选重排 → 增强 → 生成)。
- 必用模型:离线/检索侧的嵌入、在线的聊天;可选 Rerank;加载、普通切分、入库、拼提示词一般不用模型。
- 嵌入与 Rerank 多数优先在线 API;隐私/内网或高 QPS 再上本地;入库与检索须同一套嵌入模型。
- 固定流程用 LCEL +
retriever;要模型自主查库用create_agent+ 检索 Tool。 - 演示可用假嵌入 + 内存库;上线换真实嵌入,并与聊天、Rerank 分开配置。
- 下一步按序看《07 文档加载器》《08 文本切分器》,再进入嵌入、Milvus 与重排专文。