1. 为什么知识获取管道是 AI Agent 落地的第一道坎
做 AI Agent 的人,绕不开一个尴尬的现实:模型本身很聪明,但它不知道你公司内部的报销制度、不知道你手上这份设备手册的第三章写了什么、更不知道上周客户在群里反馈的那个故障最后是怎么解决的。你让它直接回答,它要么一本正经地胡说,要么礼貌地告诉你"我无法获取实时信息"。这不是模型不行,而是它的知识边界被训练数据锁死了。
知识获取管道要解决的就是这件事——把外部知识在合适的时机、以合适的形态喂给模型,让它回答问题时"有据可依"。而RAG(检索增强生成)就是目前最主流、工程上最成熟的一条管道实现路径。它的核心思路朴素到一句话就能说清:先去知识库里把相关内容捞出来,再把捞出来的内容和用户问题一起塞给模型,让模型基于这些材料作答。
我见过太多团队在 Agent 项目上栽跟头,不是栽在模型选型,也不是栽在工具调用,而是栽在这条管道上。管道没搭好,Agent 就像个记性差又爱编话的实习生,你越信任它,它坑你越狠。所以我把 RAG 放在"走进 AI Agent"系列的第四篇,因为它是从"能聊天的 Demo"迈向"能干活的产品"之间那道必须跨过去的门槛。
这篇内容适合三类人:一是刚接触 Agent、想搞明白 RAG 到底是什么的开发者;二是已经用过现成知识库产品、但想自己掌控整条链路的工程师;三是被"检索不准、答非所问"折磨过、想找到瓶颈到底在哪的实践者。我会从管道的每一段拆开讲,把稠密嵌入、向量检索、切分策略、重排这些关键环节的原理和坑都摊开说,最后给出一套可以直接抄的落地思路。
需要先明确一个认知:RAG 不是一个库、不是一个框架,而是一条数据流水线。它有两段完全不同的生命周期——离线阶段的"知识入库"和在线阶段的"检索生成"。很多人把这两段混在一起理解,结果调优时完全找不到方向。下面我们就把这两段彻底拆开。
2. 把 RAG 拆成两段流水线:离线入库与在线检索
2.1 离线入库:知识是怎么变成"可检索"的
离线阶段的目标只有一个:把各种格式的原始知识(PDF、Word、网页、数据库记录、工单系统)转化成一种机器能快速比对相似度的形态——向量。这个过程通常叫"索引构建"或"知识入库"。
完整链路大致是这样:文档加载 → 文本切分 → 稠密嵌入 → 写入向量库。每一步都有讲究,我逐个说。
文档加载看着简单,其实是最脏的一步。PDF 里的表格、双栏排版、页眉页脚、扫描件 OCR 残留,都会污染后续切分。我的经验是,加载阶段就要做清洗:去掉重复页眉页脚、把表格转成结构化文本、把跨页断开的段落合并。这一步偷懒,后面检索再准也白搭,因为垃圾进必然垃圾出。
文本切分是 RAG 里最被低估的环节。切太大,一个 chunk 里混了好几个主题,嵌入向量变成"四不像",检索时谁都匹配不上;切太小,一句话被拦腰截断,语义不完整,模型拿到手也拼不出完整答案。业界常见的做法是按语义边界切分,比如按标题层级、按段落、按句子,再配合一个重叠窗口(overlap)防止边界信息丢失。我一般会把 chunk 控制在 300 到 800 个 token 之间,重叠 10% 到 15%,具体数值要拿真实问题去测。
稠密嵌入是把文本变成向量的核心步骤。所谓"稠密",是相对于传统的稀疏表示(比如 TF-IDF、BM25 那种高维稀疏向量)而言的。稠密嵌入模型会把一段文本压缩成一个几百到几千维的实数向量,语义相近的文本在向量空间里距离就近。这就是为什么用户问"怎么报销差旅费",能检索到标题写着"费用申请流程"的文档——字面不一样,但语义对上了。
写入向量库是最后一步。向量库负责存储向量并支持高效的相似度检索,常见的有 FAISS、Milvus、Qdrant、pgvector 等。选型时重点看三件事:数据规模、是否需要持久化和过滤、团队运维能力。小规模验证用 FAISS 足够,生产环境要考虑并发、增量更新和元数据过滤。
2.2 在线检索:用户提问后发生了什么
在线阶段是用户能感知到的部分,链路是:查询改写 → 查询嵌入 → 向量检索 → 重排 → 拼装上下文 → 生成回答。
查询改写经常被忽略,但价值极高。用户的问题往往口语化、指代不清、缺上下文。比如多轮对话里用户只说"那它呢",直接拿去检索必然翻车。常见做法是用模型把问题改写成独立、完整、适合检索的查询,或者生成多个查询变体并行检索再合并结果。
查询嵌入用的是和入库时同一个嵌入模型,这点必须强调。换了模型,向量空间就对不上,检索结果会完全错乱。这是新手最容易犯的错之一。
向量检索就是拿查询向量去库里找最相似的 Top-K 个 chunk。K 取多少?太小可能漏掉关键信息,太大则引入噪声、拖慢生成。我通常先取 20 到 50 个候选,交给下一步重排去筛。
重排是提升精度的关键一招。向量检索是"粗筛",速度快但精度有限;重排模型(reranker)会对候选做更精细的相关性打分,把真正有用的排到前面。实测下来,加了重排之后,Top-3 的命中率往往能提升一截,尤其是知识库内容相近、容易混淆的场景。
拼装上下文是把筛出来的 chunk 按一定顺序塞进提示词。这里要注意 token 预算,别把上下文塞爆。生成回答则是让模型基于这些材料作答,并尽量要求它标注来源、不确定时明确说不知道。
把这两段流水线理解透,你就有了排查问题的地图:检索不准,先看切分和嵌入;答非所问,先看重排和上下文拼装;答得慢,先看检索规模和模型调用次数。
3. 稠密嵌入到底在做什么:从语义相似度说起
3.1 向量空间里的"距离"就是语义的"远近"
很多人第一次接触嵌入会懵:凭什么一段文字能变成一个数组,数组之间的距离还能代表意思像不像?我用一个生活化的类比解释。
想象一个巨大的地图,地图上每个点代表一句话。意思相近的句子,比如"如何申请年假"和"休假流程怎么走",会被放在地图上相邻的位置;意思无关的句子,比如"今天天气不错",会被放到很远的地方。嵌入模型干的事,就是训练出一个"摆放规则",让所有句子按语义被摆到这张地图上。这个地图的坐标维度可能是 768 维、1024 维甚至更高,人脑想象不了,但数学上完全成立。
训练这个"摆放规则"的过程,本质是让模型学会:语义相似的文本对,向量要靠近;语义无关的文本对,向量要远离。常用的对比学习就是干这个的。所以嵌入模型的质量,直接决定了你的知识库"摆放"得合不合理。
3.2 稠密嵌入和稀疏检索的分工
传统检索(BM25 这类)靠的是词频和逆文档频率,本质是关键词匹配。它的优点是精确、可解释、对专有名词和编号特别敏感。缺点是遇到同义词、改写、口语化表达就歇菜——用户问"笔记本开不了机",文档写的是"便携计算机无法启动",BM25 基本匹配不上。
稠密嵌入恰好补上这块短板,它抓的是语义。但稠密嵌入也有软肋:对精确的编号、型号、代码这类"字面必须一致"的内容,反而不如关键词检索稳。
所以现在主流的做法是混合检索:稠密向量检索 + 稀疏关键词检索,两路结果融合。融合方式常见的有加权求和、倒数排名融合(RRF)等。我在实际项目里几乎默认上混合检索,尤其是知识库里既有自然语言描述、又有大量型号编号的场景,纯向量检索的召回率经常不够看。
3.3 嵌入模型选型的几个现实考量
选嵌入模型不能只看榜单分数,要结合你的实际场景。我总结几个维度:
| 考量维度 | 说明 | 我的建议 |
|---|---|---|
| 语言支持 | 中文、英文、多语言能力差异大 | 中文场景优先选中文优化过的模型 |
| 向量维度 | 维度越高表达力越强,但存储和检索成本越高 | 768 到 1024 维是常见平衡点 |
| 最大输入长度 | 决定单个 chunk 能多长 | 要和你的切分策略匹配 |
| 推理成本 | 本地部署还是调用服务 | 数据敏感就本地,追求效果可调服务 |
| 领域适配 | 通用模型在专业领域可能不够准 | 医疗、法律、工业可考虑微调或领域模型 |
提示:嵌入模型一旦选定并完成入库,后续更换意味着全量重新嵌入。所以选型要在项目早期定下来,别等知识库几十万条了才想换。
还有一个常被忽略的点:查询和文档要用同一个模型,但有些模型区分"查询侧"和"文档侧"的编码方式。用错侧,效果会明显下降。接入前一定看清模型文档的用法说明。
4. 切分策略:决定 RAG 上限的隐形之手
4.1 为什么切分比模型更影响最终效果
我做过一个对比实验:同一份知识库、同一个嵌入模型、同一套检索参数,只改切分策略,Top-5 命中率能差出二十多个百分点。这个差距比换一个更强的嵌入模型带来的提升还大。原因很简单——切分决定了"检索的最小单元",单元切得不对,后面所有环节都在错误的基础上工作。
举个具体例子。一份产品手册里有一段讲"故障代码 E102 的处理方法",如果切分时把标题和正文切散了,检索时用户搜"E102 怎么处理",可能只召回标题"故障代码列表"或者只召回正文"检查电源模块",两者都不完整。模型拿到残缺信息,回答自然残缺。
4.2 几种切分策略的适用场景
固定长度切分最简单,按 token 数硬切,配个重叠窗口。优点是实现快、chunk 大小均匀;缺点是经常在句子中间切断,语义破碎。适合结构混乱、没有明显层级的文本。
递归字符切分是很多框架的默认策略,按分隔符优先级(段落 → 句子 → 词)递归尝试,尽量在自然边界切。比固定长度好,但对复杂结构仍然力不从心。
语义切分用嵌入相似度判断相邻句子是否属于同一主题,主题变了就切。效果通常最好,但计算成本高,适合对精度要求高的场景。
结构化切分是我最推荐的方式:如果文档本身有标题层级、章节结构,就按结构切,把标题路径作为元数据带上。这样每个 chunk 都自带"上下文坐标",检索时还能按章节过滤。Markdown、HTML、带书签的 PDF 都适合这么干。
4.3 元数据:让 chunk 不只是文本
切分时顺手把元数据抽出来,是性价比极高的操作。常见的元数据包括:来源文件、章节标题、页码、更新时间、文档类型、权限标签。这些信息在检索阶段能派上大用场——可以按时间过滤掉过期文档,可以按权限过滤掉用户无权查看的内容,可以在回答里标注来源让用户核对。
我踩过的一个坑:早期做知识库没存页码,结果用户追问"这条规定在哪一页",系统答不上来,体验直接打折。后来补上页码和章节路径,回答里能精确引用,用户信任度明显提升。
注意:元数据过滤要在检索阶段就生效,而不是检索完再筛。先检索一大把再过滤,既浪费算力又可能把真正相关的结果挤掉。
5. 检索环节的调优:从召回率到命中率
5.1 召回和精排是两件事
很多人把"检索"当成一个动作,其实它是两个阶段:召回负责"别漏",精排负责"别错"。召回阶段追求高召回率,宁可多捞一些候选;精排阶段追求高精度,把真正相关的排到最前。
召回用向量检索或混合检索,Top-K 设大一点,比如 30 到 50。精排用重排模型,把候选重新打分,取前 3 到 5 个交给生成。这个"先宽后严"的思路,是提升 RAG 命中率最有效的手段之一。
5.2 重排模型为什么值得加
重排模型(reranker)通常是交叉编码器结构,它把查询和候选文档拼在一起输入模型,直接输出相关性分数。相比向量检索的"双塔"结构(查询和文档分别编码再算距离),交叉编码器能看到查询和文档之间的细粒度交互,判断更准。
代价是慢——它要对每个候选单独跑一次模型,没法像向量检索那样预先建索引。所以它只适合对少量候选做精排,不适合做全库召回。这个分工要拎清楚。
实测经验:候选 30 个、重排取前 5 个,是很多场景下的甜点区。候选太少重排没意义,候选太多重排耗时明显。
5.3 命中率上不去的常见原因排查
检索命中率低,别急着换模型,先按这个顺序排查:
- 切分是否合理:chunk 里是不是混了多个主题,或者语义被切断。
- 嵌入模型是否匹配语言和领域:中文场景用了英文模型,效果必然打折。
- 查询是否被正确改写:多轮对话里的指代有没有消解。
- 是否该上混合检索:纯向量在关键词敏感场景召回不足。
- 是否该加重排:召回对了但排序不对,重排能救。
- 元数据过滤是否误伤:过滤条件太严把相关文档排除了。
这个排查顺序是从"数据层"到"模型层"再到"策略层",先解决根本问题,再考虑换更强的模型。我见过太多人一上来就换模型,结果切分问题没解决,换了也白换。
6. 生成阶段:让模型基于材料说话而不是自由发挥
6.1 提示词里怎么摆材料
检索到的 chunk 怎么塞进提示词,直接影响生成质量。我的做法是:每个 chunk 前面标注来源编号,正文按相关性从高到低排列,最后明确要求模型"只基于以上材料回答,材料中没有的信息要说明无法回答,并尽量标注引用编号"。
顺序也有讲究。有研究表明,把最相关的材料放在开头和结尾,模型利用得更好,中间位置容易被忽略。所以别简单按检索分数顺序堆,可以把最强的放两头。
6.2 抑制幻觉的几条硬规矩
RAG 的一大卖点就是减少幻觉,但如果提示词写得松,模型照样会自由发挥。几条我验证有效的规矩:
- 明确告诉模型"材料之外的内容不要编"。
- 要求模型在不确定时输出"根据现有资料无法确定",而不是硬答。
- 要求标注引用来源,方便用户核对。
- 对关键结论,可以让模型先复述材料原文再给结论。
这些规矩不能百分百消除幻觉,但能显著降低。尤其是"标注来源"这条,既提升可信度,又倒逼模型别乱说。
6.3 上下文长度和成本怎么平衡
塞的 chunk 越多,上下文越长,成本和延迟越高,而且噪声也越多。我的经验是:质量优先于数量。与其塞 10 个半相关的 chunk,不如塞 3 个高度相关的。重排就是为了帮你做这个取舍。
如果确实需要长上下文,可以考虑把多个 chunk 先做一次"压缩摘要",再喂给生成模型。这样既保留信息,又控制长度。不过压缩本身也可能丢信息,要权衡。
7. 一套可以直接抄的 RAG 落地骨架
7.1 最小可用版本的搭建顺序
如果你要从零搭一个 RAG,我建议按这个顺序推进,每一步都能独立验证:
- 先跑通单文档问答:拿一份结构清晰的文档,做切分、嵌入、检索、生成,端到端跑通。
- 加元数据和来源标注:让回答能引用出处。
- 上混合检索:补上关键词召回这一路。
- 加重排:提升 Top-K 精度。
- 加查询改写:支持多轮对话和口语化提问。
- 做评测集:收集真实问题,建立命中率和答案质量的评估标准。
这个顺序的好处是,每一步都有明确的收益,出问题也容易定位是哪一步引入的。
7.2 评测:没有评测就没有调优
RAG 调优最大的敌人是"感觉好像好了一点"。必须建评测集。我的做法是收集 50 到 200 个真实用户问题,人工标注每个问题的正确答案和应该命中的文档片段,然后量化两个指标:检索命中率(正确片段有没有进 Top-K)和答案正确率(生成结果对不对)。
有了这两个指标,任何改动都能量化对比。换切分策略、换嵌入模型、加重排,到底有没有用,数据说话。这一步投入不大,但回报极高,是区分"玩票"和"做产品"的分水岭。
7.3 几个我踩过的坑
坑一:忽略文档更新。知识库不是建一次就完事,文档会更新、会新增。要设计增量入库机制,否则用户问的是新政策,系统答的是旧版本。
坑二:chunk 里丢了标题。切分时把标题和正文分开,导致正文 chunk 失去上下文。解决办法是把标题路径拼进 chunk 文本,或者作为元数据在检索时补回。
坑三:检索结果不去重。相邻 chunk 内容高度重叠,检索回来一堆相似内容,浪费上下文。可以在拼装前做去重或合并。
坑四:忽视权限。企业知识库往往有权限分级,检索时必须按用户权限过滤,否则会泄露敏感信息。这个要在元数据设计阶段就考虑。
坑五:只测 happy path。只测那些知识库里明确有答案的问题,忽略了"知识库没有答案时系统该怎么答"。后者恰恰是幻觉高发区,必须专门测。
8. 从基础 RAG 往 Agentic RAG 走的方向
基础 RAG 是"一问一检索一生成"的固定流程,简单可靠,但遇到复杂问题就力不从心。比如用户问"对比 A 产品和 B 产品在售后政策上的差异",一次检索很难同时捞全两边的信息。
Agentic RAG的思路是让 Agent 自己决定怎么检索:可以拆解问题、多次检索、判断检索结果够不够、不够就换个查询再检、甚至调用其他工具补充信息。这把 RAG 从"固定管道"变成了"可编排的能力"。
往这个方向走,几个关键能力要补:查询规划(把复杂问题拆成子问题)、检索结果评估(判断召回内容是否足够)、迭代检索(根据评估结果决定是否再检)、多源融合(向量库、图数据库、结构化数据库协同)。
这也是为什么现在很多人在讨论 RAG 和知识图谱结合、讨论 GraphRAG。本质都是想让知识获取管道更聪明,能处理实体关系和复杂推理,而不只是"找相似段落"。
不过我的建议是:别一上来就搞 Agentic RAG。基础 RAG 没跑稳,加再多编排也是空中楼阁。先把切分、嵌入、检索、重排这条基础链路打磨扎实,把评测体系建起来,再往上叠复杂度。我见过太多项目,基础检索命中率还不到六成,就急着上多路召回和 Agent 编排,最后问题越堆越多,根本不知道是哪一层出的错。
知识获取管道这件事,说到底是个工程活,不是模型活。模型会越来越强,但管道设计的基本功——怎么切、怎么嵌、怎么检、怎么评——是绕不过去的。把这些基础打牢,后面无论技术怎么演进,你都能快速接上。