1. 为什么AI Agent需要一条“知识管道”——先搞清RAG在解决什么问题
做Agent项目做到第三篇、第四篇的朋友,基本都已经摸过大模型的脾气了:你问它“今天北京天气怎么样”,它能答得滴水不漏;你让它基于你们公司最新的《采购管理制度》回答一个问题,它就开始一本正经地胡说八道。原因不复杂——模型的知识停在训练数据截止的那一刻,公司内部制度、产品手册、私有数据,它压根没见过。
这就是Agent落地时绕不开的“知识天花板”。而目前最成熟、最务实的破局方案,就是RAG(Retrieval-Augmented Generation,检索增强生成)。说白了,RAG就是给大模型配一个随时可更新的外部知识库:用户提问时,先从知识库中检索最相关的片段,再把片段和大模型能力组合起来生成答案。这样模型不用记住每一条细节,只需要学会“查资料+组织答案”。
这篇是“走进AI Agent”系列的第四篇,主题就是知识获取管道里的RAG基础。我会从管道架构、核心环节、落地实操到常见坑位完整过一遍,重点讲清楚“为什么这样设计”以及“实际做的时候哪里容易翻车”。适合三类人:一是正准备给Agent接入私有知识的开发者,二是做RAG项目但只停留在调用API层面的朋友,三是想系统理解Agent知识闭环、后续准备搞Agentic RAG的进阶学习者。
先给一个总体的判断:RAG不难,但很碎。它不像大模型推理那么玄学,反而是由一堆细节堆起来的工程问题——分块大小、向量化方式、检索策略、提示词组装,每个环节都在影响最终效果。很多人做了一个demo就跑来说“RAG没用”,往往不是RAG不行,而是哪个环节都没认真调。
2. 四段式管道:索引、检索、增强、生成的完整链路
2.1 索引阶段:把“死文档”变成“活数据”
RAG管道的第一步,是把散落的PDF、Word、Markdown、网页内容转成可检索的格式。这个过程叫索引(Indexing),很多人不重视,但它决定了整条管道的上限。
索引阶段有三个关键动作:加载、分块、向量化。
加载没什么可说的,就是处理不同格式的文档。真正需要动脑的是分块(Chunking)。一个大章节几百页,直接整块塞给模型做检索,有两个问题:第一,向量化模型有长度上限(比如常见的是512或1024个token),超长文本会被截断或降低质量;第二,查询通常只涉及文档的某一部分,整块返回会淹没真正的关键信息。所以必须把长文档切成语义尽量完整的短块。
分块不是“平均切”那么简单。我在实际项目里常用的策略是:优先按文档结构切,比如按照标题层级(#、##、###)来切分,尽量让每个块对应一个完整小节;如果文档没有清晰结构,再退回到按固定token数切分,并设置overlap(相邻块之间的重叠区域),一般重叠80到160个token比较好。这样能避免一句话在切分时被拦腰截断,导致语义残缺,后面检索时匹配不上。
分完之后就是向量化(Embedding)。这一步要把每个文本块转换成一组高维向量,让后续能够计算“语义相似度”。Embedding模型的选择非常关键,直接决定检索效果的上限。目前主流的选择包括OpenAI的text-embedding-3系列,以及各种开源模型如BGE、M3E、GTE等。国内用户如果做的是中文场景,BGE和M3E在中文语义理解上的表现通常比英文模型好不少,而且可以本地部署。选型的核心指标是MTEB榜单的检索任务得分,外加一个实际样本测试:拿你业务里真实的问答对去验证,而不是只看榜单数字。
2.2 检索阶段:从“什么地方都有”到“精准召回”
索引完成后,知识变成了一批向量躺在向量数据库里。用户来提问时,检索阶段要把query也向量化,然后去库里做相似度搜索,找出最相关的若干文本块。
这一步看起来就是“查一下”,实际牵涉的策略选择非常多。
首先是向量数据库的选型。我试过好几款,简单给个结论:中小规模项目用开源的Milvus、Qdrant、Weaviate都可以,如果项目已经用了Elasticsearch,直接用ES的kNN检索能力也完全够用;数据量只有几万条以内,甚至SQLite加sqlite-vec这种轻量方案就能跑。不用一开始就引入重组件,等数据量真上来了再迁移也不迟。关键看你的数据规模、并发量和部署方式,把这三件事想清楚再选,省心很多。
其次是检索策略。最基础的是向量检索,但它的短板很明显:它找的是“语义相似”,不是“词汇匹配”。如果你公司内部文档里把产品型号写成“GW-2000Pro”,用户问“那个2000瓦的pro版还在卖吗?”,向量检索可能匹配到一堆关于功率的段落,反而漏掉产品型号本身。这种时候就要引入混合检索:向量检索负责抓语义,BM25或全文检索负责抓词汇精确匹配,两路结果再做一个融合排序,效果会好很多。
检索阶段还有两个容易被忽视的细节:重排序(Rerank)和元数据过滤。
重排序的目的是解决“初召回够宽但不够精”的问题。先通过向量检索召回50条候选,再用一个专门的重排序模型(比如bge-reranker系列)对这50条做精细打分,只保留Top 5。这一步的效果提升非常明显,代价只是多一点计算时间,我强烈建议加上。
元数据过滤则是从源头排除干扰。比如你的知识库里有2019年到现在所有的产品手册,检索时可以指定“只查2025年版本”或“只查某条产品线”,避免旧版本信息混进答案。这个在构建知识库时就要有意识地为每个分块打上元数据标签。
2.3 增强与生成阶段:把检索结果组装成“有用的答案”
检索只是手段,回答才是产品。生成阶段要做的事,是把检索回来的片段和用户原始问题组装成一个上下文,交给大模型生成答案。
这里有个新手特别容易犯的错:以为把检索结果拼起来塞给模型就行。实际上,提示词的设计决定了模型是“在总结材料”还是“在回答问题”。
我实际用的提示词模板大概是这样的思路:
- 明确告诉模型:你只能基于提供的上下文回答问题,不得使用内部知识编造。
- 如果上下文中没有相关信息,必须明确说“根据现有资料无法回答”,而不是硬答。
- 展示检索回来的文本块时,带上来源编号或文档名,引导模型在组织答案时引用来源并保留线索。
- 对回答格式做约束,比如是否要分点、是否需要先给结论再给依据。
这样做的目的,是让模型的“幻觉”被结构性遏制。模型不是不会编造,而是在被明确限制且给了充足依据的情况下,更倾向于做“信息整理”而不是“自由创作”。一句话:提示词里写得越死,模型发挥空间越小,答案可控性就越强。
另外,做好答案溯源是一个工程项目的基本素养。很多RAG应用demo看起来“聪明”,但实际生产环境,用户需要知道答案是从哪份文档来的,不然出了问题没法追责。所以在生成阶段最好在返回结果里带上来源文档的标题、页码或链接,把“可信度”这件事实实在在做进产品逻辑里。
2.4 为什么是管道式的流程,而不是一步到位
刚接触RAG的人常常会问:为什么不直接把整个知识库丢给大模型,让它自己去翻?这就要说清楚一个事实:大模型的上下文窗口是有限的(就算几十万token的模型,塞满了长上下文之后,注意力也会分散,效果反而下降)。RAG的存在,本质上是用一个“先缩小范围、再深入阅读”的思路,让模型每次都只聚焦和问题高度相关的少量信息。就像你让一个实习生处理公司的知识库,你会让他先搜索相关文档,再看重点章节,而不是让他把几百个文档一口气看完再回答。RAG的管道式设计,正是把这种“先搜后读”的工作方式自动化了。
所以我一直不认同“有了长上下文,RAG就要被淘汰”的说法。长上下文解决的是“读得完”的问题,RAG解决的是“找得准”的问题。两者不是替代关系,而是互补关系。甚至在实际项目中,可以把RAG检索到的关键片段连同完整原文一起交给长上下文模型——前者保证精准,后者保证深度理解。
3. 实操:从零搭一个本地RAG管道
3.1 环境与工具选型:技术栈怎么组合最省心
这部分直接给一套我实测下来比较稳的本地RAG技术栈,适合一个人或者小团队快速落地:
- 语言与框架:Python + LangChain 或 LlamaIndex。LangChain生态最全,各种组件都有;LlamaIndex在文档索引和检索上做得更精细。如果是Java技术栈,可以考虑Spring AI,它在Java生态里对RAG的支持已经比较成熟了。
- Embedding模型:中文场景推荐BGE-M3或M3E-large。BGE-M3支持百种语言,而且做了长文本优化;M3E在中文语义匹配上表现很稳。小项目也可以先跑text2vec-base-chinese,零成本起步。
- 向量数据库:数据量小就用Chroma或SQLite-Vec,开发调试方便;数据量上来或者要上生产,换Milvus或Qdrant。
- 大模型组件:本地推理可以接Ollama跑Qwen系列,或者用开源框架vLLM做高性能服务化;对效果要求高、不介意API成本,直接接商业大模型也可以。
- 重排序模型:bge-reranker-v2-m3,体量不大,效果不错。
这个组合的好处是可替换性强,每个环节都留了升级空间。刚开始没必要追求“最强组件”,先把管道跑通,再逐步替换瓶颈环节。
3.2 分块参数怎么定:用实验数据说话,而不是拍脑袋
我这里有一部分实际测试数据可以参考。同样一份约50页的中文产品说明书(约3万token),我用了三种分块策略分别测试:
| 分块策略 | 平均块大小 | 块数量 | Hit Rate(命中率) |
|---|---|---|---|
| 固定512字符,无重叠 | 512 | 126 | 0.61 |
| 固定512字符,重叠128 | 512+128 | 118 | 0.73 |
| 按标题结构分块,重叠128 | 动态 | 96 | 0.81 |
可以看到,加了重叠之后命中率提升明显,原因在于:固定切分很容易把一句话拆到两块,搜索时如果用户正好问的是那半句话,向量相似度会大打折扣。而按标题结构分块,每一块本身就是一个语义完整的单元,匹配起来自然更准。
这里要提醒一下“chunk_size”和“overlap”的调法:建议先把chunk_size控制在embedding模型编码上限的一半左右,比如模型支持512 token,那分块在256到300 token比较保险;overlap取chunk_size的15%到30%。在实际项目中,我会先跑一轮测试,把命中率低于0.7的查询样例拿出来人工分析,看是分块问题、数据格式问题还是检索策略问题,再针对调。调参不是玄学,是不断看badcase的循环过程。
3.3 检索效果调优:从“召回了一堆”到“召回了对的”
我在前面说过,检索要三管齐下:向量检索 + 全文检索 + 重排序。这里展开讲一下实操细节。
基线的做法,是用Embedding模型把用户问题向量化,在向量库里做Top-K检索,K先设20。为什么是20?因为召回太窄容易漏,召回太宽后面重排序压力大。20是一个比较保守的起点,后续根据效果调整。
然后加入BM25全文检索,它擅长精确匹配,比如型号、人名、编号这类信息。BM25也有自己的Top-K,同样取20。接下来把两路的40条结果做合并去重,送入重排序模型逐条打分,最后取Top 5送入大模型生成。
这个三步组合的测试效果,我随便举一个业务场景:用户问“AW-300型号还有没有库存”,纯向量检索召回到的第1条和第3条是相关产品型号,但攻略性内容比较少;加入BM25后,含“AW-300”字样的精确匹配段落直接被拉高了排名;再经过重排序,前5条里至少有4条是直接相关的库存/型号信息。整条流程跑下来的Hit Rate,比纯向量检索高出了近20个百分点。
如果你在调优中遇到“检索结果看着相关但答案质量一般”的情况,大概率不是检索的锅,而是生成环节的提示词组装不够好。检索阶段的任务是“尽量给对的材料”,生成阶段的任务是“把材料用对地方”,两者要分开排查,别把问题混在一块儿。
3.4 从基础RAG到Agentic RAG:把检索变成Agent的工具
第四篇先不谈太深,但我觉得有必要把“Agentic RAG”提前点到,因为这是后续几篇会深入的方向。
基础RAG有一个明显的痛点:管道是固定的,用户问什么就检索什么,算法上是个单轮交互。但实际Agent场景中,用户的意图往往没那么单一——比如用户问“对比一下我们去年和今年的采购制度差异”,这时候你可能需要先检索出两份制度的全文,再分开对比,甚至要根据第一次检索结果决定下一步查哪一章。这就是Agentic RAG的雏形:写一个能“自主规划检索路径”的Agent,它可以根据初始结果判断信息是否够了,不够就发起第二轮、第三轮检索,甚至调用不同的知识源。
这种设计其实不复杂:把检索能力封装成一个工具(Tool),让Agent在规划阶段决定“要用这个工具”“连续用几次”。核心的困难在于设计“什么情况下停止检索并开始作答”的判定逻辑。我在一个合同审查Agent项目里实践过:先做一个初步检索,如果答案候选片段之间的符号冲突(比如不同年份的条款不一致),Agent就会触发第二轮定向检索,专门去找历次修订说明,直到冲突被澄清才输出最终结论。这样从“一次性问答”变成了“带自我检查的知识工作流”。
把这个概念放在心里即可。当前阶段,先把基础管道各环节做扎实,后面看任何Agentic RAG方案,都会觉得顺理成章。
4. RAG落地中的常见问题与排查实录
4.1 问题一:检索结果看着相关,答案却“张冠李戴”
这是最典型的RAG坑:向量检索召回的内容语义上接近,但细节张冠李戴。举个例子,你有一个知识库包含了公司两种非常相似的产品A和B,用户问A的保修政策,检索回来的Top 3里有两个是B的保修段落,模型一“综合汇总”,就回答出了B的信息。
排查思路:第一步,查看检索原始返回的Top 10内容,逐条人工判断是否把A和B混了。第二步,看embedding切分,是不是两个产品被放在同一个分块里,导致向量表达“平均化”了,这时要调整分块策略,让每个产品维度单独成块。第三步,检查分块元数据,如果没有给每个块打上“产品名”标签,那就补上,并启用元数据过滤——在用户提问的同时附带产品名的过滤条件,从源头错开。
一句话经验:RAG应用里,“召回噪声”远比“召回为空”更常见也更难搞。不要等到生成环节才想办法,要在检索环节就从机制上避免混入错误上下文。
4.2 问题二:Hit Rate(命中率)一直上不去,卡在0.5到0.6
Hit Rate是RAG评估里最核心的指标,意思是“检索结果中是否包含能回答问题的正确文档片段”。我见过不少团队,优化了很久代码,Hit Rate还是上不去,最后根因往往是数据质量。
排查顺序可以这样走:
- 先确认测试集的query和golden document是否匹配,是否有多义性描述。
- 再检查文档库本身:有没有扫描件、手写体、乱码表格、扫描PDF未OCR过,这些数据无论模型多好都救不回来。
- 接着看分块是否切碎了关键信息:一个完整表格被切成两半,半边内容谁也认不出来。
- 最后才去怀疑model embedding的质量,考虑替换模型。
说一个我踩过的例子:某个项目的知识库里有大量Excel导出的PDF表格,直接加载后表格内容被拆得七零八散。检索结果看起来每条都“沾边”,但每条都缺关键列。后来把表格先转成结构化的Markdown文本块再入库,Hit Rate从0.58一下子涨到0.77。数据清洗的收益,往往比调模型大得多。
4.3 问题三:多文档之间知识割裂,回答自相矛盾
当知识库中包含新旧版本、不同部门、甚至不同来源的冲突信息时,RAG的“拼接式回答”就会出现前后矛盾。比如旧制度说“报销须提供纸质发票”,新制度说“电子发票即可”,模型不分版本地抓取了两条,答案就崩了。
这个问题在基础RAG阶段很难彻底解决,只能通过元数据管理和版本控制来缓解。具体做法:每个分块都标记生效日期、文档版本、来源部门,检索时带上时间过滤。更进一步可以做“时效加权”:越新的文档在重排序时分数权重越高,让模型更倾向引用新信息。如果要彻底解决,就需要引入Agentic RAG里我没展开的推理判断逻辑——让Agent识别冲突,再做决断。这也是后面几篇的主要内容。
4.4 评价闭环:没有评测的RAG,等于没做RAG
最后我要强调评价体系。很多团队拿到RAG项目直接上手开发,调了几个参数觉得“还行”就交付了,结果用户一句“这答案不对”就把项目打回重做。RAG的工程化,必须从一开始就建设评测集和评估流程。
我的建议是:整理至少50条真实的业务问答对,每条要标注“检索答案应该在哪个文档、哪个分块里”。每次修改、调参之后,跑一遍评测集,用Hit Rate、MRR(平均倒数排名,衡量正确答案排在第几位)以及人工抽样回答质量三个指标来评估变化。不用追求一次性做到完美,但一定要形成“改动->评测->对比->再改动”的循环。评测集是可以持续扩充的资产,它让优化工作从“凭感觉”变成了“看数据”。
5. 从一个RAG项目到可复用的知识基础设施
做到这里,基础RAG管道本身已经能跑通了:从文档加载、分块、向量化、检索、重排序到生成回答,每一步都比较清晰。但如果眼光放远一点,你会发现RAG不应该只是一个“问答机器人”的附属品,它其实是在为Agent搭建一套可复用的知识基础设施。
什么意思呢?当你把企业里的制度、手册、FAQ、工单记录、产品文档全部结构化并接成RAG之后,上层可以长出很多应用:客服问答、内部知识检索、代码辅助、合同审核、营销文案生成……这些应用的底层共用同一套索引和检索管道。所以从第一周开始,就要把知识库当成“数据资产”来治理:统一的分块规范、统一的元数据标准、统一的版本管理机制。后面加新数据、接新场景,都会舒服很多。
在这个方向上,有一些更前沿的探索值得关注:GraphRAG把知识之间的显式关系建模成图结构,适合做多跳问题推理;Ontology RAG则在知识库层面引入本体定义,用领域实体和关系约束来提升检索的语义精度。这些都不是基础RAG的对立物,而是它的自然演进——先把基础管道做扎实,再按业务需要引入更复杂的知识表示方式。
我个人这几年做Agent相关项目最大的感触是:AI Agent的能力上限,不取决于模型参数的多少,而取决于它“够得着”的知识质量和规模。RAG就是那根够得着的竿子。把这根竿子立稳了,Agent才能站在上面爬得更高。
最后分享一个实操中的小技巧:搭建RAG环境时,可以把整个管道拆成几个独立的微服务,用API暴露——检索、重排序、生成各司其职。这样每次优化某个环节,不需要牵动整条链路的重启,也方便将来在Agent里通过工具调用来组合使用。这部分在后面的Agentic RAG篇里还会再展开讲,到时候你就会明白,现在花时间做管道模块化,绝对不亏。