Agentic RAG:让 AI Agent 自主决定检索策略
发布时间:2026/6/4 9:56:01
分类:文化教育
浏览:1234

Agentic RAG:让 AI Agent 自主决定检索策略一、从"哑巴检索"到"自主决策"想象这样一个场景:你让一个基于 RAG 的 AI 助手帮你查"公司上季度在华东地区的销售额,并对比去年同期"。传统 RAG 的做法是什么?把整句话作为查询丢给向量数据库,返回最相似的几个文档块,然后让 LLM 基于这些碎片信息生成回答。结果往往令人失望——它可能返回了西北地区的数据,或者只找到了去年的记录,缺了今年的。为什么会这样?因为传统 RAG 把"理解复杂问题"和"制定检索策略"两件事都推给了 LLM 的单次推理,没有给模型一个"思考-行动-观察-再思考"的循环空间。这就是 Agentic RAG 要解决的核心问题:赋予 RAG 系统一个 ReAct(Reasoning + Acting)风格的 Agent 循环,让它能够像人类研究员一样——先分析问题、拆解成子问题、决定去哪儿检索、检索后评估结果质量、必要时更换检索策略或进行多轮迭代——最终自主完成复杂的信息获取任务。下图对比了传统 RAG 和 Agentic RAG 的本质差异:维度传统 RAGAgentic RAG检索次数1次多次(可迭代)检索策略固定(单向量库查询)动态(多源、多策略选择)查询改写无或简单增强Agent 自主分解与改写结果评估无相关性检查 + 自我反思工具使用单一检索工具多工具编排(搜索、数据库、API)任务复杂度简单问答多步推理 + 数据聚合 + 对比分析二、核心架构:Agent 循环如何工作Agentic RAG 的本质是在标准 RAG Pipeline 之上引入一个Agent 执行循环。这个循环遵循经典的Plan-Execute-Observe-Reflect模式:┌──────────────────────────────────────────────┐ │ Agent 循环 │ │ │ │ 1. Plan ──→ 分析问题,拆解检索计划 │ │ │ │ │ ↓ │ │ 2. Execute ──→ 选择并调用合适的检索工具 │ │ │ │ │ ↓ │ │ 3. Observe ──→ 获取检索结果,评估质量 │ │ │ │ │ ↓ │ │ 4. Reflect ──→ 信息是否足够? │ │ │ │ │ │ │ 不够 │ 足够 │ │ ↓ ↓ │ │ 回到 Step 1 5. Synthesize → 输出最终答案 │ └──────────────────────────────────────────────┘2.1 查询分解(Query Decomposition)这是 Agentic RAG 的第一步也是最关键的一步。对于一个复杂问题,Agent 需要将其分解为多个原子化的子查询。比如:原始问题:“对比 GPT-4o 和 Claude 3.5 Sonnet 在代码生成任务上的表现,并分析各自的技术路线差异。”Agent 分解结果:“GPT-4o 代码生成能力 benchmark 表现”“Claude 3.5 Sonnet 代码生成能力 benchmark 表现”“GPT-4o 模型架构技术路线”“Claude 3.5 Sonnet 模型架构技术路线”“GPT-4o vs Claude 3.5 代码生成对比评测”这个分解过程本身可以交给「路由 LLM」或利用原始 LLM 的 function calling 能力来实现。关键不是分解得有多细,而是子查询之间要相对独立,避免检索结果高度重叠。2.2 检索路由(Retrieval Routing)分解出子查询后,Agent 需要对每个子查询决定去哪儿检索和怎么检索。这就是检索路由的核心逻辑:# 检索路由的决策伪代码defroute_query(sub_query:str)-RetrievalStrategy:ifneeds_vector_search(sub_query):# 语义匹配需求returnVectorRetrieval(index="default")ifneeds_keyword_search(sub_query):# 精确匹配需求returnBM25Retrieval()ifneeds_structured_data(sub_query):# 结构化数据需求returnSQLRetrieval(database="reports")ifneeds_web_search(sub_query):# 实时信息需求returnWebSearch()ifneeds_hybrid(sub_query):# 混合需求returnHybridRetrieval([vector,bm25])这一步的精妙之处在于:同一个问题下的不同子查询可能需要完全不同的检索策略。比如"对比两模型的 benchmark 表现"可能需要 Web Search(获取最新评测数据),而"分析技术路线差异"则更适合向量检索(从技术论文库中匹配)。2.3 自我反思与重试(Self-Reflection Retry)获取检索结果后,Agent 不是盲目地拼接所有内容交给 LLM 生成答案,而是先做相关性评估:defevaluate_relevance(query:str,retrieved_docs:List[Doc])-float:"""评估检索结果的相关性"""prompt=f"""评估以下文档对查询 '{query}' 的相关性。 返回一个 0-10 的分数和简短理由: 查询:{query}文档摘要:{doc.summaryfordocinretrieved_docs[:5]}评分标准: - 0-3:完全不相关 - 4-6:部分相关但不够深入 - 7-8:相关但缺少细节 - 9-10:高度相关、信息充足 """response=llm.invoke(prompt)returnparse_relevance_score(response)如果评估分数低于阈值(如 6 分),Agent 不会硬着头皮用低质量检索结果回答问题。相反,它会触发重试策略:改写查询:换个角度重新表达问题(如用同义词、调整粒度)切换检索源:向量检索不行就换 BM25,或者试混合检索扩大范围:降低检索阈值,获取更多候选文档补充搜索:对缺失的关键信息点追加一次检索三、动手实践:用 LangGraph 构建 Agentic RAG下面我们基于 LangGraph 构建一个完整的 Agentic RAG 系统。它能够自动分解复杂查询、多策略检索、评估结果质量、并在必要时重试。3.1 环境准备pipinstalllanggraph langchain langchain-openai chromadb sentence-transformers3.2 定义 Agent 状态首先定义 Agent 的状态结构,它将在整个循环中传递:fromtypingimportTypedDict,List,Optional,Annotatedfromlanggraph.graphimportStateGraph,ENDimportoperatorclassAgentState(TypedDict):# 用户原始问题original_query:str# 分解后的子查询列表sub_queries:List[str]# 当前正在处理的子查询索引current_query_idx:int# 检索到的文档(累积)retrieved_docs:Annotated[List[str],operator.add]# 当前检索的相关性评分relevance_score:float# 重试次数retry_count:int# 最大重试次数max_retries:int# Agent 的思考过程记录thought_process:List[str]# 最终答案final_answer:Optional[str]3.3 实现查询分解器fromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportHumanMessage