1. 引言:传统RAG的瓶颈与Agentic RAG的价值承诺 还记得第一次部署RAG系统时的兴奋吗?看着它从知识库中检索出相关文档,然后生成看似合理的回答,你一度以为“人工智障”终于要变成“人工智能”了。直到用户抛出一个稍微复杂点的问题——“帮我比较一下这三款产品的性价比,考虑售后和性能,我家在北京五环外,配送方便吗?”——你的RAG系统直接懵了。它要么只抓到了“产品”这个关键词,返回一堆产品列表;要么生成了一个看似完整却毫无逻辑的“缝合怪”回答。
那一刻你才明白,传统RAG就像一个只会背书的图书管理员:你问“秦始皇在哪年统一了六国”,它能迅速翻到第38页;但如果你问“如果秦始皇统一六国后立即下旨修长城,当时的国库能支撑多久?”,它只会眼巴巴地看着你,然后从两本不相干的书里各抄一段给你。
这种“死板检索”的本质,源于传统RAG的静态管道架构。你设计好检索器、写好Prompt模板、设置好Top-K值,整个流程就固定了。它不知道什么时候该换一种检索方式,不知道如何把一个大问题拆成小步骤,更不知道在第一次没找到答案时该怎么补救。这就像一个流水线机器人,无论来了什么工件,它都只会用同一个机械臂做同样的操作。
当你的用户查询从“公司Q2财报”进化到“我该不该买这家公司的股票,考虑一下它刚发的季报和竞争对手的动态,再结合一下最近的行业政策”时,传统RAG的局限性暴露无遗——信息过载 (返回几十个文档让用户自己找答案)和逻辑断层 (把不相关的片段强行拼接)成了家常便饭。
而Agentic RAG的到来,彻底改变了这个游戏规则。它不是对传统RAG的简单修补,而是一次范式转换 ——从“固定检索-生成管道”进化为“智能体驱动的自适应知识工作流”。在Agentic RAG中,我们引入了一个核心智能体 ,它不再机械地执行固定指令,而是像一个“主动的情报分析师”:收到任务后,它会先评估任务复杂度—是先查一波资料,还是直接回答?
需要调用哪些工具?是向量检索、网络搜索、还是执行一段爬虫代码?它还会对中间结果进行反思 ——这个结果够了吗?相关性是否足够?如果不够,要不要换个关键词重查?或者那把问题拆成两个子问题分别查?这种动态工具调用 和迭代优化 的能力,让AI系统从“死板检索”真正进化成了“主动思考的知识助手”。
这篇文章,我将带你从底层原理到落地实战,深入拆解Agentic RAG。你将学到:Agentic RAG的核心架构与设计思想;如何用代码实现一个具备动态工具调用 能力的智能体RAG系统;如何让智能体具备自我修正 与迭代优化 的能力;以及在真实开发中应该避免哪些坑。不管你是刚入门RAG的开发者,还是已经部署过传统RAG的老手,这篇文章都将为你打开一扇新的大门——让AI真正学会“怎么思考”,而不只是“怎么背诵”。
2. 什么是Agentic RAG?从静态管道到智能体驱动的范式转换 图书管理员 vs 情报分析师:一个生动的比喻 想象你走进一个巨大的图书馆。传统RAG是那个最勤奋的图书管理员:你给他一个书名,他立刻跑去书架,按分类号精确找到那本书,翻到你指定的章节,然后把那段话抄给你。如果给的书名不准确,他就找不到了;如果你问的是需要综合多本书信息才能回答的问题,他最多把几本书都搬到你面前,你自己看着办。他高效、精准,但只适合处理“找已知信息”的简单任务。
而Agentic RAG则是那个训练有素的情报分析师。你告诉他:“帮我分析一下这个客户公司的竞争对手,他们最近三个月在电商平台的品牌声量变化,以及有没有负面舆情,顺便看看我们过去一年和他们的合作情况”。他不会转身就跑,而是会先停顿一下,在脑海中规划:嗯,这是一个多步骤任务,需要分阶段执行。第一步 ,去“内部CRM知识库”查合作记录;第二步 ,调用“新闻检索工具”查最近三个月的行业新闻;第三步 ,用“舆情分析工具”爬一下电商评论;第四步 ,把所有信息综合起来,生成一份结构化的分析报告。
如果在第一步发现合作记录太简略,他还会主动调整第二步的策略——比如重点查那些与公司主营业务相关的新闻。他不仅“知道如何检索”,更“知道如何规划检索”。
Agentic RAG vs 传统RAG:三大本质区别 从架构层面看,Agentic RAG和传统RAG至少存在三个本质区别:
区别一:策略动态性
传统RAG的策略是静态的、预先定义的。你的检索管道通常是:用户查询 → embedding → 向量检索 → Top-K个文档 → 拼接Prompt → LLM生成。整个过程就像一个火车时刻表,火车按指定轨道行驶,永远不会偏离。而Agentic RAG的策略是动态生成的。智能体可以基于当前查询的复杂度、意图、甚至历史对话,动态决定使用哪种策略。
举个例子 :当用户问“什么是RAG?”时,智能体会选择最直接的向量检索,因为这是一个简单问题,直接查知识库就够了。但当用户问“RAG和微调各自适合什么场景?它们的优劣势分别是什么?如果我要给客户做一个问答机器人,应该选哪个?”,智能体可能选择多策略组合 :先用向量检索查RAG和微调的基本定义,再调用网络搜索找最新的对比文章,最后用代码工具计算一下两种方案的成本(假设知识库中有成本数据)。
这是传统RAG做不到的。
区别二:工具调用能力
传统RAG的工具箱里只有一把锤子——向量检索。不论遇到什么类型的问题,都用同一套检索逻辑:embedding + 余弦相似度。而Agentic RAG配备了一个可插拔的工具箱 。除了向量检索,它还拥有:
结构化查询工具 :用于查询数据库、知识图谱;
网络搜索工具 :当内部知识库信息不足时,实时抓取网络信息;
代码执行工具 :当需要进行计算、数据统计时,让智能体生成并执行代码;
文档解析工具 :用于处理PDF、Word等非结构化文件;
API调用工具 :对接外部系统的RESTful接口。
这些工具不是摆设,智能体会根据当前任务的需要,主动“召唤”合适的工具组合。
区别三:结果迭代反馈机制
传统RAG是“一次过”的:你输入查询,它输出答案,整个过程无后顾之忧。而Agentic RAG内置了一个闭环反馈机制 。智能体会对每次检索和生成的结果进行自我评估:
相关性检查 :检索到的文档真的和问题相关吗?如果只有一个关键词匹配但语义无关,智能体会意识到“这次检索失败了”,然后主动调整策略。
完整性检查 :检索到的信息能够完整回答问题吗?比如需要三个维度的信息,但只检索到了两个,智能体会自动补充第三次检索。
一致性检查 :从不同工具获得的信息是否相互矛盾?如果有矛盾,智能体会要求重新检索或尝试其他信息源。
这个反馈环是Agentic RAG实现“迭代优化”的核心。它让RAG系统从“一次性检索”进化为“多轮探索式检索”,就像人类在做一个复杂研究时,不断调整搜索关键词、切换数据库一样。
深入理解:Agentic RAG的设计思想 用一句话概括:Agentic RAG = 智能体 + 工具集 + 反馈循环 。这个框架的底层设计思想,实际上是机器学习领域中“plan-and-execute”(先规划、再执行)范式的延伸。智能体不再是被动等待指令的“齿轮”,而是一个拥有“大脑”的决策者。它能感知当前状态(用户查询是什么?知识库有哪些?
已经查到了什么?),制定行动计划(应该先查什么?用什么工具?要不要拆分子任务?),执行并观察结果,然后根据反馈修正下一个动作。
最佳实践 :在设计Agentic RAG系统时,不要试图一开始就让智能体具备“万能”能力。先从最简单的场景开始——给智能体配备2-3个核心工具(向量检索 + 网络搜索 + 代码执行),让它在这套小工具箱里学会“如何选择”。随着业务需求增加,再逐步扩展工具箱和决策逻辑。
这种设计思想让RAG真正实现了从“工具”到“助手”的跃升。你的AI系统不再是一个只会背书的机器人,而是一个能根据任务主动规划、能选择最合适工具、能自我反思和修正的智能助手。这正是Agentic RAG——作为RAG进阶智能体方案——的核心价值。
3. 核心架构拆解:智能体、工具集与迭代循环 理解了Agentic RAG的设计思想,我们来看看它的核心架构。一个成熟的Agentic RAG系统由三大组件构成:决策智能体 、可插拔工具集 、反馈循环 。这三个组件之间的协作方式,决定了系统的智能程度和可靠性。
组件一:决策智能体——系统大脑 决策智能体是Agentic RAG系统的“大脑”,负责理解和分发任务。它通常基于LLM构建,但不仅仅是LLM本身——而是LLM配合一个推理框架 的组合体。目前主流的推理框架有两种:
ReAct模式(Reasoning + Acting,推理与行动) :智能体按照“思考 → 行动 → 观察 → 思考”的循环逻辑工作。当用户提问“哪家快递公司在长三角的配送时效最好?”,智能体会先思考:“这个问题需要查不同快递公司在长三角区域的配送数据”,然后调用相关工具去检索。拿到检索结果后,再思考:“数据不完整,缺少极兔快递的信息”,于是再次调用工具补充检索。
这种“边想边做”的模式,特别适合需要多轮探索的复杂问题。
Plan-and-Execute模式(规划-执行模式) :智能体先制定一个完整的行动计划,然后按照计划逐步执行。比如同样的问题,智能体会先规划:“第一步,列出所有主流快递公司;第二步,逐个查询它们在长三角的配送时效;第三步,对比数据生成报告”。然后按部就班执行。这种模式的优势在于任务路径清晰、易于追踪调试,缺点是灵活度略低于ReAct模式。
提示 :在实际开发中,ReAct模式更适合开放式、不确定性强的问题,而Plan-and-Execute模式更适合步骤明确、可预测的任务。我建议初学者从ReAct模式入手,因为它的“边想边做”逻辑更接近人类自然的思考方式,调试起来也更直观。当你对智能体行为模式足够熟悉后,再尝试Plan-and-Execute模式来应对那些明确需要“分步骤完成”的任务。
组件二:可插拔工具集——智能体之手 工具集是智能体与环境交互的“手”。每个工具本质上是一个封装好的函数或API,定义了输入、输出和功能描述。关键的设计要点是:每个工具的注册信息必须包含清晰的描述和参数说明 。因为智能体依靠这些描述来决策“什么时候该用什么工具”。
一个典型的工具注册代码片段如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 tools = [ { "name" : "vector_search" , "description" : "在内部知识库中进行语义检索,返回最相关的文档片段" , "parameters" : { "query" : {"type" : "string" , "description" : "检索查询" }, "top_k" : {"type" : "integer" , "default" : 5 } } }, { "name" : "web_search" , "description" : "通过搜索引擎获取互联网上的最新信息" , "parameters" : { "query" : {"type" : "string" , "description" : "搜索关键词" }, "num_results" : {"type" : "integer" , "default" : 5 } } }, { "name" : "code_executor" , "description" : "执行Python代码,用于数据计算、统计分析等任务。 代码必须使用print输出结果。" , "parameters" : { "code" : {"type" : "string" , "description" : "要执行的Python代码" } } } ]
注意 :工具描述的质量直接影响智能体的决策准确度。太简略的描述会让智能体无法判断何时使用;太冗长的描述又可能让智能体陷入“信息过载”。一个好的做法是:在描述中说明“这个工具擅长解决什么问题”、“适合处理什么类型的数据”。比如对vector_search的描述,可以加上:“擅长处理需要理解语义相似性的问题,如技术概念解释、产品对比”等。
组件三:反馈循环——自我修正引擎 反馈循环是Agentic RAG相比传统RAG最具革命性的组件。它让系统具备自我修正 和迭代优化 的能力。一个标准的反馈循环包含三个步骤:
步骤1:结果评估 。智能体在每次工具调用后,都要对结果进行评估。评估维度包括:相关度(结果是否与查询强相关)、完整性(结果是否覆盖所有查询维度)、一致性(不同工具返回的信息是否相互吻合)。评估可以通过一个简单的Prompt来实现,例如:“请分析以下检索结果是否完整回答了用户问题。如果缺信息,请指出缺少什么;如果不相关,请返回’无相关结果’。”
步骤2:策略调整 。如果结果评估不理想,智能体调整策略。可能的调整方式包括:
查询重写 :用HyperClarity(HyDE)风格的方式,将原始查询扩展或重写,生成更精确的检索语句;
工具切换 :换一个不同的工具重试。比如向量检索未找到结果,尝试网络搜索;
任务拆分 :将一个大问题拆成几个小问题,分别检索后再综合。
步骤3:终止决策 。智能体在每次迭代后都要判断“是否可以终止”。终止条件通常包括:检索结果的置信度超过阈值、工具调用次数达到上限(防死循环)、迭代轮数达到上限(控制成本和延迟)。如果满足终止条件,智能体进入答案生成阶段;否则,回到步骤1继续迭代。
三者的协作流程 这三个组件的协作,构成了Agentic RAG的核心工作流:
接收查询 → 决策智能体分析用户意图和任务复杂度;
制定计划 → 基于分析结果,智能体决定需要哪些工具、按什么顺序调用;
执行工具 → 调用相应工具,获取中间结果;
反馈评估 → 智能体评估中间结果的质量;
迭代优化 → 如果不满意,调整策略(重写查询、换工具、拆分子问题),回到步骤3;
生成答案 → 当迭代终止后,基于所有检索结果,生成最终答案。
这个流程看起来复杂,但当你用代码实现它时,会发现核心逻辑其实只有几十行——关键不在于代码复杂度,而在于如何设计智能体的决策规则 和如何定义工具的交互接口 。接下来,我们就用实战代码来演示这个过程。
4. 实战一:零基础搭建你的第一个Agentic RAG系统(动态工具调用实现) 理论终归要落地。在这一节,我们将从头构建一个最小可用的Agentic RAG系统。你将亲眼看到智能体如何根据用户查询,动态选择并调用不同工具,以及如何实现基本的迭代优化。
准备工作:环境与依赖 我们将使用Python标准库实现核心逻辑,不依赖LangChain等重量级框架,这样你能更清晰地理解底层原理。唯一的外部依赖是OpenAI的API(或者任何兼容的LLM API,如Qwen、DeepSeek),用于驱动智能体的决策和答案生成。
1 2 3 4 5 6 import jsonimport openaifrom typing import Callable , List , Dict , Any
实现核心:智能体决策引擎 智能体的核心决策逻辑是:给定一个用户查询和一套可用工具,LLM需要输出“我应该调用哪个工具,以及传入什么参数”。这一步通常通过给LLM一个结构化的Prompt来实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def call_llm (prompt: str , response_format: str = "text" ): """调用LLM,支持返回文本和结构化JSON""" client = openai.OpenAI() messages = [{"role" : "system" , "content" : "你是一个智能助手,请按照要求输出。 " }, {"role" : "user" , "content" : prompt}] response = client.chat.completions.create( model="gpt-4o" , messages=messages, temperature=0.0 ) content = response.choices[0 ].message.content if response_format == "json" : try : start = content.index("{" ) end = content.rindex("}" ) + 1 return json.loads(content[start:end]) except : return content return contentdef build_tool_descriptions (tools: List [Dict ] ) -> str : """将工具列表格式化为LLM可理解的描述文本""" descriptions = [] for tool in tools: params_desc = "\n" .join( f" - {name} : {info['description' ]} (类型: {info['type' ]} , 默认: {info.get('default' , '必填' )} )" for name, info in tool["parameters" ].items() ) descriptions.append(f"工具名: {tool['name' ]} \n描述: {tool['description' ]} \n参数:\n{params_desc} " ) return "\n\n" .join(descriptions)def agent_decision (query: str , tools: List [Dict ], context: str = "" ) -> Dict : """让智能体决定下一步操作""" tool_desc = build_tool_descriptions(tools) decision_prompt = f""" 你是一个智能检索助手。当前用户查询: {query} 当前已有信息: {context if context else "暂无" } 你有以下工具可用: {tool_desc} 请根据查询的需要,决定下一步操作。输出JSON格式: {{ "action": "调用的工具名称或final_answer", "params": {{"参数名": "参数值"}}, "reasoning": "你做出这个决定的原因" }} 规则: - 如果认为当前信息已经足够回答问题,action设为"final_answer" - 否则,选择最合适的工具(只选一个),并填写正确的参数 - 如果某个工具已经调用过且结果不理想,换一个工具 """ result = call_llm(decision_prompt, response_format="json" ) return result
定义工具集:模拟真实场景 为了演示动态工具调用,我们定义三个典型的检索工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 knowledge_base = { "产品A" : "产品A是一款面向中小企业的CRM系统,注重客户管理和销售流程自动化。价格:199元/月。支持在线支付和银行转账。" , "产品B" : "产品B是一款针对大型企业的ERP系统,包含财务、HR、供应链模块。 价格:899元/月。部署方式:支持云端和私有化。" , "产品C" : "产品C是一款免费的CRM系统,提供基本客户管理功能,适合初创团队。高级功能需付费:99元/月。" , }def vector_search (query: str , top_k: int = 2 ) -> str : """基于关键词匹配的知识库检索(模拟语义检索)""" results = [] for key, value in knowledge_base.items(): matched_words = len (set (query.split()) & set (key.split() + value.split())) if matched_words > 0 : results.append((value, matched_words)) results.sort(key=lambda x: x[1 ], reverse=True ) if not results: return "❌ 未在知识库中找到相关信息。 " return "\n\n" .join([f"[来源: {knowledge_base[key]} ]\n内容: {value} " for key, value in results[:top_k]])def web_search (query: str , num_results: int = 3 ) -> str : """模拟网络搜索,返回静态的测试数据""" web_data = { "产品对比" : "根据用户评测,产品A的CRM功能最全面,产品B的ERP最好,产品C性价比最高。 " , "售后服务" : "产品A提供7×24小时在线客服;产品B提供专属客户经理;产品C仅提供社区支持。" , "行业报告" : "2024年CRM市场报告中,产品A市场份额领先,产品B在企业级市场表现突出。" , } for key, value in web_data.items(): if key in query or any (word in key for word in query.split()): return value return "❌ 网络搜索未找到相关信息。 " def code_executor (code: str ) -> str : """执行简单的Python代码(安全沙箱)""" try : local_vars = {} exec (code, {"__builtins__" : {}}, local_vars) return str (local_vars.get("result" , "代码执行完成" )) except Exception as e: return f"❌ 代码执行失败: {str (e)} " tools = [ {"name" : "vector_search" , "func" : vector_search, "description" : "在内部知识库中检索产品信息、价格、功能等" , "parameters" : {"query" : {"type" : "string" , "description" : "检索关键词,如产品名称" }}}, {"name" : "web_search" , "func" : web_search, "description" : "搜索互联网上的最新信息,如用户评测、行业报告" , "parameters" : {"query" : {"type" : "string" , "description" : "搜索关键词" }}}, {"name" : "code_executor" , "func" : code_executor, "description" : "执行Python代码进行数据计算或分析。 代码中请将结果赋值给变量result。" , "parameters" : {"code" : {"type" : "string" , "description" : "要执行的Python代码" }}} ]
主循环:实现动态工具调用 现在,我们编写Agentic RAG的主循环。智能体会持续决策→执行工具→评估结果,直到决定生成答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 def run_agentic_rag (query: str , max_iterations: int = 10 ): """ Agentic RAG主循环 参数: query: 用户查询 max_iterations: 最大迭代次数,防止死循环 """ context = "" iteration_count = 0 tool_call_history = [] while iteration_count < max_iterations: iteration_count += 1 print (f"\n--- 第 {iteration_count} 次迭代 ---" ) decision = agent_decision(query, tools, context) print (f"🤔 智能体决策: {decision['reasoning' ]} " ) action = decision["action" ] if action == "final_answer" : print ("✅ 智能体认为信息足够,准备生成答案" ) break tool = None for t in tools: if t["name" ] == action: tool = t break if tool is None : print (f"⚠️ 工具 {action} 不存在,跳过" ) context += f"\n[注意] 调用 {action} 失败,工具不存在。 " continue params = decision.get("params" , {}) call_signature = f"{action} _{json.dumps(params, sort_keys=True )} " if call_signature in tool_call_history: print (f"⚠️ 检测到重复调用 {action} ,切换策略" ) context += f"\n[注意] {action} 已用相同参数调用过,信息不足,请换一种方式。 " continue tool_call_history.append(call_signature) print (f"🔧 调用工具: {action} ({params} )" ) try : result = tool["func" ](**params) print (f"📥 工具返回: {result[:100 ]} ..." ) except Exception as e: result = f"❌ 工具调用出错: {str (e)} " print (result) context += f"\n[工具调用: {action} ]\n结果: {result} " final_prompt = f""" 用户查询: {query} 基于以下检索信息,生成一个完整、准确的回答。如果信息不足,请明确指出缺失了什么。 检索信息: {context} """ final_answer = call_llm(final_prompt, response_format="text" ) print ("\n=== 最终答案 ===" ) print (final_answer) return final_answerif __name__ == "__main__" : user_query = "产品A和产品C哪个更适合初创公司?考虑价格和功能。" run_agentic_rag(user_query)
运行结果分析 当你运行上述代码,会看到智能体如何一步步决策:
第一次迭代 :智能体意识到需要比较两款产品,首先调用vector_search分别检索产品A和产品C的信息;
第二次迭代 :获取价格和基本功能信息后,智能体发现缺少关于“初创公司”场景的评估,于是调用web_search搜索相关评测;
第三次迭代 :综合所有信息后,智能体认为信息足够,调用final_answer生成对比分析报告。
易错点提示 :在实现过程中,最常见的问题是工具调用陷入死循环 。比如智能体反复调用同一个工具,却因为参数写错而不断返回空结果。解决方案包括:①设置最大迭代次数(代码中max_iterations);②记录工具调用历史,防止重复调用相同参数的同一工具;③在工具返回空结果时,让智能体“尝试其他工具或换个关键词”。
这个最小原型虽然简单,但已经完整展示了Agentic RAG的核心能力——动态工具调用 。你可以基于这个模板,替换真实的知识库和工具实现,快速搭建自己的智能体检索系统。
5. 实战二:迭代优化策略——让智能体学会自我修正 在上一节中,我们的智能体只是“选择工具、调用工具、然后结束”。但真实的Agentic RAG还需要一个关键能力:当第一次检索结果不理想时,智能体能够自我修正 。这一节,我们将实现这个“迭代优化”的核心机制。
问题场景:经典的多信息需求查询 假设用户提问:“帮我比较一下产品A、B、C的性价比,考虑价格、功能和售后服务三个维度。” 这是一个典型的多维度综合查询 。传统RAG的固定检索很可能只命中价格维度的文档,然后生成片面回答。而Agentic RAG的迭代优化,能确保所有维度都覆盖到。
实现迭代优化:查询重写与策略切换 迭代优化的核心逻辑是:智能体对每次检索结果进行评估,如果发现信息缺失或不完整,就调整策略继续检索。我们通过增加一个“信息完整性评估器”来实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def evaluate_information_gap (query: str , context: str ) -> List [str ]: """ 评估当前信息哪些维度还需要补充 返回一个列表,列出还需要检索的缺失维度 """ eval_prompt = f""" 用户查询: {query} 当前已检索到的信息: {context} 请分析:当前信息是否完整覆盖了用户查询的所有需求维度? 如果完整,请输出: [] 如果有缺失,请输出缺失的维度列表,每个维度用一句话描述。 例如: ["缺少产品C的售后服务信息", "缺少三款产品的价格对比"] 注意:只输出JSON数组,不要输出其他内容。 """ result = call_llm(eval_prompt, response_format="json" ) if isinstance (result, list ): return result return []def generate_missing_query (gap: str ) -> str : """根据缺失维度生成新的检索查询""" gen_prompt = f""" 基于用户对"产品A、B、C的性价比对比"的需求,现在需要补充以下信息: {gap} 请生成一个精炼的检索查询,用于在知识库中搜索相关信息。 只返回查询语句,不要有其他内容。 """ return call_llm(gen_prompt, response_format="text" )
完整的迭代优化Agentic RAG系统 现在,我们把评估器集成到主循环中,实现“检索→评估→缺失→再检索”的迭代链路。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 def run_iterative_agentic_rag (query: str , max_iterations: int = 10 ): """ 带迭代优化的Agentic RAG """ context = "" iteration_count = 0 initial_decision = agent_decision(query, tools, "" ) if initial_decision["action" ] == "vector_search" : result = vector_search(query, top_k=3 ) context = f"[初次检索]\n{result} " print (f"📥 初次检索完成: 共获取{len (result.split(chr (10 )))} 个信息片段" ) while iteration_count < max_iterations: iteration_count += 1 print (f"\n--- 第 {iteration_count} 轮迭代(评估与优化)---" ) gaps = evaluate_information_gap(query, context) if not gaps: print ("✅ 信息完整,无需继续检索" ) break for gap in gaps: print (f"🔍 发现缺失信息: {gap} " ) new_query = generate_missing_query(gap) print (f"📝 生成新查询: {new_query} " ) result = vector_search(new_query, top_k=2 ) if "未在知识库中找到" in result: print ("⚠️ 内部知识库无相关结果,切换到网络搜索" ) result = web_search(new_query) context += f"\n[补充检索: {gap} ]\n{result} " if iteration_count >= max_iterations: break final_prompt = f""" 用户查询: {query} 经过多轮检索和完善,以下是所有收集到的信息: {context} 请生成一个综合回答,确保覆盖价格、功能、售后服务三个维度,并给出性价比对比结论。 如果某些维度信息仍然缺失,请明确告知。 """ final_answer = call_llm(final_prompt, response_format="text" ) print ("\n=== 最终答案 ===" ) print (final_answer) return final_answerif __name__ == "__main__" : complex_query = "帮我分析产品A、产品B、产品C的性价比,考虑价格、功能和售后服务三个维度" run_iterative_agentic_rag(complex_query)
运行效果演示与解读 当你运行这段代码,会看到智能体如何通过迭代优化逐步完善检索结果:
第1轮评估 :智能体分析已有信息,发现“缺少产品B和产品C的售后服务信息”、“没有三款产品的直接价格对比”。
第2轮迭代 :智能体生成新查询“产品B售后服务信息”、“产品C售后服务信息”、“三款产品价格对比”,逐一调用工具补充检索。
第3轮评估 :发现信息基本完整,终止迭代,生成最终答案。
提示 :迭代优化虽然强大,但也需要控制成本。每一次额外的工具调用都意味着额外的LLM调用和API费用。在实际项目中,建议设置“迭代次数上限”(5-10次)和“总消耗token上限”。同时,优先使用质量高、可靠性强的内部知识库工具,减少对昂贵的网络搜索调用。
进阶优化:让迭代更“聪明” 在实际项目中,单纯依靠“发现缺失→补充检索”还不够。你还可以实现更高级的优化策略:
策略1:动态结果验证 。在每次补充检索后,让智能体验证新获取的信息是否与已有信息一致。如果存在明显矛盾(比如产品A的价格在两个来源中差了3倍),智能体应当标记冲突并寻求第三个来源验证。
策略2:智能终止决策 。不一定每次都要填满所有维度。如果智能体对已获取信息的置信度很高,且剩余维度对最终答案的影响很小,可以提前终止。这需要引入一个“置信度阈值”。
策略3:回溯与修正 。如果迭代过程中发现之前获取的信息有误(比如某个工具返回了冲突数据),智能体需要有能力“忘记”先前的错误信息,并重新检索正确内容。这类似于人类的“认知修正”过程。
最佳实践 :迭代优化在以下场景中效果最为显著:①需要多源信息综合的查询;②知识库数据覆盖不全,需要动态补充;③用户意图不明确,需要在探索中逐步明确。对于简单的事实型查询(如“产品A的价格是多少”),直接使用传统RAG反而更高效。