Agentic RAG 的核心变化在于:它把"检索"从一个固定的预处理步骤,变成了大模型在推理过程中可以自主决策、反复调用的工具。标准 RAG 是"一次检索,然后生成",而 Agentic RAG 是"边想边查,直到信息足够再回答"。
🧠 核心机制:推理与检索的循环
Agentic RAG 通常遵循 ReAct(Reason + Act)模式。大模型作为"智能体",在每一轮循环中决定下一步做什么:
推理(Reason):分析当前问题,判断已有信息是否足够。如果不够,明确还缺什么。
行动(Act):调用一个"工具"来获取信息。这个工具可以是一个向量检索器、一个 SQL 查询接口、一个网页搜索 API,甚至是一个计算器。
观察(Observe):接收工具返回的结果,更新自己对问题的理解。
循环或终止:如果信息仍然不足,回到第 1 步继续;如果已经足够,则生成最终答案。
与标准 RAG 的关键区别在于决策权。在 Agentic RAG 中,模型自己决定"要不要查"、"查哪里"、"查几次"。例如,面对一个简单问题,它可能直接回答而不检索;面对复杂问题,它可能先查产品目录,再根据结果去法规库查召回信息。
💻 编码示例:基于 LlamaIndex ReAct Agent
以下示例展示了一个最小的 Agentic RAG 实现:将两个不同的检索器(分别对应"公司政策"和"员工信息")封装为工具,交给一个 ReAct 智能体来调度。
python
依赖:pip install llama-index llama-index-vector-stores-chroma chromadb
import os
os.environ"OPENAI_API_KEY" = "your-key"
import chromadb
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
1. 构建两个独立的向量索引(对应两个"知识源")
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
chroma_client = chromadb.Client()
索引 A:公司政策
policy_collection = chroma_client.get_or_create_collection("policies")
policy_collection.add(
ids="1", "2",
documents=[
"差旅政策:员工必须通过公司门户预订差旅。经济舱机票和标准酒店房间可报销。",
"休假政策:全职员工每年享有 20 天带薪休假,需提前两周在 HR 门户申请。"
]
)
policy_index = VectorStoreIndex.from_vector_store(
ChromaVectorStore(chroma_collection=policy_collection),
embed_model=embed_model
)
policy_engine = policy_index.as_query_engine(similarity_top_k=1)
索引 B:员工信息
employee_collection = chroma_client.get_or_create_collection("employees")
employee_collection.add(
ids="1", "2",
documents=[
"John Smith 是工程部的软件工程师,2023 年 1 月 15 日入职。",
"Sarah Johnson 是市场部的市场经理,2022 年 8 月 1 日入职。"
]
)
employee_index = VectorStoreIndex.from_vector_store(
ChromaVectorStore(chroma_collection=employee_collection),
embed_model=embed_model
)
employee_engine = employee_index.as_query_engine(similarity_top_k=1)
2. 将检索器封装为 Agent 可调用的"工具"
tools = [
QueryEngineTool(
query_engine=policy_engine,
metadata=ToolMetadata(
name="company_policies",
description="查询公司政策,包括差旅、休假、着装规范等。输入应为具体问题。"
)
),
QueryEngineTool(
query_engine=employee_engine,
metadata=ToolMetadata(
name="employee_directory",
description="查询员工信息,包括姓名、部门、职位和入职日期。输入应为具体问题。"
)
)
]
3. 创建 ReAct Agent
llm = OpenAI(model="gpt-4o", temperature=0.1)
agent = ReActAgent.from_tools(tools, llm=llm, verbose=True)
4. 提问:Agent 需要先查员工信息,再查政策,才能回答
response = agent.chat(
"John Smith 是哪一年入职的?根据他的入职年份,他能享受多少天年假?"
)
print(response)
运行逻辑:Agent 收到问题后,不会直接回答。它会先判断需要"John Smith 的入职年份"和"休假政策"两个信息,然后依次调用 employee_directory 和 company_policies 两个工具,最后综合两边的结果生成答案。标准 RAG 很难在一次检索中同时覆盖两个不同的知识源,而 Agent 可以通过多轮工具调用来完成。
⚖️ 何时使用 Agentic RAG
Agentic RAG 并非在所有场景下都优于标准 RAG。微软的架构指南明确指出,每个 Agent 推理步骤都会增加延迟、Token 消耗和系统复杂度。因此,它更适合以下场景:
多步推理:答案需要从一个来源获取信息,再据此查询另一个来源(如上面的示例)。
动态源选择:模型需要在运行时判断该查哪个数据库或 API。
查询分解:复杂问题需要拆成多个子查询分别执行。
迭代精炼:第一次检索结果不够,需要根据缺口调整查询词再试一次。
对于简单的单跳问答(一次检索就能找到答案),标准 RAG 仍然是更经济、更快速的选择。