1. 从"检索增强"到"智能体编排":这次到底变了什么
如果你最近在关注大模型应用落地的技术演进,大概率会频繁刷到"Agentic RAG"这个词。很多人第一次看到它,会下意识觉得这不过是"RAG加了个Agent的壳",换汤不换药。但我实际动手搭过几套之后可以很负责任地说:这个判断只对了一半。它确实是在RAG基础上叠加了智能体(Agent)的调度能力,但真正带来的变化,是把"一次性检索"变成了"多轮自主决策的检索循环",这个转变对系统架构、提示词设计、成本控制的影响是全方位的。
先把概念说清楚。传统RAG的流程非常线性:用户提问 → 向量检索Top-K文档 → 拼进上下文 → 模型生成答案。整个过程只有一次检索动作,检索质量好不好,全看那一次召回的运气。而Agentic RAG的核心思路是:让模型自己决定"要不要检索、检索什么、检索几次、结果够不够、要不要换个角度再查"。模型从被动的"信息消费者"变成了主动的"信息调度者"。
这篇内容适合谁看?如果你已经写过基础的RAG Demo,能跑通向量库+大模型的基本链路,但发现实际业务里效果总是不稳定——比如多跳问题答不对、模糊问题召回差、复杂查询漏信息——那这篇就是为你准备的。我会从架构拆解、核心组件、实操步骤、踩坑经验几个维度,把Agentic RAG这套东西讲透,尽量做到你照着就能复现。
需要提前说明的是,Agentic RAG目前没有唯一的标准实现,不同团队的做法差异很大。我下面讲的是一套经过实际验证、相对通用且容易落地的方案,涉及具体参数和工具选型时,我会解释为什么这么选,你可以根据自己的场景调整。
2. Agentic RAG的架构骨架:四个角色各司其职
2.1 为什么不能只用一个"大循环"搞定
刚接触这个方向时,我最容易犯的错误就是:写一个while循环,让模型反复检索直到它说"够了"。听起来很简洁,但实测下来问题一大堆——模型很容易陷入死循环,或者检索两三次就草草收尾,要么就是每次都召回一堆重复内容。根本原因在于:一个模型同时承担"判断、检索、评估、生成"四件事,认知负荷太重,每件事都做不精。
所以更靠谱的做法是拆角色。我目前用的架构里,核心有四个组件,各自职责单一、边界清晰:
- 查询规划器(Query Planner):负责把用户的原始问题拆解成一个或多个可检索的子查询,并决定检索策略。
- 检索执行器(Retriever):拿着子查询去向量库、关键词库或混合索引里捞内容,返回候选文档。
- 相关性评估器(Relevance Grader):对召回的文档打分,判断是否真的和问题相关,过滤掉噪声。
- 答案合成器(Answer Synthesizer):基于筛选后的高质量上下文生成最终答案,并标注引用来源。
这四个角色可以由同一个大模型通过不同提示词扮演,也可以用不同规模的模型分工(比如评估用便宜的小模型,合成用强模型)。我倾向于后者,因为评估这一步调用频率极高,用大模型成本扛不住。
2.2 一次完整请求的生命周期
光说角色太抽象,我拿一个真实场景走一遍。假设用户问:"我们上个季度上线的那个推荐系统,和之前基于协同过滤的老版本相比,在冷启动场景下效果提升了多少?"
这个问题传统RAG基本答不好,因为它需要跨多个文档、多个时间点去拼信息。Agentic RAG的处理链路是这样的:
第一步,规划器把问题拆成三个子查询:①"推荐系统 上线时间 季度";②"推荐系统 协同过滤 对比 指标";③"冷启动 效果 提升 数据"。注意这里规划器不是简单分词,而是理解了问题的多跳结构。
第二步,检索执行器并行发起三次检索,每次召回5-8篇候选文档。这里可以走混合检索——向量召回语义相近的,BM25召回关键词精确匹配的,两路结果合并去重。
第三步,评估器逐篇打分。比如某篇文档讲的是"推荐系统整体架构",和"冷启动效果对比"相关性只有0.3,直接丢弃;另一篇明确写了"冷启动CTR提升12%",相关性0.9,保留。
第四步,合成器拿到3-5篇高相关文档,生成答案,并附上每句话的来源出处。
整个链路下来,可能调用了6-8次模型,耗时比传统RAG长3-5倍,但答案质量是质的飞跃。这就是为什么我说它不是"加个壳"——它把一次赌博式的检索,变成了一个有反馈、可纠错的决策过程。
2.3 和传统RAG的关键差异对照
为了让你更直观地理解差异,我整理了一张对照表:
| 维度 | 传统RAG | Agentic RAG |
|---|---|---|
| 检索次数 | 固定1次 | 动态1-N次 |
| 查询构造 | 用户原问题直接检索 | 规划器拆解为多子查询 |
| 结果过滤 | 无或简单阈值 | 评估器逐篇打分筛选 |
| 失败处理 | 召回差就答错 | 可重新规划、换角度检索 |
| 延迟 | 低(1-2秒) | 高(5-15秒) |
| 成本 | 低 | 高(3-10倍) |
| 适用场景 | 简单事实问答 | 多跳推理、复杂分析 |
这张表最关键的信息是最后两行:Agentic RAG不是无脑升级,而是用成本和延迟换质量。如果你的业务是简单的FAQ问答,用户问"营业时间是什么",那传统RAG完全够用,上Agentic纯属浪费。只有当问题复杂度高、对答案准确性要求严苛时,这套架构才划算。
3. 查询规划器:整个系统里最容易被低估的一环
3.1 规划质量直接决定检索上限
我踩过最大的一个坑,就是早期把精力全放在检索器和向量库调优上,结果发现无论怎么调,效果都卡在一个瓶颈。后来才意识到:如果规划器拆出来的子查询本身就是错的,后面检索再精准也是白搭。检索是"执行",规划是"战略",战略错了战术再强也没用。
举个反面例子。用户问:"对比A方案和B方案在成本和性能上的取舍。"如果规划器偷懒,直接把这个原句丢给检索器,向量库大概率会召回一堆同时提到A和B的文档,但每篇都只讲了一部分,拼起来信息是碎的。正确的做法是拆成四个子查询:A的成本、A的性能、B的成本、B的性能,分别检索后再交叉对比。
3.2 规划器的提示词该怎么写
规划器的提示词设计有几个要点,我逐个说。
第一,明确输出格式。不要让模型自由发挥,强制它输出结构化的子查询列表。我一般要求输出JSON数组,每个元素包含query(子查询文本)和intent(这个子查询想获取什么信息)两个字段。结构化输出便于后续程序解析,也逼着模型想清楚每个查询的目的。
第二,给出拆解示例。Few-shot示例对规划质量影响巨大。我会在提示词里放2-3个不同类型的拆解范例,覆盖单跳、多跳、对比类问题。模型看到示例后,拆解风格会明显更稳定。
第三,限制子查询数量。不设上限的话,模型有时会拆出十几个查询,成本爆炸。我一般限制在2-5个,并在提示词里说明"只拆解必要的维度,避免冗余"。
一个我实际在用的规划器提示词骨架大致是这样:
你是一个查询规划专家。用户会提出一个复杂问题,你需要把它拆解成2-5个独立的检索子查询。 拆解原则: 1. 每个子查询应该聚焦一个具体的信息维度 2. 子查询之间尽量不重叠 3. 如果问题本身很简单,可以只输出1个查询 4. 对于对比类问题,分别针对每个对比对象拆解 输出格式(严格JSON): [ {"query": "子查询文本", "intent": "想获取的信息"} ] 示例: 用户问题:X系统和Y系统哪个更适合高并发场景? 输出: [ {"query": "X系统 高并发 性能指标", "intent": "X系统的并发能力"}, {"query": "Y系统 高并发 性能指标", "intent": "Y系统的并发能力"}, {"query": "X系统 Y系统 高并发 对比", "intent": "两者的直接对比"} ]这套提示词实测下来,拆解准确率比不给示例高出不少。但要注意,示例不能太多,超过5个反而会让模型僵化,遇到示例没覆盖的问题类型就懵了。
3.3 什么时候该跳过规划
不是所有问题都值得规划。如果用户问的是"公司地址在哪"这种单跳事实问题,硬拆成多个子查询纯属浪费。所以我在规划器前面加了一个轻量的复杂度判断:用一个便宜的小模型(或者干脆用规则+关键词)先判断问题复杂度,简单问题直接走传统RAG单次检索,复杂问题才进Agentic流程。
这个判断逻辑我一般这么设计:问题里出现"对比""区别""为什么""如何""哪些因素"这类词,或者包含多个实体、多个时间点,就判定为复杂。规则虽然土,但胜在快且可控,比让模型判断更省钱。
提示:复杂度判断这一步千万别省。我见过有团队所有请求都走完整Agentic流程,结果简单问题也要跑十几秒,用户直接骂街。分流是刚需。
4. 检索执行器与评估器:把噪声挡在生成之前
4.1 混合检索为什么比纯向量更稳
向量检索擅长语义匹配,但对精确的关键词、数字、专有名词不敏感。比如用户问"2023年Q3的营收数据",向量检索可能召回一堆讲营收的文档,但年份季度对不上。这时候BM25这类关键词检索就派上用场了。
我的做法是双路召回+融合排序。向量路召回Top-10,BM25路召回Top-10,然后用RRF(Reciprocal Rank Fusion,倒数排名融合)算法合并。RRF的核心思想很简单:一篇文档如果在两路里都排得靠前,那它大概率真的相关。公式是给每篇文档算一个1/(k+rank)的分数再相加,k一般取60。
def rrf_fusion(vector_results, bm25_results, k=60): scores = {} for rank, doc in enumerate(vector_results): scores[doc.id] = scores.get(doc.id, 0) + 1 / (k + rank + 1) for rank, doc in enumerate(bm25_results): scores[doc.id] = scores.get(doc.id, 0) + 1 / (k + rank + 1) return sorted(scores.items(), key=lambda x: x[1], reverse=True)这段代码不复杂,但效果提升很明显。实测下来,混合检索的召回率比单走向量高出15%-25%,尤其是涉及数字和专有名词的查询。
4.2 评估器:宁可错杀,不可放过
评估器的任务是对每篇召回文档打相关性分,通常用0-1的连续值或"相关/不相关"的二分类。我的经验是:评估标准要偏严格。因为把一篇不相关的文档放进上下文,比少放一篇相关文档的危害大得多——前者会直接误导模型生成错误答案,后者只是信息不全。
评估器的提示词我一般这么写:让模型判断"这篇文档是否包含回答该问题所需的信息",而不是"这篇文档是否和问题主题相关"。这两个标准差别很大。一篇讲"推荐系统整体介绍"的文档,和问题主题相关,但不包含"冷启动提升数据"这个具体信息,按后一个标准就该被过滤。
评估的粒度也有讲究。我试过文档级评估和段落级评估,最后选了段落级。因为一篇长文档里可能只有一段是相关的,整篇保留会引入大量噪声。段落级评估虽然调用次数多,但上下文质量高得多。为了控制成本,我会先用文档级粗筛,再对通过的文档做段落级精筛。
4.3 评估不通过时的补救策略
评估器把所有文档都判为不相关,这种情况一定会遇到。这时候不能直接告诉用户"没找到",那体验太差。我的处理策略是分层的:
第一层,放宽阈值重试。把相关性阈值从0.7降到0.5,再筛一遍,看能不能捞回一些边缘相关的。
第二层,改写查询重试。让规划器基于"当前查询没找到有效信息"这个反馈,换一种表述重新生成子查询。比如把"冷启动效果提升"改成"新用户推荐准确率变化"。
第三层,降级回答。如果重试两次还是不行,就基于现有信息生成一个"部分回答",并明确告诉用户"关于XX部分,当前知识库中没有找到确切信息"。诚实比胡编强一万倍。
这个分层策略是我踩了无数坑之后总结的。早期我图省事,评估不过就直接返回空,结果用户投诉率很高。加上重试和降级之后,有效回答率提升了将近30%。
5. 答案合成与引用:让每一句话都有据可查
5.1 合成器的上下文组织方式
合成器拿到的是一堆经过筛选的段落,怎么组织进提示词,直接影响生成质量。我试过几种方式,最后固定用带编号的上下文块:
请基于以下资料回答问题。每处引用资料的地方,用[数字]标注来源。 [1] (来源:文档A,第3段) 推荐系统V2版本于2023年Q2上线,采用双塔模型... [2] (来源:文档B,第1段) 相比协同过滤,双塔模型在冷启动场景下CTR提升约12%... 问题:推荐系统V2相比老版本在冷启动场景下效果提升了多少?这种编号方式有两个好处:一是模型引用时不容易搞混来源,二是方便后续做引用溯源。我要求模型在每句话末尾标注[1]这样的引用,如果某句话没有引用支撑,那它大概率是模型自己编的,需要警惕。
5.2 处理"资料冲突"的情况
实际业务里经常遇到不同文档说法不一致的情况。比如文档A说提升12%,文档B说提升15%。这时候合成器不能随便选一个,而应该把冲突明确呈现出来:"根据文档A的数据,提升约12%;文档B则记录为15%,两者存在差异,可能源于统计口径不同。"
这种处理方式看起来不够"干净",但它是诚实的。我宁愿要一个承认不确定性的答案,也不要一个自信满满但可能错误的答案。在提示词里我会明确要求:"如果资料之间存在矛盾,请如实指出,不要自行取舍。"
5.3 引用溯源的工程实现
引用标注不能只是给用户看的装饰,它应该是可点击、可验证的。我的做法是在合成器输出后,用正则把[数字]提取出来,映射回原始文档的ID和位置,前端渲染成可点击的链接。用户点一下就能看到原文出处。
这个功能对建立信任极其重要。尤其是企业内部的 knowledge base 场景,用户看到答案能追溯到具体文档,才会真正敢用。我做过一个小范围调研,加了引用溯源之后,用户对答案的信任度评分从3.2提升到4.5(5分制)。
6. 实操中踩过的坑与调优经验
6.1 死循环:Agentic RAG的头号杀手
前面提过,让模型自主决定检索次数,最大的风险就是死循环。我遇到过模型检索了8次还在说"信息不足,需要继续检索"的情况,直接把请求拖到超时。
解决方案是硬性限制+软性引导双管齐下。硬性限制就是设一个最大迭代次数,比如3次,到了就强制进入合成阶段。软性引导是在提示词里明确告诉模型:"你最多有3次检索机会,请合理规划。"另外,我还会记录每次检索的查询,如果新查询和之前的查询相似度超过0.9,就判定为重复检索,直接跳过。
6.2 成本失控:评估器是烧钱大户
评估器要对每篇文档每个段落打分,调用次数是检索次数的好几倍。我算过一笔账:一次完整Agentic请求,评估器可能被调用20-30次。如果全用大模型,成本根本扛不住。
我的优化方案是分级评估。第一级用轻量模型(比如7B级别)做粗筛,把明显不相关的快速过滤掉;第二级才用强模型对剩下的做精细打分。实测下来,成本能降60%以上,而评估准确率只下降不到5%。这个取舍非常划算。
6.3 延迟优化:并行化能省一半时间
Agentic RAG的延迟天然比传统RAG高,但很多延迟是可以优化的。最大的优化点是并行化:规划器拆出的多个子查询,检索可以并行发起;评估器对多篇文档的打分,也可以并行。我用异步IO把这两步并行化之后,端到端延迟从平均12秒降到了6秒左右。
另一个优化点是流式输出。合成器生成答案时用流式返回,用户能很快看到第一个字,感知延迟大幅降低。虽然总时间没变,但体验好很多。
6.4 一个容易被忽略的细节:文档切分粒度
这个坑和Agentic本身关系不大,但影响巨大。文档切分太粗,检索精度差;切分太细,上下文碎片化。我试过256、512、1024三种token的切分粒度,最后发现**512左右配合一定的重叠(overlap 50-100 token)**效果最均衡。重叠是为了避免关键信息正好被切在边界上。
另外,我强烈建议在切分时保留文档的层级结构信息,比如这段属于哪个章节、哪个小节。检索时可以把章节标题也纳入向量化,提升召回质量。这个细节很多教程不讲,但实测有效。
7. 什么场景该上Agentic RAG,什么场景别碰
聊了这么多技术细节,最后回到一个更根本的问题:你到底该不该用Agentic RAG?
我的判断标准很简单,看三个维度。第一,问题复杂度。如果用户的问题大多是单跳事实查询,传统RAG足够,别折腾。第二,错误成本。如果答错一个问题的代价很高(比如医疗、法律、金融场景),那多花点成本换准确率是值得的。第三,知识库规模与结构。知识库越大、越异构,单次检索越难覆盖全,Agentic的多轮检索优势越明显。
反过来,如果你的场景是高频简单问答、对延迟极度敏感、预算有限,那Agentic RAG就是过度设计。我见过有团队为了"技术先进"硬上Agentic,结果QPS掉了一半,成本翻了三倍,用户体验反而变差。技术选型要服务于业务,不是反过来。
从工程落地角度,我的建议是渐进式演进:先跑通传统RAG,把检索质量、文档切分、提示词这些基础打牢;等基础扎实了,再逐步引入查询规划、结果评估这些Agentic组件。一步到位容易翻车,因为出问题时你根本不知道是哪一层的问题。
这套架构我前后迭代了大概两个月,从最初的"一个循环走天下"到现在的四角色分工,中间推翻重来了好几次。最大的体会是:Agentic RAG的难点不在某个单点技术,而在于如何让多个组件协同工作且不失控。规划器、检索器、评估器、合成器,每个都要调,每个都要设边界,最后还要保证整体流程不跑偏。这活儿确实比传统RAG复杂,但当你看到它能答对那些以前根本答不了的多跳问题时,那种成就感也是实打实的。