我们团队在做 AI Agent 平台时最常被问的一句话是“Agent 怎么知道只有你们内部才有的业务知识” 模型参数的截止日期是个硬伤你不可能让它凭空知道你们内部的制度文档、产品手册和客服话术。这正是 RAG检索增强生成要解决的问题。作为“走进 AI Agent”系列的第四篇这篇我们只聚焦一件事Agent 的知识获取管道也就是 RAG 基础。如果你在搭建 AI Agent或者你已经能把 ReAct 这类推理框架跑通了但面对“怎么让 Agent 会查资料”“怎么让回答不翻车”这类问题这篇就是为你准备的。我会从为什么 Agent 必须要有知识获取管道讲起拆解 RAG 的核心链路再带你落地一条最小可用的 RAG 管道最后分享一下我实际踩过的坑。不整虚的全程干货。1. 为什么 Agent 需要 RAG知识获取管道的定位1.1 模型的知识是“过去式”Agent 的知识必须是“现在式”大模型的参数里确实封装了大量人类社会公开知识但这些知识有一个天然上限训练数据集截止时间。我见过一个特别典型的场景团队用大模型做内部知识库问答问了句“公司最新报销流程是什么”模型一本正经地答出一套三年前的流程还附带详细的表单编号。当场所有人就知道这玩意儿不能直接用。这不是模型不够聪明而是它的知识是固化的。想让 Agent 回答“现在”的问题你必须给它一条能接触到“现在”的管道。RAG 做的就是这件事在模型回答问题之前先从外部知识源检索出相关内容把检索结果拼进上下文模型再基于这些新鲜内容生成答案。本质上RAG 是把“记忆”从模型参数里转移到了外部存储中。1.2 知识割裂是 Agent 落地的最大拦路虎我们在做多智能体协作的时候发现一个问题单个 Agent 的推理能力再强如果它拿不到正确的知识产出的东西就是“一本正经地胡说八道”。知识割裂体现在三个层面私有知识不可见企业内部系统、数据库、文档库里的知识模型从来没学过参数里根本不存在。实时知识跟不上项目状态、库存数量、今日价格这类动态信息模型不可能提前预知。异构知识难整合知识散落在 Wiki、数据库、PDF、聊天记录里格式不同、标准不一Agent 没法直接“读”完所有东西。RAG 就是解决知识割裂的统一方案。它把不同来源的知识通过拆块、向量化、索引统一塞进一个向量知识库让 Agent 以同一种方式去检索。这样不管知识原来散在哪里对 Agent 来说都变成“可查询的同一本书”。1.3 为什么是 RAG而不是微调我经常被问到既然想让模型懂业务为什么不直接微调一个模型这里必须把账算清楚微调和 RAG 解决的问题根本不同。对比维度RAG微调知识更新改文档、入库即可秒级生效要重新训练周期长、成本高可控性答案可以溯源到具体文档知识融进参数无法追溯实现成本无需 GPU 训练逻辑简单需要训练资源和数据标注适合场景知识频繁变、要求可解释风格模仿、固定格式生成知识深度检索到的片段有限可能细节不足参数记忆更强细节更丰富我的结论是能用 RAG 解决的不要微调。微调更适合做“模型行为”层面的调整比如让它用某种固定话术回复而知识层面的补全RAG 是成本最低、见效最快的路径。而且在 AI Agent 架构里RAG 是动态管道业务文档一更新Agent 的“知识”立刻跟上这在微调体系里是无法想象的。1.4 从 Agent 视角看 RAG它为什么是管道不是插件严格来说RAG 不是一个独立插件而是 Agent 的一条输入管道。Agent 每轮决策都可以决定“要不要查”查完之后把检索结果作为观察Observation继续推理。这也是我为什么要强调“知识获取管道”这个说法。你可以这样理解 Agent 的行为循环思考推理下一步→ 行动调用工具→ 观察获取结果→ 再思考。RAG 承担的是“行动观察”里的工具职责。Agent 判断当前问题需要外部知识就触发检索拿到文档片段然后继续生成回答。这个循环里RAG 的价值是把正确的知识在正确的时机塞进模型的视野里。不早不晚不多不少这就是管道该有的样子。2. RAG 核心链路拆解从文档到答案的完整流水线2.1 三大阶段索引、检索、生成RAG 的完整链路可以分为三个阶段索引Indexing、检索Retrieval、生成Generation。索引阶段负责把文档加工成可检索的形式。具体来说文档要经过加载、清洗、分块、向量化这几道工序最后写成向量数据库。这个阶段的特点是“贵”Embedding 模型推理要花时间向量存储要占空间但做一次可以反复用。检索阶段负责从向量库里捞相关内容。把用户问题也做一次向量化然后去向量库里做相似度检索找出最相关的几个文档片段。这个阶段的核心指标是召回率和精度既要保证该捞出来的都捞出来又要保证捞出来的不是垃圾。生成阶段负责把检索到的片段组织成答案。把用户问题和检索结果一起拼进 Prompt交给大模型生成最终回答。这个阶段的关键是如何组织上下文不能把几十个片段全塞进去要按相关性排序、去重、裁剪只保留最核心的信息。2.2 分块策略最容易被忽略却最致命的环节我在多个 RAG 项目里摸爬滚打之后可以负责任地说分块Chunking是整个 RAG 管道里对效果影响最大的环节之一但几乎没人一开始重视它。分块大小的选择本质上是粒度与语义完整性的权衡。块太小比如 100 字符语义被切碎检索到的片段往往信息残缺块太大比如 2000 字符虽然保留了完整语义但噪声太多且向量检索的相似度会被局部无关内容稀释导致召回的文档看起来相关实际上关键信息埋在大段文字里。我个人的经验值是通用文档从512~1024 字符起步。这个区间既能保留句子完整度又能让向量检索定位到相对聚焦的主题。但不要死守这个值要按文档类型调整技术文档、制度文件按 Markdown 标题结构分块保留上下文层级。对话记录、邮件按语义段落分块保持对话完整性。表格数据最好单独处理把每行转成文本描述避免把整张表直接丢进向量库。2.3 Embedding 模型选型中文场景的实战对比向量化的质量直接决定检索效果。选 Embedding 模型时要考虑三个维度语义理解能力、支持的语言、向量维度。我常用和实测过的几类模型模型维度特点text-embedding-3-small1536OpenAI 出品英文优秀中文可用但 API 调用有网络依赖bge-m31024BAAI 开源中英双语强支持长文本本地部署方便m3e-base768中文场景专调体积小适合轻量模型bge-large-zh1024中文效果更好但模型更大推理更慢我的建议是中文业务场景优先考虑本地部署的开源模型。一来数据不出内网安全合规有保障二来不依赖第三方 API 的网络延迟和费用。BGE 系列我认为是国内开源社区里经过大范围验证的选择尤其 bge-m3 在长文档和双语混排场景下表现突出。另外一个实战细节不要把多模态文档直接拿去向量化。PDF 里的图片、扫描件要么走 OCR 先转成文本要么用多模态模型描述后转成文本片段。纯文本向量化是最稳定的路径别在早期项目里给自己挖坑。2.4 向量数据库选型四类方案适配不同规模向量数据库是 RAG 的存储底座。市面上的选择五花八门但本质上分成四类轻量级嵌入型FAISS、Chroma、LanceDB。适合单机原型、个人项目、教程演示。FAISS 是 Meta 开源的向量检索库性能极高但不带服务端能力适合嵌入你自己的应用。传统数据库扩展向量能力pgvectorPostgreSQL 扩展、SQLite-Vec。适合已经有数据库基础设施的团队不用引入新组件。中小规模项目首选 pgvector加一列向量类型就能用。专业向量数据库Milvus、Qdrant、Weaviate。支持分布式、多租户、混合检索、标量过滤。适合企业级生产环境、海量知识库。云托管服务各大云厂商的向量检索服务省运维但要注意数据出境和数据所有权问题。我做项目的习惯是原型期用 FAISS 或 Chroma快速验证效果到了生产环境直接上 pgvector 或 Milvus。原因很简单——向量数据库不是瓶颈业务逻辑才是前期千万别在基建上投入过多精力。2.5 提示词里的知识组织不只是拼接字符串生成阶段经常被简单理解成“把检索文本拼到 Prompt 后面”实际上这里面很有讲究。首先检索结果要标注来源让模型在回答时可以引用其次没有检索到相关内容时要明确告诉模型“不知道”避免强行编造最后对相关片段要做去重和排序让最重要的内容靠前。我常用的知识组织模板大致长这样基于以下资料回答问题。资料按相关度从高到低排列。 资料 [1] 来源文档Axxx [2] 来源文档Bxxx /资料 问题xxx 要求仅基于资料回答如果资料中没有相关信息请直接说明资料未覆盖。这个模板的价值在于给模型设定了明确的“知识边界”。回答得出来就答答不出来就承认这直接决定了幻觉率的高低。3. 从 RAG 到 Agentic RAG把检索主动权交给 Agent3.1 为什么不满足于“一次检索、一次生成”基础 RAG 的工作模式是收到问题 → 查一次向量库 → 拼 Prompt → 生成答案结束。这个模式解决了很多问题但在复杂场景里明显露怯。举一个真实场景用户问“我在 618 活动期间买的产品有质量问题该怎么申请售后能退现金吗”这个问题里至少包含四个子问题退货政策是什么质保条款是什么活动期间的规则有没有特殊说明现金退款和原路退回的区别是什么一次检索只能拿到一坨文档片段很难覆盖所有方面。这就是基础 RAG 和阿甘里 Agentic RAG 的分水岭前者由用户问题直接驱动一次检索后者由 Agent 自主决定检索几次、查什么、用什么策略。3.2 Agentic RAG 的四种核心模式我梳理过 Agentic RAG 的常见实现路径核心可以归纳成四种模式路由Routing先判断用户问题属于哪个知识域再决定去哪个向量库或数据源检索。比如问“报销制度”走 HR 知识库问“产品参数”走技术文档库。相当于在检索前加了一个 Agent 判断层。查询改写Query Rewriting对用户原始问题做语义补全。用户说“它的价格呢”如果不知道“它”指代什么检索一定跑偏。Agent 先改写为“iPhone 15 Pro 的价格”再检索召回效果立竿见影。重排序Re-ranking一次检索可能召回 20 个片段但真正有用的可能只有三五个。让 Agent 或专用重排序模型对召回结果做精排把最相关的片段放在最前面减少上下文噪声。多跳检索Multi-Hop一次查不到就换个姿势再查。先查“H100 的显存是多少钱”拿到显存大小后再查“这个显存级别对应的型号”。Agent 自己决定下一步检索什么直到拼出完整答案。3.3 路由模式实战一个 HR 知识库 技术知识库的混合场景路由是我在公司项目里最先落地的 Agentic 能力。架构不复杂但效果提升非常直观。实现方式有两种一是用一个“路由 Agent”输入用户问题输出一个分类如“hr”“tech”“general”然后按分类进入对应索引二是直接用 Embedding 相似度做路由对每一个知识库预先写好几条代表性问题把用户问题跟这些代表问题做相似度比较选最相近的知识库。第二种方式更轻量我比较推荐前期使用。更精细一点的可以在路由决策里同时输出置信度。如果置信度低于阈值就执行“全库检索”不要让路由错误导致召回失败这也是一种稳健性兜底。3.4 查询改写的一个典型例子指代消解与信息补全查询改写是成本最低、见效最快的优化手段。不需要训练只需要在检索前加一层大模型调用把用户问题改写成更适合检索的查询语句。比如用户问“它支持并发吗”如果没有上下文这条检索基本是废的。改写时可以利用历史对话里的实体信息写成“XX系统支持并发吗”。这里的关键是把对话历史中的关键实体抽取出来填充到当前问题里。我实测过一组对比数据不做改写时这类指代不清的检索命中率可能只有 30%~40%做改写之后可以提升到 70% 以上。这还是在没有做重排序的情况下。所以如果你的 RAG 效果不佳先检查查询质量再检查检索和 chunk 策略顺序千万不能反。4. 企业级 RAG 管道落地实操一个可直接参考的示例4.1 需求分析与技术选型假设我们要给一家制造企业做一个“产品手册智能助手”。数据源是几十份产品说明书 PDF用户客服人员会问诸如“型号 X 的最大转速是多少”“维护保养周期是多久”这类问题。企业要求私有化部署数据不出内网。技术选型我建议如下Embedding 用 bge-m3 本地部署向量库用 pgvector因为企业已有 PostgreSQL文档加载与分块用 LangChain4jJava 技术栈或 LlamaIndexPython 技术栈看团队熟悉哪种生成模型用企业内部已有的开源大模型。4.2 索引阶段的代码实现用 Java LangChain4j 为例文档加载与分块的代码如下// 加载PDF文档 Document pdf new Document(/path/to/product-manual.pdf); // 分块策略按段落(400字符)切分重叠80字符 TextSegment splitter new ParagraphTextSplitter( new TextSplitterSettings.Builder() .maxSegmentSizeInChars(400) .maxOverlapSizeInChars(80) .build() ); ListTextSegment segments splitter.split(pdf); System.out.println(分块数 segments.size());分块之后做向量化入库EmbeddingModel embeddingModel new BgeM3EmbeddingModel(/models/bge-m3); EmbeddingStoreTextSegment store new PgVectorEmbeddingStore( jdbc:postgresql://localhost:5432/ragdb, product_embeddings, 1024); for (TextSegment segment : segments) { Embedding embedding embeddingModel.embed(segment.text()); store.add(embedding, segment); }这里有两个细节值得注意一是重叠Overlap的设置很关键它避免了分块边界把同一句话切断导致关键信息丢失二是向量维度和 Embedding 模型输出维度必须保持一致这里 bge-m3 输出 1024 维PgVectorEmbeddingStore 指定的也是 1024一旦不一致写入直接报错。4.3 检索与重排的实现基础检索用余弦相似度即可UserMessage query UserMessage.from(X型号的最大转速是多少); Embedding queryEmbedding embeddingModel.embed(query.text()); ListEmbeddingMatchTextSegment matches store.findRelevant(queryEmbedding, 5); // 打印检索结果 for (EmbeddingMatchTextSegment match : matches) { System.out.println(分数 match.score() 内容 match.embedded().text()); }如果你想要更好的效果可以在拿到粗略召回的 10~20 个片段后再用一个轻量级重排模型按相关性精排。重排模型的输入是“问题文档片段”拼接输出相关性分数。这一步通常能提高最终回答的准确率 10~15 个百分点尤其在文档量大、跨章节主题相似的情况下效果更明显。4.4 接入 Agent 的完整链路把 RAG 封装成一个 Agent 可调用的工具是让它进 Agent 推理循环的关键。在 LangChain4j 中可以用 Tool 注解直接暴露检索能力Tool(检索产品手册知识库输入为原始问题输出为相关文档片段) public String searchKnowledgeBase(String query) { Embedding queryEmbedding embeddingModel.embed(query); ListEmbeddingMatchTextSegment matches store.findRelevant(queryEmbedding, 5); return matches.stream() .map(m - 【来源】 m.embedded().metadata() \n【内容】 m.embedded().text()) .collect(Collectors.joining(\n\n)); }然后在 Agent 的 Prompt 里注册这个工具Agent 就能自主决定“什么时候查”。我习惯在 Prompt 里明确要求“当问题涉及产品参数、维护保养、规格说明时必须调用 searchKnowledgeBase 工具后再回答。”这条约束对降低幻觉率帮助极大。4.5 运行效果实测我们拿三个真实问题在内部测试集上跑过一轮对比问题类型基础RAG正确率Agentic RAG正确率直接参数查询92%95%多条件复合查询61%84%跨文档对比查询37%78%虽然样本量不大但趋势非常明显问题越复杂Agent 自主多跳检索带来的提升越大。尤其跨文档对比查询基础 RAG 经常只检索到其中一个文档的片段而 Agent 能多次检索、分别拿到信息再合起来推理正确率翻了一倍还多。5. 常见问题排查与调优实录5.1 检索不到相关知识怎么办我把大量“检索命中率为零”的案例总结下来原因基本逃不出这四类分块粒度不对块太大语义稀释块太小关键词不连续。先调分块参数再怀疑其他环节。查询表达方式与文档不一致文档里写的是“破损包退”用户问“东西坏了能不能退”向量检索可能匹配不上。这时候查询改写就派上用场了把口语化问题改成文档化的正式表达。Embedding 模型能力不足如果文档里大量专业术语、缩写而模型没训练过这些词检索效果一定打折。可以考虑替换更强的模型或做领域微调。索引写得不完整忘了写元数据过滤条件导致全库检索时分不清文档类型。检查一下入库时 metadata 是否完备。排查顺序建议是先看检索日志确认向量相似度分数分布再看召回的片段原文判断是“没召回”还是“召回了但不是用户要的”最后根据结论分别调 chunk、查询改写或重排。5.2 回答仍出现幻觉怎么办即使有 RAG幻觉也会发生。我归纳了三个主要原因和对应解法检索命中但信息不完整比如文档里只写了“温度不能过高”没写具体数值模型就会“脑补”一个。解法是在 Prompt 中强调“只依据资料回答资料未明确的不许编造”同时对低相似度检索结果设置阈值低于阈值直接告知“知识库无相关信息”。多源知识冲突不同文档对同一问题的答案不一致模型可能“中和”两个矛盾答案。解法是在资料块中标明来源文档和版本日期并指示模型优先采纳最新版本。上下文过长稀释注意力一次性塞入太多片段模型“忘记”了用户的原始问题。解法是限制片段数量3~5 个或使用重排精简上下文。5.3 延迟太高检索响应超过 3 秒RAG 管道的延迟来源主要是两个Embedding 推理和向量检索。如果响应速度不满足要求可以从这几个方向优化Embedding 结果缓存相同或相似问题直接走缓存不必重复推理。缓存 key 用文本的哈希值命中率在日常客服场景中能到 40%~60%。向量检索参数调优PGVector 里建立 HNSW 索引把检索从全量扫描变成近似最近邻搜索100 万条数据量下响应可以从秒级降到毫秒级。降低重排数量重排必然增加延迟可以只在初始召回量较大时触发或者把重排模型换成一个更小的交叉编码器。并行化设计多知识库检索的场景里各库之间没有依赖可以同时发起多个检索请求再做结果合并总耗时只取决于最慢的那个库。5.4 问题排查速查表现象可能原因优先排查项解决方案召回为空分块过小/查询表达不一致检索日志中的相似度分数调大分块、增加查询改写召回了一堆不相关内容Embedding 模型弱或块过大检查召回片段文字换模型、缩分块、加重排回答牛头不对马嘴上下文组织混乱查看实际送入 Prompt 的片段限制片段数量、加元数据过滤回答中有明确事实错误多源冲突或模型脑补核对答案与资料原文加“未知说不知”约束、标注来源响应超时向量检索过慢/未建索引数据库执行计划建 HNSW 索引、加缓存同问题答案不稳定相同检索但生成随机性多次调用对比设置温度参数为 0或做答案一致性校验这套速查表我打印了一份贴在工位上每次 RAG 效果不对先对照检查一遍基本能定位 80% 的问题。5.5 一个容易被忽略的事实调优要量化做 RAG 调优最大的忌讳就是“拍脑袋”。我见过太多人改了一轮 chunk 参数跑两个测试用例觉得“好像好了一点”就停止了。这完全不够。正确做法是建立一个小规模评测集50~100 条带标准答案的问题每次修改都在这套集子上跑一遍记录召回率K、准确率和端到端回答准确率。有了量化指标你才知道哪次改动是真实提升哪次只是偶然波动。这个评测集不用一开始就做得很完美但一定要有否则你的优化就是盲人摸象。我个人经验是第一版评测集花半天搭起来就够了但后续的每一次优化都离不开它收益率极高。写在后面一点个人的体会RAG 这件事听起来就是一个“检索拼接生成”的流水线但真正做过一轮的人都知道坑全藏在细节里。分块参数、查询改写、重排策略、向量库索引每一个环节都可能在你不注意的时候拉低整体效果。在搭建管道时不要急着追求漂亮的架构先把最小链路跑通再加 Agent 自主决策最后再谈调优。我踩过最多坑的阶段恰恰是最初觉得“这有什么难的”的那个阶段。最后再分享一个小技巧开工之前先花半小时把你手头文档里最容易出现的“提问姿势”列出来。比如客服手册里用户大概率会问“坏了怎么办”“多久保养”而不太可能问“本手册包含哪些章节”。文档的使用方式决定了你应该怎么分块、怎么组织检索。这个前置思考比任何调参技巧都值钱。