
1. 从Retriever到AgentAgentic RAG到底解决了什么问题先讲一个特别直观的场景。早期RAG系统做得再漂亮本质还是一套“查询—召回—拼接—生成”的固定流水线。用户问“帮我对比一下Q1和Q2的营收差异”普通RAG会先把这个提问原封不动塞给向量检索召回一堆可能相关的文本块然后让LLM强行拼答案。如果数据库里根本没有一张表同时包含两个季度的对比数据回答就会开始胡编。我做了三年RAG项目最大的感受是RAG的瓶颈不在检索而在决策。检索质量再高也只是把一个用户的真实意图压扁成一次向量查询。很多问题根本不是“查一次”能解决的它需要拆解、需要多步搜索、需要在不同数据源之间切换、需要发现第一次检索结果不够时换个思路再查。这些动作传统RAG的固定链路全都没有。这就是Agentic RAG出现的核心原因。它把RAG从“查询管道”升级成“目标导向的推理过程”让模型在检索的每一个环节都能做决策要不要拆解问题先查哪个数据源当前证据够不够答案之间有没有冲突生成结果需不需要被验证我用最直白的话概括普通RAG是“一问一查”Agentic RAG是“一问多查边查边想”。后者不追求一次召回就命中而是通过不断的工具调用和自我评估逐步逼近准确答案。这个过程本质上就是一个轻量级Agent——它拥有大模型的推理能力又通过工具检索器、代码执行器、数据库查询器感知外部世界。所以这篇我主要讲三件事Agentic RAG的架构该怎么拆、核心决策节点怎么设计、以及我在真实项目中踩过的坑。前面已经写过两篇基础内容这篇介于工程实践与原理剖析之间适合已经跑通过普通RAG链路、正在考虑把系统升级成Agent形态的开发者和架构师。2. 拆解Agentic RAG的五大核心模块很多人一听到Agent就以为要用复杂的强化学习或者上百个节点的编排框架。实际落地完全不是这样。我拆过多个生产级项目Agentic RAG在本质上就是五个模块的组合只是它们之间的调用关系从“线性”变成了“动态路由”。2.1 Agent Core负责“想”的调度中枢Agent Core是整个系统的决策核心通常就是一个具备函数调用能力的LLM。它不直接回答用户问题而是负责制定计划、选中工具、判定结果是否满足要求。在我常用的LangGraph实现里Agent Core会被设计成一个循环节点每次迭代都让模型观察当前状态、决定下一步动作直到它自己认为“信息已经足够可以给出最终答案”。这里有个关键点Agent Core的模型选型不能太弱。至少要具备稳定的工具调用能力和基础的推理能力。我测试过多款模型发现参数量低于一定规模后模型会频繁出现“不知道该调哪个工具”的迷茫状态甚至把工具名编造出来。生产环境我用的是支持并行函数调用的模型这样在多数据源查询时能明显提速。2.2 Planner把复杂问题拆成可执行的子任务Planner是“把大问题切小”的模块。用户问“去年每个月各渠道的获客成本趋势是什么”按照Agent思路Planner会把这个需求拆成几个步骤先定位月维度数据源再查询渠道维度字段最后交给生成模块做趋势归纳。在实际项目中Planner不一定要写成独立节点也可以直接交给Agent Core在上下文中完成拆解。但我的建议是如果系统要走多步检索最好把拆解结果显式记录下来这样后续每一步检索都能引用前一步的结论也方便在日志里排查问题。我自己习惯用JSON格式保存中间计划字段包括thought、tool、query和reason。2.3 Tool Registry检索器之外的“只手”Agentic RAG和普通RAG最明显的差异就在这里。普通RAG只有一个向量检索器Agentic RAG则是一个工具集——向量检索只是其中一种工具。我常用的注册表长这样工具名用途适合场景vector_search语义相似度检索开放式问题、非精确匹配keyword_search关键词/倒排索引检索专有名词、编码、文献编号sql_query结构化查询数值统计、对比分析、报表生成web_search实时联网搜索时效性较强的信息code_interpreter执行Python代码计算、数据分析、图表生成真正让Agentic RAG变“聪明”的是它能在这些问题之间做路由。比如用户问“A产品的库存周转天数”如果知识库里刚好有接口文档模型可能会选择调用sql_query而不是向量搜索——因为这是结构化数据问题向量检索帮不上忙。2.4 Memory短期上下文与长期状态的协同Agentic RAG的决策链条往往很长一旦上下文窗口被中间检索结果塞满模型很容易“忘掉”最初的提问是什么。所以Memor模块不只是缓存对话历史还要负责管理检索中间结果的去留。我采用的做法是双轨记忆短期记忆保存当前任务内产生的所有检索片段长期记忆保存跨任务沉淀下来的用户偏好和领域知识。对于一次复杂的多跳检索短期记忆里的内容可能占几千token我会在进入生成阶段前对它们做一次去重和重排只保留对最终答案有直接贡献的片段避免上下文稀释。2.5 Reflection让系统自己检查自己Reflection模块是我在所有Agent系统里都会强制加上的。它的作用是让LLM对自己的答案做一次“体检”引用是否匹配数字是否一致是否有幻觉风险如果体检不过就把问题反馈给Agent Core触发新一轮检索或修正。Reflection听起来简单实际做起来坑很多。最典型的错误是模型把“反思”变成“复述”——回答的内容跟上一轮一模一样只是换了个措辞。我后面会专门讲怎么用固定提示词和差分检测来规避这个现象。3. 核心实现用LangGraph搭一个可运行的Agentic RAG循环这一节我直接给一套可以跑通的最小实现。选LangGraph是因为它对“循环”的支持最干净普通LangChain用链表达不了复杂的条件跳转LangGraph用图结构可以轻松实现“检索—反思—再检索”的闭环。3.1 图结构的设计思路先明确我们需要哪些节点plan_node规划、retrieve_node检索、reflect_node反思、generate_node生成。连线逻辑如下plan_node输出计划后进入retrieve_node执行检索。retrieve_node的结果送给reflect_node做质量判断。reflect_node如果判定“结果充足”就转generate_node生成最终答案。如果判定“结果不足”跳回retrieve_node执行新一轮检索同时允许修正检索策略。如果检索轮数超过最大限制比如3次强制进入generate_node避免死循环。3.2 节点代码示例from langgraph.graph import StateGraph, END from typing import TypedDict, List class AgentState(TypedDict): query: str plan: dict documents: List[str] retry_count: int answer: str # 规划节点 def plan_node(state: AgentState): query state[query] # 这里用LLM生成结构化计划 prompt f拆解以下问题输出JSON 1. thought: 分析思路 2. tool: 选择的工具 3. query: 实际查询语句 问题{query} plan llm.invoke(prompt) return {plan: plan} # 检索节点 def retrieve_node(state: AgentState): plan state[plan] tool plan[tool] query plan[query] if tool vector_search: docs vector_store.search(query, k4) elif tool sql_query: docs db.query(query) else: docs web_search.run(query) return {documents: docs, retry_count: state[retry_count] 1} # 反思节点 def reflect_node(state: AgentState): if state[retry_count] 3: return {sufficient: True} prompt f判断以下文档是否能完整回答用户问题只回答YES或NO。 问题{state[query]} 文档{state[documents]} judgment llm.invoke(prompt) return {sufficient: judgment YES}3.3 构建与编译graph StateGraph(AgentState) graph.add_node(plan, plan_node) graph.add_node(retrieve, retrieve_node) graph.add_node(reflect, reflect_node) graph.add_node(generate, generate_node) graph.set_entry_point(plan) graph.add_edge(plan, retrieve) graph.add_edge(retrieve, reflect) # 条件边反思结果决定下一步走向 graph.add_conditional_edges( reflect, lambda state: generate if state[sufficient] else retrieve, {generate: generate, retrieve: retrieve} ) graph.add_edge(generate, END) app graph.compile()上面这段代码是完整可跑的骨架。我在实际项目中会额外加入一个trace字段把每一轮检索归因记录下来调试的时候特别管用。如果发现某类问题老是走错工具直接在plan_node的提示词里加上工具选择的约束说明就行。4. 检索策略的组合棋局路由、子查询、重写与多跳检索模块搭好之后真正决定Agentic RAG效果好坏的是检索策略该怎么组合。我在前面两篇文章分别讲过向量检索和关键词检索的细节这一节重点说它们的“组合策略”。4.1 什么时候做路由选择路由是整个系统里最优先的决策。模型先判断问题类型事实型问题直接查结构化数据语义型问题走向量检索实时性问题走联网搜索复合型问题则拆成多个子问题分别路由。路由判断要放在“拆解”之后、“检索”之前因为一旦拆解完成每个子任务的目标就变得清晰了。我用过一个取巧的方式在工具注册表里写清楚每个工具的擅长场景和限制然后让LLM按描述选。不需要复杂的分类模型提示词写清楚就行。4.2 子查询和重写的边界子查询适合“这个问题的答案分散在多个倒排片段里”。典型例子是“甲公司的竞争对手有哪些以及他们各自的主营业务”。普通检索会一次性搜结果往往只召回其中一个方面。Agent会把问题拆成“甲公司的竞争对手”和“这些对手的主营业务”两个查询分别检索后再合并。查询重写则适合“第一次检索没有命中但方向正确”的情况。比如用户问“智能音箱哪个牌子的音质好”第一次向量检索出来的全是产品参数这时候Agent可以把它改写成“蓝牙音箱音质评测对比”再检索一轮。子查询和重写的区别可以这样记子查询是做“广度拆分”重写是做“角度切换”。4.3 多跳检索的深度控制多跳检索是Agentic RAG逼格最高的能力也是最容易翻车的部分。我见过一个案例用户问“2023年获得融资最多的AI医疗公司的创始人是谁”系统需要先查出融资排行榜再查公司信息再查创始人信息一共三跳。每一跳都依赖上一跳的结果只要中间任何一跳召回错误最后答案就离大谱。所以我对多跳检索的控制策略是单条链路最多允许5跳超过就强制终止并让模型基于已有信息作答同时标注“部分证据缺失”。每一跳之后都要让Reflection节点给出置信度评分。如果某跳置信度低于60%触发重写或更换工具而不是硬着头皮往下一跳。中间结果里包含结构化数据时优先做数值一致性校验。比如上一跳说“融资2.3亿”下一跳说“融资230M”虽然单位不同但数值要一致。4.4 多源结果冲突怎么合并这是Agentic RAG独有的麻烦。同一个问题在两个数据源里检索结果可能是矛盾的。普通RAG会直接把全部片段塞给LLM让模型“自行判断”——这等于把风险完全交给了模型幻觉。我采用的做法是“证据比分制”每个检索片段都附上来源类型、时间戳和检索得分在进入生成前让Reflection节点做一次交叉验证。如果两个片段冲突且无法通过时间戳区分新旧就触发一轮针对冲突点的定向检索专门查找能打破僵局的第三方信息。如果实在解决不了在最终答案中明确标注“不同来源存在冲突”。5. 质量保障信号验证、自我反思与幻觉抑制很多人对Agentic RAG的最大误解是只要让模型自己规划、自己检索、自己反思答案质量就自动上去了。实际恰恰相反——自由度过高幻觉概率反而更大。一个Agent每多一次工具调用就多一次引入错误信息的机会。质量保障模块的设计直接决定系统能不能上线。5.1 检索相关度的硬性门槛我通常在检索环节设置一道硬卡点召回结果低于相关性阈值就直接丢弃重查而不是带病进入生成。具体做法是让LLM对每条片段打分1到5分低于3分的片段不参与答案生成。这个操作成本很低又能显著减少模型“硬编”低相关内容的概率。生产环境里我会用纯规则做初筛比如片段与查询的关键词重叠度低于某阈值就丢掉。LLM打分放在第二轮做因为纯规则容易误杀语义匹配的优质片段纯LLM打分又有延迟问题两个结合最稳。5.2 Reflection的提示词陷阱我再强调一次反思模块的坑。初版系统我写的反思提示词是“请检查以上答案是否有问题如果有则输出修正建议。”结果模型每次都说“答案整体准确但可以更详细”然后输出一段跟原答案几乎一样的废话。后来我把反思拆成了三个匹配项效果立刻好转对比原始问题、检索证据和生成答案逐项检查 1. 答案中的每个事实主张是否有检索证据支撑列出没有支撑的主张。 2. 答案中的每个数值是否与检索结果完全一致列出不一致的数值。 3. 答案是否回答了原始问题的每一个子意图列出遗漏的子意图。 如果以上三项都没有问题输出PASS否则输出需要修正的具体内容。关键点在于反思不是让模型“觉得有没有问题”而是让模型“用清单逐项核对”。前者依赖模型的主观判断后者拆成了可验证的客观动作结果完全不同。5.3 生成阶段的受控与透明Agent最后的生成阶段我会做两个约束。第一个是“引用可见”生成的每个事实性句子都要在文档索引里标注对应的检索片段ID这样下游可以做归因审查。第二个是“底线声明”如果Reflection节点的置信度不足但系统已经达到最大检索轮数生成时必须显式告诉用户“以下信息部分缺失仅供参考”而不是打肿脸充胖子。实现上我是在generate的提示词里追加一段规则并配合format_instructions让模型输出带引用标记的JSON结构。解析之后再做一次后处理把没有对应片段ID的句子直接过滤掉。6. 实测与调优我踩过的坑和参数建议理论和代码都过完了最后分享一些真实项目里摸索出来的经验。这些内容花了我好几个月时间才沉淀下来网上文档基本不会写。6.1 最大检索轮数别贪多我给多个团队做过咨询最常见的问题是“我的Agent怎么老是检索不到就放弃了”。查日志发现最大轮数设的是6但大多数情况下第2到3轮就能定位到正确方向第4轮开始基本是在原问题附近打转。轮数放宽并不会提升召回质量只会给模型更多“乱试”的机会。我的建议是普通场景设3轮复合型问题设5轮封顶。每轮的检索结果如果相比上一轮没有新增有效证据就提前终止。判断“没有新增有效证据”的方法也简单把前后两轮的片段做一次交叉去重新增的片段数量低于2就视为收敛。6.2 并发工具调用的提速效果向量检索单独调一次大约200毫秒到1秒不等如果Agent需要查三个不同的数据源串行执行的延迟会叠到好几倍。多轮多跳以后整个系统响应能拖到15秒以上用户根本等不了。我用的是OpenAI系列模型自带的并行函数调用在LangGraph里就是同一个节点里同时触发多个Tool Node。实测下来如果能把三个检索并行执行整个多跳流程的响应时间能从12秒压到5秒左右。代价是上下文里会一次性挤进大量检索结果需要做好去重和精排。6.3 路由错误是最大的隐藏杀手反思下来我遇到过最头疼的问题不是检索不出来而是该用SQL的时候用了向量检索该查实时网页的时候查了内部文档。这类错误在单轮RAG里不可能出现因为工具是写死的但在Agentic架构里模型判断失误的后果被放大了。我的缓解方案是在工具描述里做“负例引导”不只写工具能干什么还写它“不适合干什么”。比如向量检索的描述里加了“本工具不擅长精确数值查询、不擅长按字段过滤例如‘2023年营收超过100亿的公司’不应使用本工具。”加了负例之后路由准确率提升非常明显。6.4 日志与追踪系统的必要性Agentic RAG的排错难度比普通RAG高一个量级。普通RAG查一个问题只需要看一次检索日志Agentic系统要检查每次规划、每次路由、每次反思结果。没有日志追踪出了问题根本无从下手。我现在跑的所有项目都会记录完整的“决策轨迹”每一轮模型的thought是什么、选了哪个工具、查询语句原文是什么、召回片段得分是多少、反思结果是什么。LangSmith这类工具可以直接可视化整条轨迹排查效率提升巨大。对于生产环境中动辄几千个请求的规模轨迹数据同步存一份到数据库将来做错误分析的时候会感谢自己。7. 进阶扩展从单Agent到多Agent协作和记忆持久化基础版Agentic RAG跑通之后事情还远没有结束。我最近在推进的两个方向很可能也是大部分团队将来会遇到的需求。7.1 多Agent协作的适用边界单Agent处理复杂问题时会遇到一个难题规划、检索、反思的所有上下文都挤在同一份记忆里互相干扰。比如一边要查财务报表一边要读产品文档两个任务的指令和数据混在一起模型容易“人格分裂”。拆分多Agent的前提条件是任务具备清晰的边界。我设计过一个案例一个Agent专门负责处理结构化数据查询另一个Agent负责语义文档检索第三个Agent做最终的汇总生成。每个Agent有自己的系统提示词和工具集彼此之间通过消息传递交换结果。这个方案的代价也很明显延迟变高、系统复杂度翻倍、错误类型指数增加。我的建议是——先跑明白单Agent确认问题边界足够稳定之后再动多Agent。不要为了架构好看而上多Agent。7.2 记忆持久化的两种路径当Agent系统反复服务于同一群用户时持久化记忆的价值就开始显现。用户可能昨天问过A产品的成本结构今天问A产品的竞品分析——如果系统能记住前者的背景今天的检索就会更有方向。我实现过两种路径。第一种是“缓存式记忆”把用户最近N轮的问题和答案摘要存入向量库下次提问时先做一轮相似度匹配如果有强相关的历史对话就把摘要注入到当前上下文中。第二种是“沉淀式记忆”对多轮对话做周期性的离线分析提取稳定的用户偏好和领域规则存成长期记忆。两者的区别在于缓存式解决“短期连续性”沉淀式解决“长期一致性”。生产环境我通常两者都上但会刻意控制记忆注入的token量避免历史对话把当前检索的空间挤占掉。7.3 评估体系要跟着升级最后想提醒的是评估方式。普通RAG用RAGAS那套指标就够用了——忠实度、答案相关性、上下文相关性。但Agentic RAG的评估维度多得多路由准确率、每跳检索命中率、反思触发的修正次数、多轮收敛时长、决策轨迹可解释性——这些指标需要单独搭一套评测集来持续跟踪。我现在的做法是在评测集里给每个问题标注了“标准决策路径”比如“应该先查SQL再查文档最后直接生成”。系统跑完之后对比实际路径和标准路径的差异能迅速暴露模型策略偏移。这个评估思路比只看最终答案正确率要深刻得多——最终答案对了不代表过程是对的高效的。Agentic RAG说到底是在用工程化的方式给RAG系统注入“推理能力”。它没有想象中那么玄学也没有文档里写得那么简单它的上限取决于你对决策节点的设计精度而下限取决于你有没有做足够的质量兜底。我写这篇文章时特意把每个踩过的坑都摊开了就是希望大家不要在一个地方重复栽跟头。机器可以不断试错但生产系统不能。