Agentic-RAG-让Agent自主决策检索策略
> **时效说明**:本文内容以 2026 年 3 月为基准。
Agentic RAG:让 Agent 自主决策检索策略
时效说明:本文内容以 2026 年 3 月为基准。
1.1 先理解标准 RAG 的问题
传统 RAG 固定检索流程(左)与 Agentic RAG 自主决策流程(右)的对比
在讲 Agentic RAG 之前,先理解标准 RAG 为什么有上限。不理解这个,你就不知道 Agentic RAG 在解决什么问题,也不知道什么时候需要它。
标准 RAG 的流程是固定的:用户提问 → 向量检索 → 拼装 Prompt → LLM 生成答案。
这个流程有一个核心假设:所有问题都适合同一套检索策略。这个假设在很多真实场景中不成立。
举几个具体例子:
不需要检索的问题也在检索。用户问"1 + 1 等于多少"、"Python 里怎么定义变量",这类模型早就知道答案的问题,标准 RAG 还是会走完整个检索流程,浪费时间和 token。
一次检索不够用。用户问"张三负责的项目用了哪些技术栈,这些技术栈分别有什么优缺点"。这是一个多跳问题(multi-hop question)——需要先检索张三负责的项目,再用项目名去检索技术栈详情,最后综合分析。标准 RAG 只做一次检索,只能拿到第一跳的信息,答案不完整。
检索策略缺乏灵活性。一个知识库可能包含产品文档、技术手册、FAQ 等不同类型的内容,不同问题应该路由到不同的知识库,标准 RAG 对所有问题一视同仁。
这三个问题的根本原因是一样的:检索策略是硬编码的,不是智能的。
1.2 Agentic RAG 的核心转变:检索从规则变成推理
Agentic RAG 的核心思想可以一句话概括:把检索的决策权交给 Agent,而不是写死在代码里。
在标准 RAG 里,检索策略是开发者在写代码时就固定下来的——"每次都检索 Top-5 相关文档"。在 Agentic RAG 里,检索策略本身成为 Agent 的推理对象:
- 这个问题需要检索吗?(路由决策)
- 需要检索哪些信息?(查询规划)
- 当前检索到的信息够用了吗?(评估决策)
- 如果不够,用什么关键词继续检索?(迭代优化)
这就是"Agentic"的本质:让 LLM 参与流程控制,而不只是生成最终答案。
1.3 四种主要模式
1.3.1 模式一:路由(Routing)
根据问题类型,智能路由到不同的知识库或检索策略。
这是最简单的 Agentic 形式。Router 本质上是一个分类器,判断问题属于哪个领域,然后把它发到对应的知识库。好处是每个知识库可以针对性优化,检索准确率比混在一起高得多。
适合场景:知识库有明确的类别划分,不同类别的最优检索策略不同。
1.3.2 模式二:查询规划(Query Planning)
把复杂问题拆成多个子查询,分别检索,最后合并。
比如用户问"对比 iPhone 和 Android 在拍照、续航、价格三个方面的差异",Query Planner 会把它拆成多个子查询分别检索,然后综合。这比一次性用原始问题检索,召回的信息更全面。
适合场景:多维度对比分析,需要从多个角度收集信息的问题。
1.3.3 模式三:迭代检索(Iterative Retrieval)
检索后评估信息是否充分,不够就继续检索,直到充分为止。
这个模式特别适合多跳问题。Agent 在每次检索后自问:"现在有没有足够的信息来回答这个问题?"没有的话,重新组织关键词再搜一次。
适合场景:需要多步推理的复杂问题,信息可能分散在不同文档中。
1.3.4 模式四:Self-RAG
模型在生成过程中自己决定要不要插入检索,并评估检索结果的可信度。这是最复杂的形式,需要专门训练过的模型或精心设计的 Prompt 模拟。
1.4 用 LangGraph 实现迭代检索
迭代检索是最实用的模式,下面给出完整的 LangGraph 实现。
这段代码的关键设计决策:把"评估信息是否充分"和"优化查询词"都交给 LLM 来做——这就是 Agentic 的本质,让 LLM 不只生成答案,还参与流程控制。
# 安装依赖:pip install langgraph langchain-openai langchain-community faiss-cpu
from typing import TypedDict, List
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
# 定义状态:所有节点共享这个状态,通过它传递信息
class RAGState(TypedDict):
question: str # 用户原始问题
query: str # 当前检索词(可能被优化过)
documents: List[Document] # 检索到的文档(累积所有检索结果)
generation: str # 最终生成的答案
retrieval_count: int # 已检索次数(防止无限循环)
is_sufficient: bool # 当前信息是否充分
# 初始化 LLM 和检索器
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
embeddings = OpenAIEmbeddings()
# 实际项目中从文件加载:
# vectorstore = FAISS.load_local("my_index", embeddings)
# retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
MAX_RETRIEVAL = 3 # 最多检索 3 次,防止无限循环
def retrieve(state: RAGState) -> dict:
"""执行一次检索,累积到已有文档列表"""
docs = retriever.invoke(state["query"])
return {
"documents": state["documents"] + docs, # 累积,不是替换
"retrieval_count": state["retrieval_count"] + 1
}
def grade_documents(state: RAGState) -> dict:
"""让 LLM 评估当前文档是否足以回答问题
这是 Agentic 的关键:用 LLM 替代规则来做判断
"""
grade_prompt = ChatPromptTemplate.from_template("""
你是一个信息充分性评估员。
用户问题:{question}
当前已检索到的文档内容:
{documents}
判断这些文档是否包含足够的信息来完整回答用户的问题。
评判标准:
1. 文档是否直接包含问题所需的关键信息
2. 信息是否完整(不缺少重要的方面)
3. 信息是否足够具体(不只是泛泛的相关内容)
只回答 "sufficient" 或 "insufficient",不要任何其他内容。
""")
docs_text = "\n\n---\n\n".join([
f"文档 {i+1}:\n{d.page_content}"
for i, d in enumerate(state["documents"])
])
result = llm.invoke(
grade_prompt.format_messages(
question=state["question"],
documents=docs_text
)
)
is_sufficient = "sufficient" in result.content.lower()
return {"is_sufficient": is_sufficient}
def refine_query(state: RAGState) -> dict:
"""让 LLM 基于现有文档,生成更精准的查询词
这是 Agentic 的另一个关键:用 LLM 优化检索策略
"""
refine_prompt = ChatPromptTemplate.from_template("""
原始问题:{question}
已尝试的查询词:{query}
已检索到的信息摘要:{documents}
已有信息还不够完整,需要继续检索。
分析一下:现在缺少什么信息?用什么关键词检索能找到这些信息?
请生成一个新的、更精准的查询词来补充缺失的信息。
只返回查询词本身,不要解释,不要其他内容。
""")
docs_text = "\n".join([
d.page_content[:200] + "..." # 只取前 200 字作为摘要,避免 token 过多
for d in state["documents"]
])
result = llm.invoke(
refine_prompt.format_messages(
question=state["question"],
query=state["query"],
documents=docs_text
)
)
new_query = result.content.strip()
print(f"[优化查询] 原查询: '{state['query']}' → 新查询: '{new_query}'")
return {"query": new_query}
def generate(state: RAGState) -> dict:
"""基于所有检索到的文档生成最终答案"""
generate_prompt = ChatPromptTemplate.from_template("""
基于以下文档,回答用户的问题。如果文档中没有相关信息,请如实说明,不要编造。
文档内容:
{documents}
用户问题:{question}
请提供准确、完整的回答:
""")
docs_text = "\n\n---\n\n".join([
f"文档 {i+1}:\n{d.page_content}"
for i, d in enumerate(state["documents"])
])
result = llm.invoke(
generate_prompt.format_messages(
documents=docs_text,
question=state["question"]
)
)
return {"generation": result.content}
def should_continue_retrieval(state: RAGState) -> str:
"""条件判断:继续检索还是直接生成答案
这里决定了 Agent 的行为逻辑
"""
if state["is_sufficient"]:
print(f"[决策] 信息充分,准备生成答案(共检索 {state['retrieval_count']} 次)")
return "generate"
if state["retrieval_count"] >= MAX_RETRIEVAL:
print(f"[决策] 达到最大检索次数 {MAX_RETRIEVAL},用现有信息生成答案")
return "generate"
print(f"[决策] 信息不足,继续检索(已检索 {state['retrieval_count']} 次)")
return "refine_query"
# 构建 Agentic RAG 图
workflow = StateGraph(RAGState)
workflow.add_node("retrieve", retrieve)
workflow.add_node("grade_documents", grade_documents)
workflow.add_node("refine_query", refine_query)
workflow.add_node("generate", generate)
# 定义流程
workflow.add_edge(START, "retrieve") # 开始就检索
workflow.add_edge("retrieve", "grade_documents") # 检索后评估
workflow.add_conditional_edges(
"grade_documents",
should_continue_retrieval, # 根据评估结果决定下一步
{
"generate": "generate", # 信息充分,生成答案
"refine_query": "refine_query" # 信息不足,优化查询
}
)
workflow.add_edge("refine_query", "retrieve") # 优化后重新检索
workflow.add_edge("generate", END)
app = workflow.compile()
def ask(question: str) -> str:
"""对外的问答接口"""
initial_state = RAGState(
question=question,
query=question, # 初始查询词就是原始问题
documents=[],
generation="",
retrieval_count=0,
is_sufficient=False
)
result = app.invoke(initial_state)
print(f"\n共检索 {result['retrieval_count']} 次,使用了 {len(result['documents'])} 份文档")
return result["generation"]
# 使用示例(需要先建立好 retriever)
# answer = ask("张三负责的项目用了哪些技术,各有什么优缺点?")
# print(answer)
代码要点:
grade_documents和refine_query都调用 LLM,这是"Agentic"的核心代价should_continue_retrieval是条件判断节点,决定了 Agent 的决策逻辑MAX_RETRIEVAL = 3是安全阀,防止无限循环
1.5 适合用 Agentic RAG 的场景
多跳推理问题:需要先找 A,用 A 的结果找 B,再用 B 找 C,多步才能得出答案。
需要综合多个文档的问题:对比分析、全面总结类,单次检索往往只能拿到一部分信息。
问题类型多样的场景:有些问题需要检索,有些不需要。路由模式可以避免对简单问题做无效检索。
1.6 不需要 Agentic RAG 的场景
问题类型单一:如果用户的问题基本都是同一类型(比如都是查某个特定知识库的事实性问题),标准 RAG 就够了。
成本敏感:Agentic RAG 每次评估、每次优化查询都是额外的 LLM 调用。原来普通 RAG 每次问答调用 1 次 LLM,Agentic RAG 可能要 3-5 次,成本直接倍增。
延迟敏感:每多一次 LLM 调用就多一些延迟。如果你的应用要求快速响应,评估和优化的时间可能让用户体验变差。
1.7 正确的使用顺序
先把基础 RAG 做好:
- 文档切割合理(chunk size 和 overlap 调到最优)
- 向量化质量高(选对 embedding 模型)
- 检索召回率达标(Top-K 设置合理,必要时用混合检索)
这些基本功扎实之后,如果仍然遇到多跳问题或信息不充分的场景,再考虑加 Agentic 能力。
底层不稳,上层再智能也白搭。
先用标准 RAG 解决 80% 的问题,再用 Agentic RAG 解决剩下那 20% 难搞的问题。这才是正确的工程路径。