
做 Agent 做到这个系列第四篇终于轮到许多朋友最关心的知识获取问题了。之前几篇聊过 Agent 的规划、工具调用、记忆但大家动手搭 Agent 时最容易卡住的反而是另一件事模型推理再强它依然不知道你们公司内部的业务细节。前阵子有个朋友让我帮看他的客服 Agent问产品手册里的型号参数时总是胡编比如问“XX-200 的防护等级是多少”模型能一本正经给出一个根本不存在的数据。我一看问题根本不在推理而在知识获取管道是断的。到今天为止AI Agent 的知识获取最成熟、最通用的方案仍然是 RAG全称 Retrieval-Augmented Generation检索增强生成。这篇文章就把 RAG 基础拆开讲透它到底解决什么问题、索引阶段怎么做、检索阶段怎么调、怎么接到 Agent 工作流里再加上我实际跑项目时踩过的坑。适合正准备做知识库问答 Agent、或者已经照着网络 Demo 跑通但效果不理想的开发者。1. 大模型答不好领域问题不是因为它笨而是因为“没资料”1.1 知识过期、幻觉、无法溯源本质上是一场闭卷考试你可以把大模型想象成一个读过很多书、但记性不稳定的考生。平时你问它常识性问题它答得头头是道因为那些知识在训练阶段见过。可一旦你问的是“我们 2025 年 Q3 的价格表”“内部合同编号规则”“设备维护手册第七页的参数”它就傻眼了。原因很直接这些内容根本不在它的训练数据里或者只存在于某个隐蔽角落但早就过时了。这就解释了幻觉为什么必然发生——模型面对不知道的问题最自然的反应是“编一个看起来合理的答案”因为它的训练目标就是生成连贯文本而不是承认自己不知道。你如果不给它参考资料它就只能闭卷硬答。所以很多人以为是 prompt 写得不够好拼命加“请不要胡说”之类的约束效果依然有限。真正的问题不是态度而是信息源。RAG 的思路是把它从闭卷考试变成开卷考试。系统先从一个外部知识库里检索出与问题相关的文档片段再把这些片段拼到上下文里让模型基于这些资料作答。这样做有三层价值知识可以随时更新不用重训模型回答有出处能溯源幻觉发生的概率大幅下降因为模型是被“喂着答案”答题的。1.2 RAG 和微调怎么选先做管道再做“性格调教”很多人一提到“让模型懂业务”第一反应就是微调Fine-tuning。我在社群答疑时经常遇到这种思路但说实话大多数场景下微调并不是第一步。把两者放在一张表里对比选择就会很清楚维度RAG微调知识更新改文档、重索引即可分钟级生效需要准备训练集、重新训练周期以天计幻觉问题显著缓解因为生成有上下文依据缓解有限模型仍可能凭记忆发挥溯源能力天然支持可以指出引用来源很难回答“你从哪学来的”数据量要求几十篇文档就能见效通常需要大量高质量问答对成本主要是向量检索资源和 Prompt Token 开销训练和推理部署成本高我的结论是领域知识优先用 RAG微调更适合做“性格调教”比如让模型固定输出格式、模仿某种语气或者把特定行业的表达习惯内化进模型。你甚至可以两者结合但顺序一定是先建 RAG 管道把检索做扎实再考虑要不要微调。1.3 RAG 在 AI Agent 中的定位知识获取管道在 AI Agent 的整体架构里RAG 不是独立单点而是一条标准的知识获取管道。它和普通 API 工具有一个本质区别API 工具返回的是直接可执行的结果而 RAG 的检索结果只是“参考资料”最终还要交给模型去阅读、理解、归纳成答案。你可以把它理解成 Agent 团队里配了一个“内部资料管理员”。Agent 是那个负责分析问题、制定计划的项目经理它手里的工具列表里有文档搜索、数据库查询、代码执行等技能其中“知识检索”就是 RAG 服务。当项目经理发现用户的问题涉及公司内部知识时就向资料管理员说“帮我查一下相关材料”拿到资料之后再决定怎么组织答案。这个比喻也解释了为什么 RAG 在 Agent 里最自然的接入方式是工具调用而不是写死在主流程里后面我会专门展开。2. 索引阶段让文档变成 Agent 能“读懂”的向量记忆2.1 文档接入先解决“数据能不能被正确解析”RAG 管道的第一步不是向量化而是把文档变成干净、结构化、可检索的文本。这一步被很多人跳过了网络教程通常直接拿现成的 txt 文件演示但真实项目里全是 PDF、Word、网页、表格甚至扫描图片。我踩过的第一个坑就是扫描版 PDF。某些设备手册是扫描图转成的 PDF文字根本不存在直接解析出来是一堆空白。当时我没检查结果 80% 的检索结果都是垃圾。正确处理方式是先做 OCR用 PaddleOCR 或 Tesseract 把图片转成文字再进管道。另外一个常见问题是表格。Word 里的表格如果按普通文本抽取行列关系全丢检索时会把表头和表体拆开。我现在的习惯是解析阶段优先考虑版面分析工具比如 Unstructured 或者 PyMuPDF 抽取结构表格尽量转成 Markdown 格式保留语义网页内容则要抓正文主体把导航、广告、版权信息全部过滤掉。这一阶段花的时间可能占整个项目的 40% 以上但非常值得。因为 RAG 的上限由文档质量决定解析不干净后面所有调优都是给一栋歪楼装修。2.2 切分chunk 太小没上下文太大有噪声文本解析完之后不能整篇塞给模型因为大模型上下文窗口虽然越来越大但向量检索的输入长度和相关性精度都有上限。切分Chunking是决定 RAG 精度的重要关口。先讲参数含义。chunk_size 是每个切块的最大长度比如 512 tokensoverlap 是相邻块之间的重叠长度比如 50 tokens。为什么要重叠因为文档在切分处可能被拦腰截断比如一个段落讲到一半被切开后半块缺少前文的主语检索到它时模型看不懂。重叠能在一定程度上保留上下文连续性。更重要的其实是“怎么切”。我强烈建议不要无脑按固定长度切而是按语义结构切。Markdown 标题感知切分是性价比最高的按章节、小节边界切如果某节内容太长再递归切大块。LangChain 的 RecursiveCharacterTextSplitter、LlamaIndex 的 SentenceSplitter 都支持这种思路。如果文档里有代码块、表格、列表也要尽量把它们作为完整单元保留。切分方式优点缺点适用场景固定字符切分简单、快容易切断语义纯文本、无结构内容递归字符切分保留常见边界对复杂文档仍会误切通用默认选择标题/段落感知切分保留章节语义需要文档结构清晰Markdown、技术文档语义切分按语义边界切效果好计算成本高对质量要求高的场景中文场景还有个细节token 计算方式不同。中文一个 token 通常对应一到两个汉字如果你按英文文档的习惯把 chunk_size 设成 1024实际切出来的中文块会比想象的大很多。我通常从 300 到 500 tokens 开始试再结合手动观察结果调整。2.3 Embedding 选型中文场景别乱用模型切分完的文本要变成向量这一步靠 Embedding 模型。Embedding 的作用是把一段文本映射成高维向量让语义相近的文本在向量空间里距离更近。模型选型对 RAG 效果的影响非常大而且没有免费的“通用最优解”。常见的选项有这些。OpenAI 的 text-embedding-3-small 是英文场景的默认选择但直接用在中文上效果一般中文场景建议用专门优化过的模型比如 bge-m3、bge-large-zh、gte-Qwen2 系列。bge-m3 是目前中文社区用得最多的一个支持最长 8K 输入多语言效果好而且有现成的本地部署方案。如果你对数据安全有要求或者文档涉及敏感信息本地部署 embedding 模型是更稳妥的做法。这里有一个很容易被忽略的原则查询侧的文本和文档侧的文本要用同一个 embedding 模型。很多人会把用户输入的 Embedding 和服务端文档的 Embedding 用不同模型生成导致相似度计算在语义空间里“牛头不对马嘴”。另外向量维度也不是越高越好维度高的模型匹配效果更好但存储和计算成本都上去了很多项目 1024 维已经够用。2.4 向量数据库选型从 Chroma 到 Milvus按场景定Embedding 生成的向量需要一个地方存起来并支持检索这就是向量数据库的活。选型直接看你的项目阶段不必一步到位上重型系统。我自己的经验是练手项目直接用 Chromapip install 就能跑几十行代码完成入库和检索非常适合跑通流程。原型验证阶段可以用 FAISS它是内存索引速度快但数据量大了之后持久化和集群能力不行。如果你的团队已经有 PostgreSQL想省一个中间件pgvector 是个务实选择它在现有数据库里加一个向量列就能用。生产级场景再考虑 Milvus、Qdrant 或 Elasticsearch这几个支持高并发、丰富的过滤条件和混合检索。这里重点提一下 Elasticsearch。很多人对它的印象停留在“全文搜索引擎”但新版 ES 自带向量检索可以同时支持 BM25 关键词检索和 KNN 向量检索。这对 RAG 项目太重要了因为实际开发中你会发现“关键词匹配”和“语义匹配”缺一不可。关于混合检索下一章细说。我的建议是先别沉迷选型用 Chroma 把整条链路跑通确认业务瓶颈到底在检索精度、并发量还是运维复杂度再决定要不要换库。过早引入重系统只会拖慢开发节奏。3. 检索阶段命中率才是衡量知识管道的硬指标3.1 向量检索的原理和一个关键误区索引建好之后查问题时就进入检索阶段。流程是把用户的问题也用同一个 Embedding 模型转成向量在向量数据库里找距离最近的 Top-K 个文档块通常用余弦相似度作为距离度量。说白了就是高维空间里找“邻居”。但这里有一个关键误区向量检索不等于万能语义理解。它对专有名词、编号、型号、人名这类信息并不敏感。比如用户问“那个额定电流 3A 的型号是什么”文档里写的是一个设备参数且整段没有直接出现完整的“3A 型号”这样的字符串纯向量检索很可能召回一堆“电流”相关但不相关的段落。反过来如果用户直接说“XX-200 的防护等级”向量模型可能识别了 XX-200 和防护等级但如果你同时有大量相似型号的文档片段它们之间的向量距离其实很接近相似度就分不开。这也是为什么很多项目“照着教程跑通了效果却很一般”——教程里的 demo 问题是“什么是 RAG”这种大而泛的问题向量检索能轻松命中。但真实业务问题往往是精确、指代性强的这时候单靠向量相似度就露怯了。记住一句话向量检索负责语义泛化关键词检索负责精确匹配两者要互补。3.2 Hit Rate 怎么算为什么它直接决定 RAG 上限聊 RAG 效果首先得有个量化的尺子。Hit Rate命中率是我看的第一指标定义是在测试集里标准答案对应的文档块是否出现在检索返回的 Top-K 结果中出现则计为命中总体命中的比例就是 Hit Rate。举例来说你准备了 100 个“问题-答案文档块”组成的测试集检索时每条取 Top-5如果 100 条里有 80 条在 Top-5 中能找到标准答案块那么 Hit Rate 就是 80%。之所以说它决定 RAG 上限是因为检索都没命中生成模型再强也只能瞎编后面无论怎么调 prompt 都救不回来。反之如果命中率已经 95% 以上你就可以把优化重心放到生成端比如控制格式、减少冗余而不是继续调检索参数。我见过很多团队把大量时间花在调 prompt 上却从没统计过自己的 Hit Rate。这是本末倒置。建议建项目第一天就准备一个 50 到 100 条的 golden set之后每次改动切分参数、Embedding 模型、检索方式都重新跑一遍 Hit Rate让每个决策都有数字支撑。3.3 混合检索和 Rerank检索质量提升最快的两板斧如果你的 Hit Rate 卡在 70% 到 80% 上不去大多数情况下缺的就是混合检索和 Rerank。先说混合检索。思路是同时跑两路召回一路是传统的关键词检索BM25 算法对型号、编号、人名等精确字符串非常有效另一路是向量检索对语义近义词、同义表达更擅长。然后把两路结果用 RRFReciprocal Rank Fusion做融合排序也就是根据每条结果在两路召回中的排名打分合并排在越前面的综合得分越高。我用一个例子说明效果差异用户问“那个支持双频的型号”假设文档里写的是“支持 2.4GHz 和 5GHz”纯向量检索很可能命中这段语义匹配成功了但用户问“WG-602 支持什么频段”纯向量检索可能会被文书里其他 WG 系列设备干扰而 BM25 对字符串“WG-602”极其敏感一下子就把正确的文档块拉回来了。两者一融合检索覆盖范围宽了很多。Rerank 则是更精细的一道工序。前面的粗召回把候选切块扩大到 50 条甚至 100 条Rerank 用一个交叉编码器Cross-Encoder模型把“问题候选文本”拼在一起逐条计算相关性分数再取分数最高的 Top-5 返回给模型。这类模型如 bge-reranker-v2-m3 比普通向量检索精确得多。它的缺点是多了一步打分延迟会高几十毫秒但相对检索质量提升而言完全值得。我在项目里几乎是无脑加 Rerank 的尤其文档数量超过 100 个之后效果从 72% 的 Hit Rate 直接提到 90%。3.4 查询改写和多路召回针对难问题的补充手段有些时候 Hit Rate 低不是因为检索模型不行而是用户的问题本身太“口语化”或者太“复合”。常见救命手段有两个。查询改写是让一个小模型先对用户问题进行改写再去做检索。比如用户问“之前讨论过的那个安全方案你还记得吗”这句话直接拿去检索基本废了。我会先用一个轻量模型把它改写成“历史讨论:安全方案 主要措施”这种适合检索的形式命中率立刻提升。改写可以做得更复杂比如拆出关键词、补全缩写、翻译成英文再检索但核心原则是“检索时的查询句子要和文档的表述风格接近”。多路召回则是把复杂问题拆成多个简单查询分别检索。比如用户问“A 方案和 B 方案哪个性价比高”一次性检索很难同时兼顾两个方案和成本信息。正确做法是拆成“A 方案 特点”“B 方案 特点”“A B 方案 成本”三路检索把结果去重合并后再交给模型。我之前做开发文档问答时凡是遇到“对比”“结合”“以及”这类词都会下意识拆多路效果比只在 prompt 里要求“请全面回答”好得多。4. 把知识管道接到 Agent 工作流里从单次 RAG 到 Agentic RAG4.1 一次性检索的局限Agent 需要“按需取用”基础 RAG 流程是一条直线问题进来检索一次生成回答。这在单个事实类问答场景下够用但接到 AI Agent 工作流里就会碰壁。举个具体例子。用户说“帮我对比一下 A 方案和 B 方案重点看成本结合我们上季度的数据给个建议。”这个问题里模型需要回答“A 方案是什么”“B 方案是什么”“它们的成本数据”“上季度公司数据”四块信息。一次性检索很难把四块信息同时拉全即便强制 Top-K 拉到 20大量无关内容也会把有效信息稀释成噪声模型的注意力被分散生成质量直线下降。Agent 的做法应该不一样它先把任务拆解第一步检索 A 方案资料第二步检索 B 方案资料第三步检索成本相关数据每一步都拿到精确结果后再综合。这种“让 Agent 自己决定何时检索、检索几次”的形式就是不折不扣的 Agentic RAG。它不是替代基础 RAG而是在基础管道外面包了一层 Agent 决策逻辑。4.2 路由、工具调用与 SkillRAG 在 Agent 里的标准接法要把 RAG 接入 Agent 工作流最标准的做法是把它封装成 Agent 的一个工具Function / Tool而不是写死流程。这样 Agent 可以在规划阶段决定“这个问题是否需要知识库”而不是每次都无脑检索。这里有个细节叫路由Routing。很多简单问题并不需要 RAG比如“你是什么模型”。如果每次调用都走一次知识库检索既浪费算力还可能把无关内容塞进上下文造成干扰。路由可以用大模型判断也可以用 embedding 相似度做一个“知识库意图匹配”的过滤后者便宜且快适合高频请求。当你发现某个领域的检索有固定套路时可以把这些套路封装成 Skill。比如医疗 QA 领域的流程是“先按症状检索疾病条目再按疾病检索用药指南最后做交互冲突检查”把这三步封装成一个 SkillAgent 判断用户问题属于“症状咨询”后直接调用它检索质量会比通用 RAG 稳定得多。这也是很多人在问“Skill 怎么和 RAG 结合起来”时的答案Skill 负责编排检索逻辑RAG 负责底层获取内容二者是上下层关系不是竞争关系。4.3 往下走GraphRAG、本体 RAG 与 LLM Wiki 的关系聊到“RAG 进阶方向”你大概率见过 GraphRAG、Ontology RAG、LLM Wiki 这些词。它们并不是互相替代的关系而是从不同角度优化知识获取质量。GraphRAG 由微软开源核心做法是先让大模型从文档中抽取实体和关系构建一张知识图谱检索时支持多跳关系推理。典型场景是“某部门下有哪些项目组项目组里谁负责 XX”普通向量检索很难回答这种关系型问题但图谱检索可以沿边走路。Ontology RAG 更进一步在知识库里加入本体层也就是“类、属性、关系约束”的正式定义让检索结果更符合领域逻辑。LLM Wiki 则是把知识库变成一个对模型友好的、可交互的 wiki 形态强调知识的可维护性和链接关系。这些方向各有价值但对刚接触 RAG 的人来说优先把基础链路打磨到能稳定回答、能溯源、能评估再考虑进阶形态。知识库的规范化、本体设计、图谱构建都是重活基础不牢时贸然上这些方案只会换来一堆维护负担。5. 跑通 RAG 之后我踩过的坑和调试清单5.1 命中率低但模型还在编先查这三个位置我接手过好几种“RAG 效果差”的案例最后基本都是同一个套路问题在检索链路却总有人去调生成端的 prompt。如果你发现自己调 prompt 调了半天没什么起色务必按下面的顺序排查。第一切分是不是破坏了语义。把每道检索失败的问题单独拿出来看看返回的 Top-5 里到底是什么样的片段。如果片段明显被拦腰截断、上下文缺失去调切分策略。第二Embedding 模型是不是不适合你的语言和领域。把问题直接和文档块算一遍相似度如果你发现正确答案的相似度分数和其他无关块差不多就考虑换模型。第三是不是只有向量检索、没有混合检索。这种问题最隐蔽因为大部分题目看起来都能命中但涉及精确型号、编号的就集体翻车。调试顺序一定要记得先解决“检索里有没有正确答案”再解决“生成端有没有正确使用”。不要一上来就改 prompt。我见过最多的无效努力就是在 Hit Rate 只有 60% 的时候把 prompt 改来改去最后发现正确答案根本没被检索出来。5.2 知识更新向量库里的旧内容比你想的更难清理RAG 项目上线之后最容易被忽略的是知识更新问题。知识每天都在变比如价格表每月一调、产品手册出新版但向量库里还躺着旧版本的 chunk。检索时新旧内容一起返回模型看到两套数据互相冲突轻则答错重则直接混乱。我自己的处理方法是文档级版本管理。入库时给每个 chunk 打上 doc_id、版本号、更新时间的 metadata。文档更新后先把该 doc_id 下所有旧 chunk 删除再重新解析、切分、写入。更进一步我会在入库前计算文档哈希如果哈希没变就直接跳过避免重复索引浪费算力。这个坑之所以隐蔽是因为大多数网络教程只教怎么插入不教怎么更新和删除。你如果只跑 Demo 当然感觉不到一旦放到生产环境跑一个月陈旧知识带来的错误率会逐渐暴露。建议从一开始就把 metadata 设计好不要等出问题再补。5.3 没有评估就没有优化给 RAG 建立 Golden Set优化 RAG 最忌“感觉流”。这个参数调一下感觉好一点那个模型换一下感觉又差一点。没有数字支撑你永远不知道到底哪一个改动真正有效。所以我的强烈建议是项目第一天就建立 Golden Set。具体做法是挑 50 到 100 条真实用户问题逐条标注它对应的标准答案文档块和标准回答。之后所有改动无论是切分、Embedding、检索策略还是 Rerank 模型都用这套集子跑一遍评估输出 Hit Rate 和 RAGAS 指标。RAGAS 里有几个关键值Faithfulness生成回答是否忠实于检索内容、Answer Relevance回答是否与问题相关、Context Precision检索内容是否精确命中关键信息。我习惯把评估脚本挂在 CI 上每次改完配置自动跑一遍出一份报告。这样团队里任何人做了改动效果升降都一目了然。没有这套机制之前我调参基本靠猜有了之后每一个优化点都有清晰归因。5.4 我的调试顺序和一份可复用的检查清单最后分享一份我目前固定使用的 RAG 调试清单照着做能避免大部分无效劳动检查文档解析质量扫描版是否 OCR、表格是否结构化、网页是否只保留正文。首次入库后人工抽样随机抽 20 个文档块看切分是否语义完整。建立 50 条以上 Golden Set记录 Hit Rate 基线。打印检索失败案例的 Top-5定位是切分问题还是 Embedding 问题。开启混合检索BM25 向量对比 Hit Rate 变化。加入 Rerank对比 Hit Rate 变化。确认 Hit Rate 达到 90% 以上后再调整生成端 prompt。上线后持续收集 Bad Case每周回灌到 Golden Set。这里我想特别说一句很多人以为 RAG 的核心是“大模型多厉害”但我做了这么多项目后的体会是RAG 的核心永远在数据管道。谁把文档解析、切分、检索、评估这些笨功夫做扎实了谁的效果就稳。那些看起来花哨的进阶方案都是在基础管道可靠的前提下才能发挥作用的。你手里要是有一套干净、可控、可评估的知识获取管道Agent 的可靠程度会远超你的预期。