
1. 为什么 AI Agent 离不开一条“知识获取管道”做 Agent 开发绕不开一个尴尬的真相大模型本身的“知识”是凝固的。你把它训练好、部署好它知道的还停留在训练数据截止的那一天你公司内部的财务制度、产品文档、售后工单里的经验它一概不知。此时如果你硬着头皮让 Agent 直接回答业务问题它要么一本正经地胡说八道要么直接告诉你“这个我没学过”。所以“知识获取管道”这个说法我觉得比单纯的“RAG”这个词更有画面感。RAGRetrieval-Augmented Generation检索增强生成本质上是给 Agent 装了一条从外部知识源到模型输入之间的传送带先按需检索再把检索到的内容塞进上下文让模型基于真实的、你所拥有的知识作答。它解决的不是“模型能不能记住”而是“模型在回答的那一刻能不能拿到对的东西”。但凡你在网上搜过 RAG 相关的资料大概率会看到一堆术语——向量化、embedding、召回率、重排序、chunk 切分、混合检索。这些词单独拎出来都懂但真到自己从零搭一条管道时才发现细节全在“怎么串起来”以及“每个环节怎么调”。这篇是“走进 AI Agent”系列的第四篇我会从 Agent 实际落地时会踩的坑出发把 RAG 这条管道从头到尾拆开讲清楚每一段的作用、选型逻辑以及我实际跑过之后的一些体会。适合谁看两类人。第一类是刚接触 Agent 开发想给机器人接上“企业内部知识”的工程师第二类是已经跑通过一个简单 RAG Demo但发现效果不理想、不知道该调哪里的人。你会发现 RAG 的难点不在“调通”而在“调好”——而这恰恰是管道设计决定的。2. RAG 管道的完整骨架从原始文档到可回答的问题2.1 一条标准管道的五个环节RAG 从物理形态上看其实就是两条链路一条是“写入链路”也叫索引链路另一条是“查询链路”。写入链路负责把知识变成可检索的形态查询链路负责在每次提问时把最相关的知识捞出来交给大模型。下面是拆开后的五个环节文档解析与清洗把 PDF、Word、Markdown、HTML 等原始格式转成纯文本去掉页眉页脚、重复内容保留章节语义。分块Chunking把长文本切成若干小段每段作为一个检索单元。向量化与存储用 embedding 模型把每个块转成向量存入向量数据库同时保留原文和元数据。查询改写与检索用户提问时对问题做必要的改写/扩展通过向量召回可能结合关键词召回找出 top-k 候选块。重排序与合成对候选块做重排挑出最准的几块连同问题一起交给 LLM 生成答案。很多初学教程会把 2、3 两步混在一起讲把 4、5 两步简化为“查一下拼一下”但实际工程里每一个环节都会显著影响最终回答质量。我见过太多团队花了一周把流程跑通结果问什么都答非所问原因往往不是模型不行而是前面某个环节悄悄“带偏”了。2.2 知识获取管道模型 —— 用“仓库”来理解它把这条管道想象成一个仓库会更容易记住每个环节的作用。原始文档是散装货物堆在地上没法直接发货文档清洗是“卸货分拣”把垃圾剔除、把货归好类分块是“重新装箱”每个箱子大小一致、标签清楚向量化是给每个箱子贴上“内容语义编号”方便以后按需找向量数据库是仓库货架按语义编号摆放查询改写是“客户模糊描述翻译成仓库内部语言”检索是“根据需求去货架上找最像的几箱”重排序是“再人工过一遍把最匹配的箱放最前面”。这套比喻在我给团队做技术分享时屡试不爽。因为很多人在调 RAG 时总是盯着“向量检索”这一个点却忽略了整个管道是一个系统任何一环失配都会让下游白费力气。2.3 从“搜索式问答”到“Agent 的知识底座”需要特别说明的是RAG 放进 AI Agent 体系里不只是做一个“问答机器人”那么简单。在 Agent 的规划-执行循环中知识获取管道承担的是“记忆外置”的角色当 Agent 决定下一步需要某些背景信息时不是凭模型内部记忆硬猜而是主动去管道里取。这意味着 RAG 的设计目标不只是“回答对”还要考虑“取用及时”和“更新可控”新增一份文档能不能马上被检索到下架一份旧文档会不会仍然被召回这些在对话场景里可能只是体验问题在 Agent 自动执行任务的场景里就是正确性问题——它可能因为一条过期知识去执行了一个错误的操作。所以在后续章节里我不光讲 RAG 基础怎么搭还会专门聊一聊当它作为 Agent 知识底座时你要额外关注哪几个问题。先把骨架立在脑子里接下来逐个环节填肉。3. 索引链路实战文档清洗、分块策略与嵌入模型选型3.1 文档清洗容易被低估很多人做 RAG 第一步就是调库、写切分代码但我建议你先把“文档清洗”做了。这个环节不性感但回报极高。我处理过的真实案例某团队把一个 PDF 版的《员工手册》直接扔进 RAG 管道结果模型反复回答出“第 3 页页脚里的公司地址”之类的内容。原因就是 PDF 解析出来后页眉页脚、页码、目录、水印全都混进了正文一个分块里包含大量噪声。检索时这些问题片段和用户问题有了浅层词匹配就以高相似度被召回导致上下文里全是无用信息。清洗的常见操作去除页眉页脚、页码、目录、超链接合并因 PDF 分页造成的断行把两端对齐生成的多余空格和换行去掉识别并过滤表格中无意义的空单元格对 OCR 结果做简单的纠错如果扫描件质量差这一步能救回不少。清洗不是越狠越好。比如有些文档里保留了“本文档适用于 xxx”这是有语义价值的别一刀切。建议清洗后人工抽查 20 条左右确认主要噪声确实没了再进入分块环节。3.2 分块策略固定大小、递归切分还是语义切分分块是索引链路里对检索效果影响最大的环节之一但也是很多人顺手默认“按 512 字切”就过去了的地方。主流分块方案有三类固定大小分块每 500 或 800 字一刀带少量重叠overlap。实现简单但经常切断句子、段落甚至把一个完整概念拆到两块里。递归字符分块先按段落分隔符切再按句子切最后按字符数切。这是目前工程实践中的默认方案LangChain 里的 RecursiveCharacterTextSplitter 就是这路。它比固定大小聪明在尽量保持语义粒度。语义分块Semantic Chunking用 embedding 计算相邻句子之间的相似度相似度低就切一刀。这个方案对中文长文档效果往往更好但计算成本偏高适合离线建索引。我的建议是上一套 RAG 项目分块大小先按内容类型定。规章制度、产品说明书这类结构化文档用递归分块目标块大小 400-800 字符会议纪要、聊天记录这类无强结构文本用语义分块更稳。至于重叠值一般设分块大小的 10%-15%太大浪费存储太小丢上下文。3.3 嵌入模型选型与中文场景的坑Embedding 模型决定了两段文本在向量空间里有多“近”选错了后面检索做得再花哨也是白搭。市面上常见选择有 OpenAI 的 text-embedding-3-small、Cohere 的 embed 系列、BGE 系列、M3E 系列国内也有若干商业化 embedding API。如果纯做中文场景我个人更偏向本地可部署的开源模型比如 BGE-large-zh或者 M3E-base一是数据不出内网二是可以针对领域微调。选型时注意三个指标检索质量可以用 MTEB 中文榜单参考、向量维度维度越高越占内存、推理速度对上线服务影响很大。我自己踩过一个坑一开始直接用通用的多语言 embedding 模型处理中文产品名结果检索“无线鼠标”召回了“无线充电器”因为语义上它们都在“无线”附近。后来换了领域适配模型或加了关键词权重情况才有明显好转。这说明 embedding 的“语义”偏向未必符合你的业务语义需要实测验证。3.4 向量数据库怎么选从 Chroma 到 Milvus 的取舍向量数据库是存放向量和原文的地方。项目小、快速验证直接用 Chroma 或 FAISS 就够了生产环境、数据量大、要支持过滤和权限隔离再用 Milvus 或 Qdrant 这类专业引擎。方案适合场景优点需要注意Chroma本地开发、Demo轻量、零配置不适合大数据量和高并发FAISS离线相似度检索高效纯算法库无内置服务化能力需自己封装Qdrant中小规模生产Rust 写的高性能自带过滤需运维一个服务Milvus海量数据、高并发生产分布式、支持复杂过滤部署运维成本最高对起步项目我的建议是先用 Chroma 把流程跑通等确认了分块策略和检索逻辑再迁移到 Qdrant 或 Milvus。别一上来就上一套重型分布式集群那会让调优变得更加繁琐。写入链路到这里就完整了清洗 → 分块 → embedding → 入库。下一步就是用户提问时管道如何工作了。4. 查询链路核心召回、重排序与查询改写4.1 召回环节不是只有向量检索很多 Demo 教程让你用一句“embedding(question) → 向量库 top-k”就算完成了检索。在实际项目里这往往不够。向量检索的本质是语义搜索擅长处理“用词不同但意思相近”的查询但它的弱点在于高相似度的文本可能并非正确答案比如两个产品都叫“智能音箱”但它们的功能、价格、适用场景完全不同语义上很近业务上却大相径庭。所以生产级 RAG 几乎都会上“混合检索”向量检索 关键词检索BM25再把两路结果合并。关键词检索负责精确命中的场景比如型号、编号、人名、专有名词向量检索负责泛化语义。合并时可以用倒数排名融合RRF也可以用加权得分两种方式我都试过RRF 对分数尺度不敏感更省心。4.2 重排序让最相关的内容“真的在最前面”召回阶段为了不漏一般会放宽 top-k比如取 20 或 50 条。但给大模型的上下文是有限且珍贵的放进来太多无关内容反而会干扰生成。所以需要重排序模型Reranker对候选块重新打分。重排序和向量检索的区别在于向量检索时 query 和 document 是分别编码再算相似度的而 Reranker 通常是直接计算 query 和 document 的交互匹配精细一些但推理成本也高。所以工程上常用“双阶段检索”第一次用便宜的方式粗筛 20 条第二次用 Reranker 精排取 top-3 或 top-5 给大模型生成。我在一个企业知识库项目里做过对比不加 Reranker 时答案正确率约 68%加了一个中等规模的 Reranker 后正确率到了 84%提升非常明显。代价是每次查询多了几十毫秒延迟在非实时场景完全可以接受。4.3 查询改写用户的问题往往不能直接拿去搜在知识库问答里用户提问常常很口语化也会省略上下文。比如用户先问了“A 产品支持无线吗”再问“它的价格呢”——第二问如果直接拿去检索泛泛地查“它的价格”召回质量会很差。解决方案是查询改写常见做法有两类基于规则的改写把代词替换为上文的实体比如“它”替换成“A 产品”。基于 LLM 的改写让模型把当前问题和对话历史合并成一个完整的查询——在 Agent 场景里这通常是由 Agent 内部规划环节顺手完成的。还有一个容易忽略的细节一个复杂问题可能需要拆成多个子查询分别检索再把结果合并。这其实就是 Agentic RAG 的雏形了后面我会专门展开。4.4 检索过程的真实体感一次带过滤条件的召回这里分享一个实操中非常常用的能力元数据过滤。比如知识库里同时有《2024 版产品手册》和《2023 版产品手册》用户问“新款智能门锁的待机时间是多久”。如果不加过滤两个版本都可能被召回模型可能会混合不同版本的数据作答。解决方式有两种一种是把“版本号”写入每个 chunk 的 metadata检索时根据提问自动构造过滤条件另一种是文档更新时把旧版本直接下架保证同一主题只有一个有效版本。在某次项目里我用的是“版本过滤 时间过滤”每个 chunk 元数据带上 create_time 和 version查询时先解析出时间/版本条件再检索。效果很直接——因为检索结果不会再出现“新旧混答”的尴尬情况。这也是 RAG 和传统问答最大的不同它不只是“查得准”还得“查得可控”。5. Agent 与 RAG 的三种集成方式以及向 Agentic RAG 的演进5.1 三种常见的集成形态RAG 与 AI Agent 的集成我按复杂程度把它分成三个层级你在不同阶段的项目里可能会用到不同层级第一层工具式 RAG。Agent 在需要知识时把 RAG 当作一个工具调用。比如 Agent 先判断“这个问题需要查产品手册”然后调一个 search_knowledge_base 工具拿到结果后自己总结。这是最常见的轻量集成。第二层流程式 RAG。Agent 的 workflow 里定义了固定的取知步骤比如“先查权限再查文档”“先检索引擎再走 RAG”。适合知识获取有固定顺序、没法乱来的业务场景。第三层规划式 RAG。Agent 自己决定要查什么、在哪里查、查完怎么用这就是走向 Agentic RAG 的方向。如果是从 0 到 1 起步我的建议是先做第一层跑通闭环后再逐步加规划能力。一上来就做第三层等于同时面对“Agent 规划不稳定”和“RAG 检索不准”两个问题排错时很难定位。5.2 Agentic RAG从“一次性检索”到“边执行边获取”传统 RAG 是“一个 query 进去一个答案出来”。但 Agent 任务往往不是一次检索能搞定的——比如“对比 A 产品和 B 产品在安全性上的差异并针对 C 客户的使用场景给出建议”这个任务至少需要 2 到 3 次独立检索查 A 的安全性、查 B 的安全性、查 C 的场景特征。Agentic RAG 的核心是检索行为由 Agent 自主决策它决定检索几次、搜什么、什么时候停止。这个模式的优点很明显——回答复杂问题不再受限于单次 top-k 的上下文够不够缺点同样明显——Agent 可能为了一个简单问题反复检索多次浪费时间甚至偏离主题。我目前实际使用的折中方案是给 Agent 设定检索的“预算上限”比如最多检索 3 次并让检索工具返回“置信度”。置信度高的结果Agent 直接采信置信度低则提示用户补充信息或换一个检索条件尽量避免它盲目地一搜再搜。5.3 Skills 与 RAG 的结合检索不应该只是“查文档”现在不少 Agent 框架引入了“技能”Skills的概念比如让 Agent 直接调用一个“Excel 分析”技能或“SQL 查询”技能。那 Skill 怎么和 RAG 结合我的经验是RAG 可以充当 Skills 的“启动条件”或“参数来源”。举一个例子在内部工单系统里如果用户提问“查一下本月退货率最高的前三款产品”Agent 并不会直接执行 SQL而是先从 RAG 中检索出“退货率”的官方定义和统计口径文档这决定了 SQL 怎么写再把口径传入 SQL 技能最后拿到结果做报表。这里 RAG 提供了“如何做”的知识技能提供了“能做”的能力两者各司其职。这也是未来多智能体系统里比较可行的分工模式底层的知识管理统一走 RAG/知识图谱上层 Agent 更像是编排层负责决策要调用什么样的知识获取动作。6. RAG 上线后的三大硬伤命中率、幻觉、知识更新6.1 命中率不是唯一指标但它是一切的起点做 RAG 效果评估时大家很喜欢盯着“命中率”hit rate也就是正确答案是否出现在召回的候选块里。这个指标当然重要但它只说明“候选里有没有”不说明“模型最终回答得好不好”。我建议把评估拆成三层检索评估hit_rate、MRR、生成评估语义相似度、人工打分、业务评估有没有正确引用文档有没有加不必要的臆断。小项目可能做不到全自动评估但至少准备 50 到 100 个真实问题测试集每次改动管道后跑一遍对比分数变化。我吃过不少亏凭感觉调了分块参数感觉好像变好了一跑测试集才发现某类问题的命中率反而掉了。6.2 幻觉怎么压引用来源与实际置信度RAG 做得再好的回答模型仍然可能“超纲发挥”——在检索内容之外脑补细节。缓解办法有几种限制知识来源在 prompt 中明确“只允许依据提供的文档片段回答超出范围则说不知道”。强制引用要求模型在关键结论后标注文档编号并在生成后做引用校对。置信度打分如果检索到的 top-1 块和问题相似度很低宁可让 Agent 说“知识库中暂无相关信息”也不要硬编。我见过有些团队把“提供来源”做成一种机制违规来管理如果模型引用的来源在检索候选里不存在就把这次回答标记为高风险在界面上加黄色预警。这个做法很值得借鉴。6.3 知识更新与增量索引最容易被忽视的运维负担对比传统搜索引擎RAG 的优势在于更新快但这不意味着你不用管。实际运维中知识更新带来的最大坑是“重复召回”和“冲突召回”。比如文档更新后你重新 embedding 了一份新 chunk但旧 chunk 没有清理掉用户检索时新旧两个版本都命中模型就可能给出自相矛盾的答案。这是非常典型的生产事故。我的经验是每次文档更新不要只做“新增”要做“变更管理”删除旧版本、添加新版本、在元数据里记录变更时间必要时让管道在入库前检查“同源文档是否已存在”。另外增量索引的频率也要结合实际一天一个新文档的团队每天跑一次批量索引完全够用实时性要求高的场景如客服工单才考虑流式索引。过度的“实时”往往带来不必要的算力开销。7. 我在实操中反复用到的调优顺序与工具清单7.1 从问题现象反推管道环节如果你发现 RAG 效果不好先别急着换模型、调参数。先定位问题出在哪个环节表现大概率问题环节检查点答案明显不对且引用内容与问题无关召回环节看召回结果 Top-5 是否包含正确答案候选里已有正确答案但模型答错合成环节Prompt 是否误导是否没有强制引用文档没更新但答案总是旧版本索引环节检查旧 chunk 是否清理、缓存是否作废检索结果相似度普遍偏低分块/嵌入环节分块是否过大嵌入模型是否领域适配迟延高用户无法接受重排序/检索环节是否双阶段都过重能否先小候选再精排这个排查表是我在项目例会上常用来对齐团队的每次效果下滑五分钟内就能锁定大方向。7.2 推荐的技术栈组合从轻到重最后给出一套可以直接“抄作业”的组合起步版适合个人项目/小团队验证LangChain Chroma BGE-M3 一个开源 LLM流程简单一天能跑通。中间版适合团队内部工具LlamaIndex Qdrant BGE-large-zh Reranker如 bge-reranker支持过滤和多用户并发。生产版适合企业级 Agent 产品自建/选型 Milvus 或 Elasticsearch带向量能力 混合检索 重排序 全链路可观测。工具选型其实没有“最好”只有“匹配”。我见过有人用 FAISS 硬撑几十万文档也还行也见过用 Milvus 但索引配置不对导致检索比 FAISS 还慢的情况。所以关键不是工具本身而是你对每个环节的理解是否到位。我个人的经验是每个新项目开始前花半天时间把“文档清洗 → 分块评估 → 检索评估”这三个环节的最小闭环跑起来再往上面加功能。这样后面无论怎么改都有个基线可以对比。框架选 LangChain 还是 LlamaIndexSSE 还是 WebSocket分布式还是单机——这些都是后话管道本身的正确性才是 RAG 项目能不能真正落在业务上的分水岭。