🚀 Agentic RAG:从"检索增强生成"到"智能体驱动的检索增强生成",RAG 的下一个范式
📌 本文适合:了解 RAG 基础概念、希望深入理解 Agentic RAG 架构设计与工程实践的开发者
📊 本文所有架构图均使用 Mermaid 绘制,掘金编辑器原生支持 Mermaid 渲染
📖 前言
2023 年,RAG(Retrieval-Augmented Generation,检索增强生成)横空出世,成为 LLM 应用落地的"银弹"。但随着业务场景的复杂化,传统 RAG 的局限性逐渐暴露:
- 🔍 检索质量不稳定:简单的向量相似度检索,经常"答非所问"
- 🔄 单轮检索不够用:复杂问题需要多步推理,一次检索远远不够
- 🛠️ 缺乏工具调用能力:只能从文档里找答案,无法执行操作
- 📊 无法自我纠错:检索到错误信息就直接输出,没有验证机制
于是,Agentic RAG 应运而生 ------ 让 AI Agent 来驱动整个检索、推理、生成过程,实现更智能、更可控的问答系统。
🎯 一、什么是 Agentic RAG?
1.1 传统 RAG 的回顾
先快速回顾传统 RAG 的核心流程:
这个流程简单直接,但存在一个核心问题:它是线性的、无状态的、无法自我调整的。
1.2 Agentic RAG 的定义
Agentic RAG = Agent(智能体) + RAG(检索增强生成)
核心思想:让 LLM 以 Agent 的角色,自主决定何时检索、检索什么、如何验证、是否需要追问。
1.3 核心区别一览
| 维度 | 传统 RAG | Agentic RAG |
|---|---|---|
| 检索策略 | 固定一次检索 | 多轮自适应检索 |
| 查询生成 | 直接使用原始问题 | 智能改写、分解、多路召回 |
| 工具使用 | 无 | 可调用搜索、数据库、API 等 |
| 自我纠错 | 无 | 可验证、可重试、可回溯 |
| 推理链路 | 单步 | 多步推理(Chain-of-Thought) |
| 答案质量 | 取决于首次检索质量 | 迭代优化,质量更高 |
🏗️ 二、Agentic RAG 的核心架构
2.1 整体架构设计
一个完整的 Agentic RAG 系统通常包含以下组件:
2.2 核心组件详解
🧠 Planner(规划器)
规划器负责将复杂问题分解为可执行的子任务:
python
class Planner:
"""将用户问题分解为多个可执行的检索子任务"""
def plan(self, query: str, context: list[str]) -> list[SubTask]:
"""
输入: 用户问题 + 上下文历史
输出: 子任务列表
示例:
输入: "Compare the revenue growth of Company A vs Company B in 2024"
输出: [
SubTask(action="search", query="Company A revenue 2024"),
SubTask(action="search", query="Company B revenue 2024"),
SubTask(action="compare", depends_on=[0, 1]),
]
"""
prompt = f"""
Given the user question and context, break it down into sub-tasks.
User Question: {query}
Context: {context}
Available actions:
- search: Search documents with a query
- sql: Query structured database
- api: Call external API
- reason: Synthesize information from previous steps
Return a JSON list of sub-tasks.
"""
return llm.generate(prompt, response_format=SubTaskList)
🔍 Retriever(多路检索器)
Agentic RAG 的检索不再是单一的向量搜索,而是多路召回 + 智能融合:
python
class MultiRouteRetriever:
"""多路检索器:同时执行多种检索策略,融合结果"""
def __init__(self):
self.retrievers = {
"vector": VectorRetriever(), # 语义相似度检索
"keyword": BM25Retriever(), # 关键词检索
"knowledge_graph": KGRetriever(), # 知识图谱检索
"sql": SQLRetriever(), # 结构化数据查询
}
self.reranker = CrossEncoderReranker()
def retrieve(self, query: str, routes: list[str]) -> list[Document]:
# 1. 并行执行多路检索
results_per_route = {}
for route in routes:
results_per_route[route] = self.retrievers[route].search(query)
# 2. 融合结果
all_results = self._reciprocal_rank_fusion(results_per_route)
# 3. 重排序
reranked = self.reranker.rerank(query, all_results)
return reranked[:TOP_K]
def _reciprocal_rank_fusion(self, results: dict, k=60):
"""RRF 融合算法"""
scores = {}
for route, docs in results.items():
for rank, doc in enumerate(docs):
if doc.id not in scores:
scores[doc.id] = 0
scores[doc.id] += 1 / (k + rank + 1)
return sorted(scores.items(), key=lambda x: -x[1])
✅ Validator(验证器)
这是 Agentic RAG 的关键创新 ------ 对检索结果和生成答案进行验证:
python
class AnswerValidator:
"""验证生成的答案是否准确、完整"""
def validate(self, question: str, answer: str, sources: list[Document]) -> ValidationResult:
# 1. 忠实度检查:答案是否基于检索到的文档?
faithfulness = self._check_faithfulness(answer, sources)
# 2. 相关性检查:答案是否回答了用户的问题?
relevance = self._check_relevance(question, answer)
# 3. 完整性检查:答案是否完整?
completeness = self._check_completeness(question, answer, sources)
return ValidationResult(
is_valid=faithfulness.score > 0.8 and relevance.score > 0.7,
faithfulness=faithfulness,
relevance=relevance,
completeness=completeness,
suggestions=self._generate_suggestions(faithfulness, relevance, completeness),
)
🔧 三、Agentic RAG 的关键设计模式
3.1 自适应检索(Adaptive Retrieval)
Agent 根据问题复杂度决定是否需要检索:
python
class AdaptiveRAGAgent:
"""自适应 RAG Agent:根据问题类型选择不同策略"""
STRATEGIES = {
"simple_fact": "直接用 LLM 知识回答,无需检索",
"complex_query": "多轮检索 + 推理",
"temporal": "需要最新信息,必须检索",
"opinion": "检索多个观点,综合分析",
}
def answer(self, query: str) -> str:
# Step 1: 分类问题类型
query_type = self._classify_query(query)
# Step 2: 根据类型选择策略
strategy = self.STRATEGIES[query_type]
if query_type == "simple_fact":
return self._direct_answer(query)
# Step 3: 执行检索增强流程
return self._agentic_rag_loop(query, strategy)
3.2 查询改写与扩展(Query Transformation)
在检索之前,对用户查询进行智能改写:
python
class QueryTransformer:
"""查询改写器:提升检索质量"""
def transform(self, query: str) -> list[str]:
"""将一个查询改写为多个变体,提升召回率"""
prompt = f"""
Generate 3 different search queries for the following question.
Each query should approach the question from a different angle.
Original: {query}
Return as JSON: {{"queries": ["q1", "q2", "q3"]}}
"""
result = llm.generate(prompt, response_format=QueryVariations)
return result.queries
def decompose(self, complex_query: str) -> list[str]:
"""将复杂查询分解为多个子查询"""
prompt = f"""
Break down this complex question into simpler sub-questions
that can be answered independently:
Question: {complex_query}
Return as JSON: {{"sub_questions": ["q1", "q2", ...]}}
"""
result = llm.generate(prompt, response_format=SubQuestions)
return result.sub_questions
3.3 反思与纠错(Reflection & Self-Correction)
Agent 能够反思自己的回答,发现不足并主动补充:
python
class ReflectiveAgent:
"""具有反思能力的 RAG Agent"""
def answer_with_reflection(self, query: str) -> str:
max_iterations = 3
for iteration in range(max_iterations):
# 1. 生成当前答案
current_answer = self._generate_answer(query)
# 2. 反思:答案是否足够好?
reflection = self._reflect(query, current_answer)
if reflection.is_satisfactory:
return current_answer
# 3. 根据反思结果调整检索策略
if reflection.needs_more_evidence:
additional_docs = self._retrieve_with_refined_query(
reflection.refined_query
)
self.context.extend(additional_docs)
if reflection.has_contradictions:
self._resolve_contradictions(reflection.contradictions)
return current_answer # 返回最佳答案
def _reflect(self, query: str, answer: str) -> Reflection:
prompt = f"""
Critically evaluate this answer:
Question: {query}
Answer: {answer}
Check:
1. Is the answer factually accurate based on the provided context?
2. Does it fully address the question?
3. Are there any contradictions?
4. What additional information would improve the answer?
Return a structured reflection.
"""
return llm.generate(prompt, response_format=Reflection)
3.4 工具调用模式(Tool Use Pattern)
Agent 可以调用各种工具来获取信息或执行操作:
python
class ToolRegistry:
"""工具注册表:管理 Agent 可用的工具"""
def __init__(self):
self.tools = {}
def register(self, name: str, tool: BaseTool):
self.tools[name] = tool
def get_tool_descriptions(self) -> str:
"""生成工具描述,供 LLM 选择使用"""
descriptions = []
for name, tool in self.tools.items():
descriptions.append(f"- {name}: {tool.description}")
return "\n".join(descriptions)
# 注册工具
registry = ToolRegistry()
registry.register("web_search", WebSearchTool())
registry.register("database_query", DatabaseQueryTool())
registry.register("calculator", CalculatorTool())
registry.register("code_executor", CodeExecutorTool())
🏭 四、工程实践:基于 Onyx 的 Agentic RAG 实现
在开源项目 Onyx(原 Danswer)中,Agentic RAG 的实现采用了模块化的架构设计。
4.1 整体流程
4.2 核心代码结构
Onyx 的 Agentic RAG 实现分布在多个模块中:
bash
backend/onyx/
├── chat/
│ ├── agentic/ # Agentic 核心逻辑
│ │ ├── agent_step.py # Agent 单步执行
│ │ ├── tool_calling.py # 工具调用
│ │ └── reasoning.py # 推理链
│ └── orchestrator.py # 编排器
├── document_index/
│ ├── vespa/ # Vespa 向量检索
│ └── hybrid_search.py # 混合检索
└── llm/
└── prompt_cache/ # Prompt 缓存优化
4.3 关键实现细节
意图识别与路由
python
# backend/onyx/chat/agentic/agent_step.py
class AgentStep:
"""Agent 单步执行"""
def determine_next_action(self, query: str, history: list) -> Action:
"""决定下一步动作:检索、工具调用、还是直接回答"""
prompt = f"""
Based on the conversation and current context, determine the next action.
Conversation: {history}
Current Query: {query}
Available actions:
- RETRIEVE: Search for relevant documents
- TOOL_CALL: Use a specific tool
- DIRECT_ANSWER: Answer directly from context
- CLARIFY: Ask user for clarification
- DECOMPOSE: Break down the query into sub-queries
Return the action and parameters.
"""
return llm.generate(prompt, response_format=ActionDecision)
多路混合检索
python
# backend/onyx/document_index/hybrid_search.py
class HybridSearchEngine:
"""混合检索引擎:融合语义检索与关键词检索"""
def search(self, query: str, filters: SearchFilters) -> list[SearchResult]:
# 1. 语义检索(Vespa 向量索引)
semantic_results = self.vespa_index.semantic_search(
query_embedding=self.embedder.embed(query),
filters=filters,
top_k=50,
)
# 2. 关键词检索(BM25)
keyword_results = self.vespa_index.keyword_search(
query_text=query,
filters=filters,
top_k=50,
)
# 3. RRF 融合
fused = self._reciprocal_rank_fusion(
semantic_results,
keyword_results,
alpha=0.7, # 语义检索权重
)
# 4. Cross-Encoder 重排序
reranked = self.reranker.rerank(
query=query,
documents=fused[:20],
)
return reranked[:10]
📊 五、Agentic RAG 的评估体系
5.1 评估维度
| 维度 | 指标 | 说明 |
|---|---|---|
| 检索质量 | Recall@K, NDCG@K | 检索到的文档是否相关 |
| 答案质量 | Faithfulness, Relevance | 答案是否基于文档、是否回答了问题 |
| 推理能力 | Reasoning Accuracy | 多步推理是否正确 |
| 效率 | Latency, Token Usage | 响应时间和 Token 消耗 |
| 用户满意度 | Thumbs Up/Down | 用户反馈 |
5.2 评估代码示例
python
class RAGEvaluator:
"""RAG 评估器"""
def evaluate(self, dataset: list[QAPair]) -> EvaluationReport:
results = []
for qa in dataset:
# 1. 执行 Agentic RAG
answer, traces = self.agent.answer_with_trace(qa.question)
# 2. 计算各项指标
metrics = {
"faithfulness": self._calc_faithfulness(answer, traces.sources),
"answer_relevance": self._calc_relevance(qa.question, answer),
"context_precision": self._calc_context_precision(
qa.question, traces.sources
),
"context_recall": self._calc_context_recall(
qa.ground_truth, traces.sources
),
"latency_ms": traces.total_latency_ms,
"token_usage": traces.total_tokens,
"num_retrieval_steps": len(traces.retrieval_steps),
}
results.append(metrics)
return EvaluationReport(
metrics=results,
summary=self._aggregate_metrics(results),
)
🎨 六、最佳实践与踩坑经验
6.1 ✅ 最佳实践
1. 合理设置最大迭代次数
python
# ❌ 不设上限,可能无限循环
while not answer_is_satisfactory:
answer = agent.iterate()
# ✅ 设置合理的最大迭代次数
MAX_ITERATIONS = 5
for i in range(MAX_ITERATIONS):
answer = agent.iterate()
if answer_is_satisfactory(answer):
break
2. 使用结构化输出保证一致性
python
# ❌ 自由文本输出,难以解析
response = llm.generate("Return a JSON with fields: action, query, reasoning")
# ✅ 使用 Pydantic 模型约束输出
from pydantic import BaseModel
class AgentAction(BaseModel):
action: Literal["search", "answer", "clarify"]
query: str | None = None
reasoning: str
response = llm.generate(prompt, response_format=AgentAction)
3. 实现优雅降级
python
def robust_answer(query: str) -> str:
"""带降级策略的问答"""
try:
# 尝试完整的 Agentic RAG 流程
return agentic_rag_agent.answer(query)
except AgentTimeoutError:
# 超时降级到简单 RAG
return simple_rag_agent.answer(query)
except Exception as e:
# 兜底:直接用 LLM 回答
logger.warning(f"Agentic RAG failed: {e}, falling back to direct LLM")
return llm.generate(f"Answer this question: {query}")
6.2 ⚠️ 踩坑经验
坑 1:Agent 死循环
现象:Agent 反复检索同一个查询,无法得出结论。
解决方案:
python
class LoopDetector:
"""检测并阻止 Agent 陷入循环"""
def __init__(self, window_size=5):
self.history = []
self.window_size = window_size
def is_looping(self, current_action: str) -> bool:
self.history.append(current_action)
if len(self.history) < self.window_size:
return False
# 检查最近 N 步是否有重复
recent = self.history[-self.window_size:]
return len(set(recent)) <= 2 # 超过 60% 重复则判定为循环
坑 2:Token 消耗爆炸
现象:多轮检索 + 推理导致 Token 消耗远超预期。
解决方案:
python
class TokenBudgetManager:
"""Token 预算管理器"""
def __init__(self, max_tokens: int = 4000):
self.max_tokens = max_tokens
self.used_tokens = 0
def can_afford(self, estimated_tokens: int) -> bool:
return self.used_tokens + estimated_tokens <= self.max_tokens
def record_usage(self, tokens: int):
self.used_tokens += tokens
def get_budget_status(self) -> dict:
return {
"max": self.max_tokens,
"used": self.used_tokens,
"remaining": self.max_tokens - self.used_tokens,
"usage_pct": self.used_tokens / self.max_tokens * 100,
}
坑 3:检索结果质量参差不齐
现象:不同数据源的检索结果质量差异大,影响最终答案。
解决方案:
python
class SourceWeightManager:
"""数据源权重管理:根据历史质量动态调整权重"""
def __init__(self):
self.source_weights: dict[str, float] = {}
self.feedback_history: dict[str, list[bool]] = {}
def update_weight(self, source: str, was_helpful: bool):
if source not in self.feedback_history:
self.feedback_history[source] = []
self.feedback_history[source].append(was_helpful)
# 计算新的权重(基于最近 100 次反馈)
recent = self.feedback_history[source][-100:]
self.source_weights[source] = sum(recent) / len(recent)
def get_weighted_results(self, results: list[SearchResult]) -> list[SearchResult]:
for r in results:
r.score *= self.source_weights.get(r.source, 0.5)
return sorted(results, key=lambda x: -x.score)
🔮 七、未来展望
7.1 多模态 Agentic RAG
未来的 Agentic RAG 将不仅处理文本,还能理解和检索图片、视频、音频:
python
class MultiModalAgent:
"""多模态 Agentic RAG Agent"""
def answer(self, query: str, attachments: list[Attachment]) -> str:
# 1. 分析附件类型
for attachment in attachments:
if attachment.type == "image":
# 图像理解 + 视觉检索
image_desc = self.vision_model.describe(attachment.content)
similar_images = self.image_index.search(image_desc)
elif attachment.type == "table":
# 表格解析 + 结构化查询
table_data = self.table_parser.parse(attachment.content)
sql_query = self.generate_sql(query, table_data.schema)
# 2. 多模态融合推理
return self.multi_modal_reason(query, context)
7.2 Agent 协作(Multi-Agent RAG)
多个专业 Agent 协作完成复杂任务:
python
class MultiAgentRAG:
"""多 Agent 协作 RAG"""
def __init__(self):
self.agents = {
"researcher": ResearchAgent(), # 负责信息检索
"analyst": AnalysisAgent(), # 负责数据分析
"writer": WritingAgent(), # 负责内容生成
"reviewer": ReviewAgent(), # 负责质量审核
}
def answer(self, query: str) -> str:
# 1. Researcher 检索信息
research = self.agents["researcher"].research(query)
# 2. Analyst 分析数据
analysis = self.agents["analyst"].analyze(research)
# 3. Writer 生成初稿
draft = self.agents["writer"].write(query, analysis)
# 4. Reviewer 审核并反馈
feedback = self.agents["reviewer"].review(draft)
# 5. Writer 根据反馈修改
final = self.agents["writer"].revise(draft, feedback)
return final
7.3 持续学习与优化
Agentic RAG 将具备从用户反馈中持续学习的能力:
python
class LearningAgent:
"""可学习的 RAG Agent"""
def learn_from_feedback(self, query: str, answer: str, feedback: UserFeedback):
"""从用户反馈中学习,优化检索和生成策略"""
if feedback.rating < 3: # 负面反馈
# 分析失败原因
failure_analysis = self.analyze_failure(query, answer, feedback)
# 更新检索策略
if failure_analysis.failure_type == "retrieval_miss":
self.query_transformer.add_paraphrase_pattern(
failure_analysis.query_pattern
)
# 更新排序权重
if failure_analysis.failure_type == "ranking_error":
self.reranker.adjust_weights(
failure_analysis.feature_importance
)
📝 总结
Agentic RAG 代表了 RAG 技术的进化方向,它将 Agent 的自主决策能力与 RAG 的知识增强能力相结合,解决了传统 RAG 的诸多痛点:
| 痛点 | Agentic RAG 解决方案 |
|---|---|
| 检索质量不稳定 | 多路召回 + 智能重排序 |
| 单轮检索不够 | 多轮迭代检索 + 自适应策略 |
| 缺乏工具调用 | 丰富的工具注册与调用机制 |
| 无法自我纠错 | 反思机制 + 验证器 |
| Token 消耗大 | 预算管理 + 智能缓存 |
核心要点:
- 🧠 让 Agent 决定何时检索,而不是每次都检索
- 🔍 多路召回比单一向量检索更可靠
- ✅ 验证和反思是提升答案质量的关键
- 🛠️ 工具扩展让 RAG 不再局限于文档问答
- 💰 Token 预算管理是生产环境的必修课
📚 参考资料
- Onyx - Open-source Enterprise Search & RAG
- LangChain - Agents and Tool Calling
- LlamaIndex - Agentic RAG
- Self-RAG: Learning to Retrieve, Generate, and Critique
- Corrective RAG
💡 写在最后
Agentic RAG 不是银弹,它在提升答案质量的同时也带来了更高的复杂度和成本。在实际项目中,建议从简单 RAG 开始,根据业务需求逐步引入 Agentic 能力。记住:没有最好的架构,只有最合适的架构。
如果你对 Agentic RAG 有任何问题或想法,欢迎在评论区交流!🎉