Agentic RAG与传统RAG的差别:多轮决策、参数调优与避坑指南
简介这份资源围绕Agentic RAG代理式检索增强生成提供可运行源码面向已了解基础RAG、希望进阶掌握AI代理与检索流程结合的开发者或研究者。内容清晰解释了Agentic RAG如何弥补传统RAG单一知识源和一次性检索的局限并对比单代理、多代理架构及函数调用、代理框架两种实现路径。资源包共3个文件以HTML演示页面、Inscode配置和Git忽略文件为主整体仅8KB结构精简便于直接查看运行效果。目前已有147人学习。通过该源码可快速理解Agentic RAG的界面交互与项目配置方式并参考DSPy、LangChain等框架的集成思路为后续实验和企业场景落地提供基础。1. Agentic RAG是什么它和你搭过的传统RAG到底差在哪同样是内网知识库问答传统RAG是一锤子买卖把问题向量化从库里捞出 top_k 个片段塞进上下文让模型生成答案。碰上复杂问题就容易翻车——尤其是那种需要对比、分步查证、把多个文档拼起来才能回答的问法一次检索捞回来的往往是碎片模型只能硬着头皮编。Agentic RAG 的核心转变是把「检索」从一次性动作改成一个多轮决策过程模型先判断这个问题要不要查、先查哪部分查完看一眼结果够不够不够就改写查询再查直到信息能支撑回答了才进入生成。这个转变最直接的红利是复杂问题上的答案质量与可解释性提升——每一轮检索、改写、评估的轨迹都能留痕出错了知道在哪一步错的。代价也很明确推理轮次变多、端到端耗时变长、出错面从「检索不准」扩大到了「Agent 规划不好」。这篇笔记从机制讲起落到一份最小可运行源码包怎么组织、参数怎么调最后是我在真实业务里踩过的五个坑。适合正在把 RAG 从 Demo 推向有复杂查询的业务场景的工程师也适合做技术选型时想弄明白 Agentic RAG 和自己的场景合不合的人。2. 从一次检索到多轮决策Agentic RAG 的核心机制Agentic RAG 不是一个新框架它是一套「把规划权交还给模型」的检索增强范式。理解它之前先得说清楚传统 RAG 的固定流水线到底死在哪。2.1 传统 RAG 的固定流水线为什么卡在复杂查询上传统 RAG 的链路是 embedding → 向量召回 → top_k 拼接 → 生成中间没有任何反馈回路。它在文档级问答上表现不错但一旦查询本身是复合的就会露出三个典型失效模式。第一个是召回粒度错位。用户问「A 方案和 B 方案在延迟和成本上的差异我该选哪个」知识库里是两个独立文档各自讲方案单次向量检索只能按语义相似度捞出与「延迟」「成本」分别相关的片段拼出来的上下文没有对比结构模型只能靠语言惯性硬写。第二个是上下文噪声累积。top_k 取 5 的时候还算可控取到 10 以上必然混进无关片段这些噪声对生成质量的影响不是线性的往往是几个强相关的片段被一堆弱相关的干扰项淹没模型反而抓不住重点。第三个是实体和术语的语义转写失败。业务文档里写「结算系统」用户问「资金清算」向量相似度可能并不低但检索结果就是排不到正确文档一次检索没有重试机会。有些团队试图用扩大上下文窗口来硬抗——既然捞不准就把 top_k 拉到 20 甚至 30。这在短文档场景勉强能用但token 成本和幻觉风险同步上升本质上是用计算换运气。Agentic RAG 的思路不是把网撒得更大而是让模型像人一样查资料先想清楚要找什么找到一点看一点不够再换个说法继续找。2.2 决策点一路由判断——这个问题到底要不要检索Agentic RAG 的第一个决策发生在生成之前这个问题必须查库还是可以直接用模型自身知识回答这在实际业务里区分度很高——「公司年会什么时候办」也许直接答就行「平台支持哪几种单点登录协议」则必须查文档。常见做法是把路由交给模型做一次轻量推理输出一个结构化动作。我一般会限制动作空间为三类search需要查向量库、sql需要查结构化数据源、answer直接回答。动作空间越窄误判率越低这也是 Agentic RAG 里最容易被过度设计的地方——有人给路由加了十几个工具结果模型在工具选择上反复横跳检索轮次翻倍但答案质量没涨。路由的提示词是判断质量的命门。空泛的「请判断是否需要检索」几乎必然得到随机输出得把决策条件具体化。我用的版本大致是这样给定问题与当前已收集的资料片段决定下一步动作 - search资料不足或者已有片段之间缺少关联需要继续检索 - sql问题涉及结构化指标金额、时间、状态需要查业务库 - answer资料足以支撑完整回答 只输出一个动作词不要解释。路由判断本身是低温度下的单次调用不参与多轮循环。它解决的是「第一轮到底要不要动手查」的问题而真正让 RAG 变得 Agentic 的是后面这个循环查完发现不够怎么办。2.3 决策点二评估与改写——结果不够就换个方式再查传统 RAG 只有一次检索Agentic RAG 把「检索结果是否足够支撑回答」显式建模成了一个评估节点。这个评估节点是整套机制里最有价值也最难做对的部分——它决定了循环什么时候终止也直接影响了答案质量。具体流程是每轮检索完成后把「原始问题」和「截至目前已收集到的所有片段」一起交给评估逻辑判断是否存在信息缺口。如果缺口存在进入改写节点模型基于已有片段针对缺失的部分生成一个更有指向性的新查询。注意这不是简单地把原问题换个说法而是要明确「缺什么补什么」。比如原问题是「两套方案的延迟对比」第一轮检索可能只捞到了方案 A 的延迟数据那么第二轮改写就应该针对「方案 B 的延迟」去查而不是再查一遍「延迟对比」。改写方向的约束直接写进 prompt比靠模型自觉可靠得多。我常用的改写约束有两条一是只做术语和限定词层面的调整不改变问题意图二是如果前几轮已经查过同一实体本轮要换成该实体的下位概念或相关维度。第一条防止模型把问题带偏第二条保证多轮检索之间有信息增量而不是在原地打转。2.4 主流落地形态自写循环和框架的取舍理解了机制之后落地形态无非两种。一种是完全自己写路由、检索、评估、改写这个循环不依赖任何 Agent 框架。好处是逻辑透明、依赖少几十行代码就能跑通一个最小版本出问题可以直接看循环内部每一轮在干什么缺点是生产化时状态管理、重试、可观测性都要自己补。我见过不少团队的第一步就是这样起步的跑通验证价值之后再迁移到框架。另一种是基于成熟的 Agent 编排框架实现。比如用 LangGraph 把每个决策点建模成图节点节点之间有显式的状态流转或者用 LlamaIndex 的 workflow 机制把检索器包成一个工具让模型自主调用。框架的好处是状态流转、并发控制、持久化这些生产要素是现成的适合直接上线的场景代价是抽象层次高一旦模型行为不符合预期排查链路要先穿透框架本身的调度逻辑。选哪个取决于团队的模型运维能力和业务体量。小团队、验证期自写循环更划算已经有线上 RAG 服务、有监控体系的团队用编排框架更稳。下面一章直接拆一个最小源码包把上面这套机制落到能跑的结构上。3. 把可运行源码拆开看一个最小 Agentic RAG 的代码结构与核心循环网上这类 Agentic RAG 源码包不少但直接拿下来跑会发现「能跑」和「能理解」是两回事。这一章按我自己组织最小实现的习惯来拆不依赖具体框架核心逻辑就是上一章说的路由、检索、评估、改写四件事。3.1 源码包里的文件划分每个文件只干一件事一个适合拿来学习的最小源码包文件划分应该能让你一眼看出来每个决策点在哪。常见的结构大致是这样文件职责关键内容agentic_rag.py主循环路由 → 改写 → 检索 → 评估的循环控制router.py路由决策判断该搜索还是直接回答retriever.py检索抽象封装向量检索与关键词检索rewriter.py查询改写针对信息缺口生成新一轮查询evaluator.py评估终止判断已有片段是否足以回答config.py参数集中地top_k、max_steps、阈值等这个划分的逻辑是循环控制、决策逻辑、检索实现三者解耦。排查问题时可以快速定位——答案是错误的看 evaluator 是不是太容易放行回答内容对但命中不对看 retriever 的召回质量Agent 一直不终止看主循环的 max_steps 和 evaluator 的判据。不要把所有逻辑揉进一个文件里否则后面加日志、加缓存、加人工干预时全是阻力。3.2 核心循环Agentic RAG 本质上是一个 ReAct 循环如果抛开框架的包装Agentic RAG 的核心就是一个 ReAct 循环Thought判断该做什么→ Action执行检索→ Observation观察检索结果→ 循环直到 Observation 足够支撑最终答案。最小实现的核心循环用几十行代码就能说清楚# agentic_rag.py —— Agentic RAG 最小核心循环 def agentic_rag(query: str, max_steps: int 4) - tuple[str, list]: passages [] # 多轮累计的检索片段 trace [] # 每轮决策的日志用于事后排查 for step in range(max_steps): # 1. 路由当前该继续检索还是直接回答 action router_call(query, passages) if action answer: break # 2. 改写针对已有片段的缺口生成本轮查询 refined_query rewrite_call(query, passages) # 3. 检索按改写后的查询做混合召回 hits hybrid_search(refined_query, top_k5) # 4. 去重合并控制上下文膨胀避免同一片段重复累积 passages merge_and_dedup(passages, hits) # 5. 评估拿到新片段后判断是否足以回答原始问题 verdict judge_call(query, passages) # 记录本轮轨迹便于离线分析 trace.append({ step: step, action: action, query: refined_query, hit_count: len(hits), verdict: verdict }) if verdict sufficient: break return answer_call(query, passages), trace这段代码是整个源码包的主干。max_steps是安全阀防止 Agent 无限循环router_call决定要不要动手查rewrite_call负责在检索结果不足时生成更有指向性的查询merge_and_dedupp的作用容易被低估——每轮 top_k5四轮下来就有 20 个片段不按分数去重合并上下文会被重复信息塞满judge_call的返回值直接决定循环是否提前终止。如果只看一个函数来理解 Agentic RAG 和传统 RAG 的区别就看这个循环传统 RAG 的检索只执行一次且结果不可反馈这里每一轮检索的结果都会影响下一轮查询的生成方向。judge_call返回insufficient是驱动改写的原因这也是 Agentic RAG 与普通 RAG 加一个循环检索fixed-step retrieval的本质区别——后者是盲目地多查几轮前者是知道缺什么才去查什么。3.3 路由与改写把决策条件写进 prompt而不是靠模型自觉路由节点和改写节点都是纯大模型调用质量取决于 prompt 的具体程度。路由的 prompt 要给出明确的动作空间和判定条件改写的 prompt 要给出信息增量的硬性约束。# router.py —— 路由判断 def router_call(query: str, passages: list[str]) - str: prompt f 你是检索规划器。根据问题与已收集的资料决定动作 - search资料不足或已有片段之间缺少关联 - answer资料已足以完整回答 问题{query} 已收集片段{passages[:2]} 只输出一个动作词。 return llm_call(prompt, temperature0)这里temperature0是关键参数。路由和改写这类决策节点不需要创造性温度设高只会让模型在动作词之间随机漂移。我在早期版本里给路由设过 0.3结果同一个问题往返几次动作不一致改成 0 之后稳定很多。# rewriter.py —— 针对缺口改写查询 def rewrite_call(query: str, passages: list[str]) - str: prompt f 原始问题{query} 已有片段{passages[-3:]} 请只输出一个改写后的检索查询要求 1. 针对已有片段中缺失的信息不重复检索已有内容 2. 只做术语和限定词层面的调整不改变问题意图 3. 如果前几轮已查过同一实体本轮改为该实体的下位概念或相关维度 return llm_call(prompt, temperature0.2)改写节点温度可以略高0.2 左右因为换术语和调整限制词需要一点多样性但这个多样性必须约束在「不改变意图」的框架内。我在实际使用中遇到过改写把「结算延迟」改成「系统性能优化」的翻车情况就是 prompt 里缺少「不改变意图」这条约束导致的。3.4 评估终止judge 是循环的刹车片评估节点的任务是判断「已有信息够不够」。这个节点设计的好坏决定了整个系统的两个极端判据太松Agent 觉得什么问题都「够」实际上就是退化成了普通 RAG判据太紧Agent 永远觉得不够把上下文撑爆了还在检索反而拉低答案质量。# evaluator.py —— 评估是否继续检索 def judge_call(query: str, passages: list[str]) - str: prompt f 阅读已有片段判断它们是否足以回答原始问题。 sufficient 的条件需同时满足 - 问题涉及的每个子项都有对应片段 - 关键数字、状态、结论有明确出处 - 已有片段之间不存在相互矛盾 原始问题{query} 已有片段{passages} 只输出 sufficient 或 insufficient不要解释。 return llm_call(prompt, temperature0)把「sufficient 的条件」显式列举出来是控制 Agent 行为最有效的手段。只写「判断信息是否足够」是玄学写上「每个子项都有对应片段」「关键数字有出处」之后评估行为才变得可预期。我在后面调试时发现judge 的判据写得越具体需要的 max_steps 越低整体耗时也越低——模型很会钻空子判据抽象它就敷衍。4. 关键参数怎么设top_k、迭代上限与评估阈值能跑的源码包和跑得好的源码包之间差距几乎全在参数上。Agentic RAG 引入了传统 RAG 没有的决策参数这些参数的相互作用比单点调优重要得多。4.1 top_k 与 score_threshold召回宽度和置信底线top_k 控制每一轮检索捞出多少片段score_threshold 控制捞出来的片段必须多相关才能进入上下文。这两个参数是一对需要联动调整单独调一个往往把问题从一个极端推向另一个极端。查询类型top_kscore_threshold说明事实性单点查询某接口并发上限3-50.6-0.7精度优先捞多了反而干扰对比类查询A vs B 的差异5-80.5保证两边都有料阈值过高会漏掉一边综述/方案建议类8-120.4-0.5靠数量覆盖碎片知识阈值过低噪声会被累积top_k 在 Agentic RAG 里比传统 RAG 更敏感因为它是多轮累积的。单轮 top_k10四轮就是 40 个片段对生成模型来说这个上下文早就超出有效注意力范围了。我的一般做法是单轮 top_k 控制在 5-8宁可多查一轮也不让单轮召回带进来一堆低分片段——低分片段在后续轮次里还会被模型当作「已有信息」去影响改写方向错误会自我强化。score_threshold 的作用是过滤明显不相关的片段。但要注意阈值设置过高会引发另一种失败该查的信息被当成噪声滤掉了评估节点看到的信息永远不够Agent 陷入循环。调试时可以分两路观察一路看命中分数的分布一路看最终答案里有没有出现阈值临界片段带来的信息增益这样能判断是阈值过滤过度还是确实没有有价值片段。4.2 迭代上限 max_steps安全阀和效果阀max_steps 是 Agentic RAG 里最重要的安全参数。它的作用有两个一是防止评估节点失灵时无限循环这是安全阀属性二是控制答案质量的边界这是效果阀属性——步数太少复杂问题还没查够就被迫生成步数太多上下文被低质量信息撑满答案信息密度反而下降。场景建议值原因单文档问答1-2改写空间小第一轮基本就能覆盖多文档对比3-4需要分步取证且每步要等前一步结果跨库/混合检索4-5多次工具切换但超过 5 轮收益急剧下降我的观察是当 max_steps 从 1 提到 3 时复杂问题的答案质量提升明显从 3 提到 5 时提升趋缓超过 5 之后绝大多数场景下答案质量不升反降因为累计的片段太多模型在生成时对着信息量过载的上下文反而开始忽略关键片段。所以 max_steps 设 4 是我在大多数业务场景里的默认值——允许覆盖「查实体 → 查维度 → 查对比 → 收尾确认」这种三层检索结构又不至于让上下文失控。调试 max_steps 时重点看 trace 里的verdict分布。如果大部分问题都在第一轮就sufficient说明路由判断偏保守可以适当压紧评估判据让必要的多轮检索真正发生如果大量问题耗满 max_steps 才终止说明评估判据过严或改写方向有问题先调整judge_call的判据描述而不是继续加大 max_steps 去掩盖问题。4.3 评估阈值判据不量化Agent 就是黑匣子judge_call虽然是通过大模型实现的但它在生产里必须表现得像一个有明确阈值的符号逻辑。纯让模型自由判断「够不够」不同问题之间标准不一致而且不可调。我习惯把评估判据拆成可度量的硬性条件让模型只做「判断是否满足」而不是「定义什么叫满足」。三个最有效的量化判据是覆盖度问题拆解出的子项是否都有对应片段、置信度命中片段的相似度分数是否超过阈值、矛盾检测片段之间是否存在互相矛盾的结论。其中覆盖度对答案质量的影响最大——对比类问题如果只查到了一面的信息评估节点必须判定不足而不是等生成阶段让模型含糊带过。覆盖度的实现方式是让路由/改写节点顺带输出问题的子项然后用规则判断片段的命中分布。比如「A 和 B 的延迟对比」拆成 A-延迟、B-延迟两个子项检索 A 延迟的片段命中后只满足一个继续查 B。这个方式比纯靠大模型判断稳定得多而且子项列表可以直接写进改写节点告诉模型「还缺哪项」检索方向不会跑偏。4.4 参数联动多轮检索下的上下文膨胀估算Agentic RAG 最容易忽略的问题是参数联动导致的上下文膨胀。单看每个参数都合理叠加起来就能撑爆模型的上下文窗口。粗略估算一个最坏场景max_steps4每轮 top_k5平均每个片段 500 token单轮就是 2500 token四轮累计 1 万 token。加上最初的问题、每次改写生成的查询、评估节点的对话记录总输入很容易到 1.2 万 token 以上。这还是保守估算如果片段是整页文档截取平均长度翻倍很正常。控制膨胀有四个手段按优先级排列。第一merge_and_dedup后的分数截断每轮合并后只保留 score 前 N 的片段。第二片段级摘要如果原始片段超过 300 token先压缩再进入上下文。第三收敛判定优先——评估节点一旦返回sufficient立即终止这是最简单也最有效的膨胀控制。第四max_steps 硬顶宁可答案缺一块也不能让上下文失控。这四个手段配合使用上下文膨胀基本可控不要只靠调低 top_k 单点硬扛。5. 避坑指南Agentic RAG 落地常见的 5 个坑这部分全是现场踩过的坑。每一条都是现象、原因、解决的结构可以直接对照排查。5.1 Agent 无限循环日志里全是重复检索现象max_steps 设到 6 甚至 8问题简单的场景也经常跑满才停。看 trace 发现每轮改写的查询都差不多命中片段大量重复。原因评估节点的判据写得太抽象模型永远觉得「不够」于是一直改写、一直检索。另一个常见原因是改写节点缺少「不重复已有内容」的约束导致每轮都在查同一个实体。解决把评估判据量化明确写出「问题涉及的每个子项都有对应片段才算 sufficient」。同时给改写 prompt 加硬约束前几轮查过的实体本轮必须换下位概念或相关维度。改完之后循环次数明显下降答案质量反而更好——因为每轮都有信息增量。5.2 越改越偏第二轮查询和原始问题已经没关系了现象原始问题问的是「系统 A 的故障恢复时间」第二轮改写变成了「分布式系统的可用性设计」。检索结果倒是越来越宽泛但和原始问题越来越远。原因改写节点 prompt 里只写了「生成新的检索查询」没有约束「不改变原始意图」。模型在上下文里看到大量宽泛片段后被这些片段带偏了方向。解决改写 prompt 里加上「只做术语和限定词层面的调整不改变问题意图」这条硬约束。我在实际使用中还加了一条「改写后的查询必须与原始问题共享至少一个核心实体词」用规则兜底模型输出里没有核心实体就驳回重写。5.3 加了 Agent 循环后效果反而不如普通 RAG现象对照组里普通 RAG 答对的题Agentic 版本答错了。对比 trace 发现多轮检索累积的片段里混入了低分噪声模型被噪声干扰。原因这是 Agentic RAG 最典型的翻车场景。普通 RAG 只捞一次 top_k噪声有限Agentic 版本多轮累积每轮都带进来几个低分片段上下文里的信息密度被稀释关键片段反而不突出了。解决在merge_and_dedup时按 score 截断只保留每轮 top 3-5 且有把握的片段。另一个有效手段是引入重排序对累计片段统一按与原始问题的相关性重新排序截断后再进生成。记住Agentic RAG 多出来的轮次优势必须建立在每一轮片段都干净的基础上否则就是噪声累加器。5.4 上下文膨胀直接冲破模型的窗口上限现象max_steps4、top_k8 的配置下调用报 token 超限。测试单轮没问题多轮才触发。原因参数没有联动考虑。单轮 top_k8 是可控的但四轮累计 32 个片段按每个片段 500 token 算上下文已经 1.6 万 token加上改写和评估的对话轮次越界是必然的。解决按照第 4.4 节的估算方法先算上限再倒推参数。我一般的做法是「先定 max_steps再定单轮 top_k最后定片段截断长度」优先保证累计 token 在模型窗口的 50% 以内。另外在 merge 阶段把超过长度阈值的片段先做摘要能有效压低增量。5.5 评测显示步数多了、耗时涨了但准确率没涨现象Agentic 版本的平均检索步数比普通 RAG 高了 2 倍多端到端耗时长了不少但离线评测的答案准确率基本持平。原因Agent 的规划能力没有被正确利用。要么路由判断太保守、简单问题也走了多轮检索要么评估判据太容易放行、多轮检索的结果没被真正用于补缺口。解决用 trace 分析把问题分清楚——看有多少问题是第一轮就sufficient但还是走了多轮这类是路由误判压缩路由的search触发条件看有多少问题是多轮检索后verdict才翻转为sufficient但答案没变好这类是改写方向没对准信息缺口调整改写 prompt 的补缺约束。这两个方向调完步数会下降准确率才会体现 Agentic 的价值。6. 让 Agent 学会说「够了」评估节点设计与进阶验证评估节点是 Agentic RAG 和普通循环检索最本质的区分点。进阶用法里我最推荐做两件事一是把评估节点从「LLM 自由判断」升级为「规则套 LLM 兜底」的混合策略二是用一套能暴露「伪 Agentic」的评测方法来验证你的系统真的在规划而不仅仅是多查了几轮。混合策略的实现是先用规则层做快速判定——子项覆盖度是否达标、命中片段分数是否过线、是否存在硬性矛盾规则层能明确给出sufficient或insufficient时就直接返回不浪费一次大模型调用规则层判不了比如子项覆盖度达标但语义上仍有关键信息缺失再降级到judge_call做语义层面的兜底判断。这套做法比单纯用 LLM judge 省 30%-40% 的评估调用量而且行为边界更可控——规则层就是你的底线性约束模型的判断只负责在确定性不足时补充语义理解。验证方法上不要只看最终答案准确率。跑一组固定的问题集记录三个指标平均检索步数、无效检索占比返回的片段最终没被答案引用、改写收敛率改写后的查询是否比上一轮更接近信息缺口。这三个指标能直接暴露「伪 Agentic」——如果平均步数很高但无效检索占比也高说明你的 Agent 在盲目检索而不是规划如果改写收敛率低说明改写节点在空转。我个人在真实业务里吃过这个亏上线初版时没写评估节点只做了固定两轮检索评测发现答案质量比单轮 RAG 还差因为第二轮检索在已充分回答的问题上注入了额外噪声拖累了答案的确定性。后来把评估节点补上加入「够不够」的判断系统才真正在步数和质量之间找到平衡。这是 Agentic RAG 落地中最容易被低估的工程量——写一个能检索的循环很容易教它学会什么时候停下来才是这个方向真正值钱的地方。希望帮到你。本文还有配套的精品资源点击获取