mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
2178 字
6 分钟
Agent 规划架构:ReAct、Plan-and-Execute 与 Reflexion
2024-12-16

你让 Agent 帮你完成一个复杂任务:「分析公司最近的销售数据,找出下滑最严重的产品,并给出改进建议。」

Agent 需要做什么?先查询数据库,再分析数据,然后搜索行业趋势,最后生成报告。这不是单步操作,而是一个规划与执行的过程。

问题来了:Agent 如何规划这些步骤?如何决定下一步做什么?如何知道自己做得对不对?

这就是 Agent 规划架构要解决的核心问题。

本文要点#

  • ReAct 架构:推理与行动的交替循环
  • Plan-and-Execute 架构:先规划后执行的分离模式
  • Reflexion 架构:基于自我反思的迭代改进
  • 三种架构的对比与选型指南
  • 代码实现与实战案例
  • 论文解读:ReAct (Yao et al., 2022)

一、为什么需要规划架构?#

1.1 单步决策的局限#

假设你让 Agent「帮我订一张明天去上海的机票」,如果只用简单的 Function Calling:

用户:帮我订一张明天去上海的机票
LLM:决定调用 book_ticket 工具
执行:book_ticket(destination="上海", date="明天")
结果:订票失败——缺少出发地、航班偏好等信息

问题: Agent 不知道订票需要哪些信息,也不知道如何获取缺失信息。

1.2 规划架构的价值#

规划架构让 Agent 能够:

  1. 分解任务:把复杂目标拆解为多个子步骤
  2. 动态调整:根据执行结果调整后续计划
  3. 自我纠错:发现错误并修正
flowchart TD A[复杂任务] --> B{任务分解} B --> C[子任务1] B --> D[子任务2] B --> E[子任务3] C --> F[执行] D --> F E --> F F --> G{结果评估} G -->|成功| H[继续下一步] G -->|失败| I[调整策略] I --> F H --> J[任务完成]

二、ReAct 架构:推理与行动的交替#

2.1 核心思想#

ReAct(Reasoning + Acting)是 2022 年由普林斯顿大学和 Google Research 提出的 Agent 架构。核心思想:让 LLM 在「思考」和「行动」之间交替进行

Thought(思考)→ Action(行动)→ Observation(观察)→ Thought(再思考)→ ...

2.2 ReAct 循环详解#

flowchart TD A[用户输入] --> B[Thought: 思考下一步] B --> C[Action: 决定执行什么] C --> D[执行工具调用] D --> E[Observation: 获取执行结果] E --> F{任务完成?} F -->|否| B F -->|是| G[输出最终答案]

2.3 完整示例:市场调研任务#

任务:「分析某科技公司 2024 年的市场表现」
=== 第 1 轮 ===
Thought: 需要先了解这家公司的基本情况,我应该搜索公司信息
Action: search("某科技公司 2024 年财报")
Observation: 找到公司 2024 年 Q1-Q4 财报链接
=== 第 2 轮 ===
Thought: 有了财报链接,需要读取具体数据
Action: read_document("财报链接")
Observation: 营收 100 亿(+20%),净利润 15 亿(-5%),研发投入 20 亿(+30%)
=== 第 3 轮 ===
Thought: 数据有了,但需要了解行业对比情况
Action: search("2024 年科技行业平均增长率")
Observation: 行业平均增长 10%,净利润率平均 18%
=== 第 4 轮 ===
Thought: 信息足够了,可以总结分析
Action: finish("该公司 2024 年营收增长 20%,超过行业平均..."

2.4 ReAct 的 Prompt 模板#

REACT_PROMPT = """
你是一个智能助手,使用 Thought-Action-Observation 循环来完成任务。
可用工具:
{tools_description}
使用以下格式:
Thought: 思考下一步应该做什么
Action: 工具名称[参数]
Observation: 工具执行结果
... (重复 Thought/Action/Observation)
Thought: 我现在知道最终答案了
Final Answer: 最终回答
开始!
任务:{task}
"""

2.5 ReAct 代码实现#

from typing import List, Dict, Any
import json
class ReActAgent:
def __init__(self, llm_client, tools: Dict[str, callable]):
self.llm = llm_client
self.tools = tools
self.max_iterations = 10
def run(self, task: str) -> str:
"""执行 ReAct 循环"""
history = []
tools_desc = self._format_tools()
for i in range(self.max_iterations):
# 构建当前上下文
context = self._build_context(task, tools_desc, history)
# LLM 生成下一步
response = self.llm.generate(context)
# 解析 Thought 和 Action
thought, action, args = self._parse_response(response)
history.append({"thought": thought, "action": action, "args": args})
# 检查是否完成
if action == "finish":
return args.get("answer", "")
# 执行工具
if action in self.tools:
observation = self.tools[action](**args)
history[-1]["observation"] = observation
else:
history[-1]["observation"] = f"错误:未知工具 {action}"
return "达到最大迭代次数,任务未完成"
def _parse_response(self, response: str):
"""解析 LLM 响应中的 Thought 和 Action"""
lines = response.strip().split("\n")
thought = ""
action = None
args = {}
for line in lines:
if line.startswith("Thought:"):
thought = line.replace("Thought:", "").strip()
elif line.startswith("Action:"):
action_part = line.replace("Action:", "").strip()
# 解析 Action[参数]
if "[" in action_part:
action = action_part.split("[")[0]
args_str = action_part.split("[")[1].rstrip("]")
args = json.loads(args_str) if args_str else {}
else:
action = action_part
elif line.startswith("Final Answer:"):
return thought, "finish", {"answer": line.replace("Final Answer:", "").strip()}
return thought, action, args
def _format_tools(self) -> str:
"""格式化工具描述"""
return "\n".join([
f"- {name}: {func.__doc__}"
for name, func in self.tools.items()
])
def _build_context(self, task: str, tools_desc: str, history: List[Dict]) -> str:
"""构建上下文"""
context = f"任务:{task}\n\n可用工具:\n{tools_desc}\n\n"
for h in history:
context += f"Thought: {h['thought']}\n"
context += f"Action: {h['action']}"
if h.get('args'):
context += f"[{json.dumps(h['args'])}]"
context += "\n"
if h.get('observation'):
context += f"Observation: {h['observation']}\n"
return context
# 使用示例
def search_tool(query: str) -> str:
"""搜索互联网信息"""
return f"搜索结果:{query} 的相关信息..."
def calculate_tool(expression: str) -> str:
"""计算数学表达式"""
try:
return str(eval(expression))
except:
return "计算错误"
agent = ReActAgent(
llm_client=openai_client,
tools={"search": search_tool, "calculate": calculate_tool}
)
result = agent.run("某公司去年营收 1000 万,今年增长 20%,计算今年营收")

2.6 ReAct 的优势与局限#

优势:

  • 思考过程透明,可解释性强
  • 动态调整策略,适应性强
  • 实现简单,易于理解和调试

局限:

  • 每步都需要 LLM 推理,成本较高
  • 可能陷入无效循环(如反复尝试错误的工具)
  • 对于明确可规划的任务,效率不如 Plan-and-Execute

三、Plan-and-Execute 架构:先规划后执行#

3.1 核心思想#

Plan-and-Execute 将任务分为两个阶段:

  1. 规划阶段:LLM 生成完整的执行计划
  2. 执行阶段:按计划逐步执行,失败时可重新规划
flowchart TD A[用户任务] --> B[规划阶段] B --> C[生成完整计划] C --> D[步骤1] D --> E[步骤2] E --> F[步骤3] F --> G{全部成功?} G -->|是| H[输出结果] G -->|否| I[重新规划] I --> B

3.2 与 ReAct 的区别#

flowchart LR subgraph ReAct R1[思考] --> R2[行动] --> R3[观察] --> R4[思考] end subgraph Plan-and-Execute P1[一次性规划] --> P2[执行步骤1] --> P3[执行步骤2] --> P4[执行步骤3] end
特性ReActPlan-and-Execute
规划时机每一步动态规划一次性提前规划
执行方式边思考边执行按计划顺序执行
调整策略每步可调整失败时重新规划
适用场景不确定性高的任务结构化明确的任务
Token 消耗较高(每步推理)较低(规划后批量执行)

3.3 Plan-and-Execute 代码实现#

from pydantic import BaseModel
from typing import List, Optional
class PlanStep(BaseModel):
"""单个计划步骤"""
step_id: int
description: str
tool: str
args: dict
depends_on: List[int] = [] # 依赖的前置步骤
class Plan(BaseModel):
"""完整执行计划"""
steps: List[PlanStep]
expected_output: str
class PlanAndExecuteAgent:
def __init__(self, llm_client, tools: Dict[str, callable]):
self.llm = llm_client
self.tools = tools
self.max_replans = 3
def run(self, task: str) -> str:
"""执行 Plan-and-Execute 流程"""
for attempt in range(self.max_replans):
# 规划阶段
plan = self._create_plan(task)
print(f" 生成的计划:\n{self._format_plan(plan)}")
# 执行阶段
results = {}
success = True
for step in plan.steps:
# 检查依赖是否满足
if not self._check_dependencies(step, results):
success = False
break
# 执行步骤
try:
result = self.tools[step.tool](**step.args)
results[step.step_id] = result
print(f"步骤 {step.step_id}: {step.description} -> 成功")
except Exception as e:
print(f"步骤 {step.step_id} 失败: {e}")
success = False
break
if success:
return self._synthesize_results(plan, results)
print(f" 计划执行失败,尝试重新规划... ({attempt + 1}/{self.max_replans})")
return "任务执行失败,已达到最大重试次数"
def _create_plan(self, task: str) -> Plan:
"""使用 LLM 生成执行计划"""
prompt = f"""
你需要为一个任务生成详细的执行计划。
任务:{task}
可用工具:
{self._format_tools()}
请以 JSON 格式输出计划,格式如下:
{{
"steps": [
{{"step_id": 1, "description": "步骤描述", "tool": "工具名", "args": {{}}, "depends_on": []}}
],
"expected_output": "预期输出描述"
}}
注意:
1. 步骤要有明确的依赖关系
2. 每个步骤只调用一个工具
3. 参数要具体可执行
"""
response = self.llm.generate(prompt)
return Plan.parse_raw(response)
def _check_dependencies(self, step: PlanStep, results: Dict) -> bool:
"""检查步骤依赖是否满足"""
return all(dep_id in results for dep_id in step.depends_on)
def _synthesize_results(self, plan: Plan, results: Dict) -> str:
"""综合所有结果生成最终答案"""
prompt = f"""
任务:{plan.expected_output}
执行结果:
{json.dumps(results, ensure_ascii=False, indent=2)}
请根据以上结果,生成最终答案。
"""
return self.llm.generate(prompt)
def _format_plan(self, plan: Plan) -> str:
"""格式化计划输出"""
lines = []
for step in plan.steps:
deps = f" (依赖: {step.depends_on})" if step.depends_on else ""
lines.append(f" {step.step_id}. {step.description} [{step.tool}]{deps}")
return "\n".join(lines)
def _format_tools(self) -> str:
"""格式化工具描述"""
return "\n".join([
f"- {name}: {func.__doc__}"
for name, func in self.tools.items()
])
# 使用示例
def database_query(sql: str) -> str:
"""执行数据库查询"""
return f"查询结果:{sql}"
def web_search(query: str) -> str:
"""搜索网络信息"""
return f"搜索结果:{query}"
def generate_report(data: str) -> str:
"""生成分析报告"""
return f"报告内容:{data}"
agent = PlanAndExecuteAgent(
llm_client=openai_client,
tools={
"database_query": database_query,
"web_search": web_search,
"generate_report": generate_report
}
)
result = agent.run("分析公司最近的销售趋势并生成报告")

3.4 Plan-and-Execute 输出示例#

生成的计划:
1. 查询最近 6 个月的销售数据 [database_query]
2. 搜索行业销售趋势作为对比 [web_search]
3. 生成综合分析报告 [generate_report] (依赖: [1, 2])
步骤 1: 查询最近 6 个月的销售数据 -> 成功
步骤 2: 搜索行业销售趋势作为对比 -> 成功
步骤 3: 生成综合分析报告 -> 成功
最终结果:根据数据分析,公司销售额...

3.5 Plan-and-Execute 的适用场景#

适合:

  • 任务结构清晰,步骤可预见
  • 需要多次执行相同类型的任务
  • 对执行效率有要求

不适合:

  • 高度不确定性任务(如探索性研究)
  • 中间结果可能改变整体策略的任务

四、Reflexion 架构:自我反思与改进#

4.1 核心思想#

Reflexion(Shinn et al., 2023)在执行循环中加入自我反思环节:

执行 → 评估 → 反思 → 改进策略 → 重新执行

核心创新:让 Agent 对自己的输出进行批判性分析,生成”反思文本”指导后续改进。

flowchart TD A[任务输入] --> B[执行] B --> C{评估结果} C -->|成功| D[输出答案] C -->|失败| E[生成反思] E --> F[存储反思] F --> G[更新策略] G --> B style E fill:#ffeb3b style F fill:#ffeb3b style G fill:#ffeb3b

4.2 Reflexion 的关键组件#

flowchart LR subgraph 执行器 A1[Actor] --> A2[执行任务] end subgraph 评估器 B1[Evaluator] --> B2[评估结果] end subgraph 反思器 C1[Reflector] --> C2[生成反思] end A2 --> B1 B2 -->|失败| C1 C2 --> A1 B2 -->|成功| D[最终答案]

4.3 Reflexion 代码实现#

from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Reflection:
"""反思结果"""
attempt: int
task: str
trajectory: str # 执行轨迹
failure_reason: str # 失败原因
improvement_suggestion: str # 改进建议
class ReflexionAgent:
def __init__(self, llm_client, tools: Dict[str, callable]):
self.llm = llm_client
self.tools = tools
self.max_attempts = 3
self.reflections: List[Reflection] = []
def run(self, task: str) -> str:
"""执行 Reflexion 循环"""
for attempt in range(1, self.max_attempts + 1):
print(f"\n 尝试 {attempt}/{self.max_attempts}")
# 构建上下文(包含之前的反思)
context = self._build_context(task)
# 执行任务
trajectory, result = self._execute(task, context)
# 评估结果
evaluation = self._evaluate(task, result)
if evaluation["success"]:
print(f"任务成功完成!")
return result
# 生成反思
reflection = self._reflect(
attempt=attempt,
task=task,
trajectory=trajectory,
failure_reason=evaluation["reason"]
)
self.reflections.append(reflection)
print(f" 反思:{reflection.improvement_suggestion}")
print("达到最大尝试次数")
return "任务执行失败"
def _execute(self, task: str, context: str) -> tuple:
"""执行任务并返回轨迹和结果"""
# 使用 ReAct 风格执行
trajectory = []
result = ""
prompt = f"""
{context}
任务:{task}
请使用 Thought-Action-Observation 格式执行任务。
"""
response = self.llm.generate(prompt)
trajectory.append(response)
# 解析并执行工具调用
# ... (类似 ReAct 的执行逻辑)
return "\n".join(trajectory), result
def _evaluate(self, task: str, result: str) -> dict:
"""评估执行结果"""
prompt = f"""
任务:{task}
执行结果:{result}
请评估结果是否成功完成了任务。
输出 JSON 格式:
{{"success": true/false, "reason": "失败原因(如果失败)", "score": 0-10}}
"""
response = self.llm.generate(prompt)
return eval(response) # 实际应用中应使用 json.loads
def _reflect(self, attempt: int, task: str, trajectory: str,
failure_reason: str) -> Reflection:
"""生成反思"""
prompt = f"""
任务:{task}
执行轨迹:
{trajectory}
失败原因:{failure_reason}
请分析失败原因并提出改进建议:
1. 哪里出了问题?
2. 为什么会失败?
3. 下次应该如何改进?
输出 JSON 格式:
{{"failure_analysis": "...", "improvement_suggestion": "..."}}
"""
response = self.llm.generate(prompt)
analysis = eval(response)
return Reflection(
attempt=attempt,
task=task,
trajectory=trajectory,
failure_reason=failure_reason,
improvement_suggestion=analysis["improvement_suggestion"]
)
def _build_context(self, task: str) -> str:
"""构建包含反思的上下文"""
context = f"任务:{task}\n\n"
if self.reflections:
context += "=== 之前的尝试和反思 ===\n"
for r in self.reflections:
context += f"尝试 {r.attempt}\n"
context += f"失败原因:{r.failure_reason}\n"
context += f"改进建议:{r.improvement_suggestion}\n\n"
return context
# 使用示例
agent = ReflexionAgent(
llm_client=openai_client,
tools={"search": search_tool, "calculate": calculate_tool}
)
result = agent.run("找出销售额增长最快的产品并分析原因")

4.4 Reflexion 执行示例#

尝试 1/3
Thought: 需要查询销售数据
Action: search("公司销售数据 2024")
Observation: 找到部分数据,但缺少增长率
...
评估:失败 - 缺少完整数据
反思:搜索查询不够精确,应该使用更具体的数据库查询工具而非网络搜索
尝试 2/3
Thought: 根据反思,应该使用数据库查询获取精确数据
Action: database_query("SELECT product, growth_rate FROM sales_2024 ORDER BY growth_rate DESC")
Observation: 产品 A 增长率 45%,产品 B 增长率 32%...
...
任务成功完成!

4.5 Reflexion 的优势#

  1. 持续改进:每次失败都能学到东西
  2. 知识积累:反思可以存储为长期记忆
  3. 提高成功率:论文显示 Reflexion 在多个任务上显著提升成功率
任务类型基础成功率Reflexion 成功率
HumanEval(代码)67%91%
ALFWorld(具身)75%97%
HotPotQA(问答)29%51%

五、三种架构对比与选型指南#

5.1 架构对比表#

维度ReActPlan-and-ExecuteReflexion
核心思想边思考边行动先规划后执行执行+反思+改进
规划粒度单步全局单步+迭代
执行方式串行可并行迭代优化
Token 消耗最高
成功率
执行速度最慢
实现复杂度

5.2 控制流程对比#

flowchart TB subgraph ReAct架构 R1[用户输入] --> R2[Thought] R2 --> R3[Action] R3 --> R4[Observation] R4 --> R5{完成?} R5 -->|否| R2 R5 -->|是| R6[输出] end subgraph Plan-and-Execute架构 P1[用户输入] --> P2[规划] P2 --> P3[执行计划] P3 --> P4{全部成功?} P4 -->|是| P5[输出] P4 -->|否| P6[重新规划] P6 --> P2 end subgraph Reflexion架构 E1[用户输入] --> E2[执行] E2 --> E3[评估] E3 --> E4{成功?} E4 -->|是| E5[输出] E4 -->|否| E6[反思] E6 --> E7[改进策略] E7 --> E2 end

5.3 选型决策树#

flowchart TD A[任务类型] --> B{任务复杂度} B -->|简单/中等| C{是否需要高质量输出?} B -->|复杂| D{步骤是否可预见?} C -->|是| E[Reflexion] C -->|否| F[ReAct] D -->|是| G[Plan-and-Execute] D -->|否| H{是否需要自我纠错?} H -->|是| I[Reflexion] H -->|否| J[ReAct]

5.4 场景推荐#

使用 ReAct 当:
- 任务不确定性高,需要灵活调整
- 需要透明的决策过程
- 资源消耗不是首要考虑
使用 Plan-and-Execute 当:
- 任务步骤清晰可预见
- 需要高效执行多个子任务
- 任务可以并行化
使用 Reflexion 当:
- 任务质量要求高
- 允许多次迭代尝试
- 可以接受更高的资源消耗

5.5 组合使用#

实际项目中,三种架构可以组合使用:

class HybridAgent:
"""混合架构:Plan-and-Execute + Reflexion"""
def __init__(self, llm_client, tools):
self.planner = PlanAndExecuteAgent(llm_client, tools)
self.reflector = ReflexionAgent(llm_client, tools)
def run(self, task: str) -> str:
# 先用 Plan-and-Execute 执行
plan = self.planner.create_plan(task)
result = self.planner.execute_plan(plan)
# 评估结果
if self._is_satisfactory(result):
return result
# 如果不满意,切换到 Reflexion
print("Plan-and-Execute 结果不满意,启用 Reflexion 优化...")
return self.reflector.run(task)

六、论文解读:ReAct (Yao et al., 2022)#

6.1 论文基本信息#

  • 标题:ReAct: Synergizing Reasoning and Acting in Language Models
  • 作者:Shunyu Yao, Jeffrey Zhao, Dian Yu, Nan Du, Ishaan Gulrajani, Karthik Narasimhan, Yuan Cao (Princeton University, Google Research)
  • 发表:ICLR 2023
  • 链接https://arxiv.org/abs/2210.03629

6.2 核心贡献#

1. Reasoning + Acting 融合#

论文发现:仅推理(CoT)缺乏外部知识,仅行动缺乏规划能力。ReAct 将两者结合:

纯推理(CoT):
用户问题 → 思考 → 思考 → 思考 → 回答
问题:可能产生幻觉,缺乏事实依据
纯行动:
用户问题 → 行动 → 观察 → 行动 → 观察 → 回答
问题:缺乏规划,容易盲目行动
ReAct:
用户问题 → 思考 → 行动 → 观察 → 思考 → 行动 → 观察 → 回答
优势:有规划、有依据、可解释

2. 四种模式对比#

论文对比了四种模式:

模式描述特点
Act-only只有行动盲目执行,容易走偏
Reason-only (CoT)只有推理产生幻觉,缺乏验证
ReAct推理+行动交替平衡规划与执行
ReAct + Retrieval增加知识检索增强事实准确性

3. 实验结果#

在 HotPotQA 和 Fever 两个基准测试上:

xychart-beta title "HotPotQA 准确率对比" x-axis ["Act-only", "CoT", "ReAct", "ReAct+R"] y-axis "准确率 %" 0 --> 100 bar [28, 29, 27, 35]

关键发现:

  • ReAct 单独使用时准确率不高(因为缺乏知识)
  • 但 ReAct + Retrieval 组合后大幅提升
  • ReAct 的决策过程更透明、可解释

4. 错误分析#

论文分析了各模式的错误类型:

Act-only 错误:
- 搜索词不精确(31%)
- 盲目跟随搜索结果(27%)
CoT 错误:
- 事实性幻觉(39%)
- 推理链断裂(24%)
ReAct 错误:
- 工具调用格式错误(21%)
- 搜索策略不当(19%)

6.3 论文启示#

  1. 推理和行动应结合:不能偏废
  2. 外部工具很重要:ReAct 需要配套工具才能发挥最大价值
  3. 可解释性是优势:思维链让决策过程透明
  4. 仍有改进空间:Reflexion、工具增强等后续工作

七、实战案例:构建智能调研 Agent#

7.1 需求描述#

构建一个能完成市场调研任务的 Agent:

  1. 搜索行业信息
  2. 分析数据趋势
  3. 生成调研报告
  4. 质量检查和优化

7.2 选择架构#

分析需求特点:

  • 步骤相对明确(搜索→分析→生成)
  • 输出质量要求高
  • 需要迭代优化

决策:使用 Plan-and-Execute + Reflexion 混合架构

7.3 完整实现#

from typing import Dict, List, Any
from dataclasses import dataclass
import json
@dataclass
class ResearchTask:
"""调研任务"""
topic: str
requirements: List[str]
deadline: str = None
@dataclass
class ResearchResult:
"""调研结果"""
summary: str
key_findings: List[str]
data_sources: List[str]
confidence_score: float
class ResearchAgent:
"""智能调研 Agent"""
def __init__(self, llm_client, tools: Dict[str, callable]):
self.llm = llm_client
self.tools = tools
self.reflections = []
self.max_iterations = 3
def research(self, task: ResearchTask) -> ResearchResult:
"""执行调研任务"""
for iteration in range(self.max_iterations):
print(f"\n{'='*50}")
print(f"第 {iteration + 1} 轮调研")
print(f"{'='*50}")
# 阶段 1:规划
plan = self._plan_research(task)
self._print_plan(plan)
# 阶段 2:执行
results = self._execute_plan(plan)
# 阶段 3:综合
draft = self._synthesize_results(task, results)
# 阶段 4:质量检查
evaluation = self._evaluate_quality(task, draft)
if evaluation["score"] >= 8:
print(f"\n调研完成!质量评分:{evaluation['score']}/10")
return self._format_result(draft, results)
# 阶段 5:反思并改进
reflection = self._reflect_on_failure(
task, plan, results, evaluation
)
self.reflections.append(reflection)
print(f"\n 改进建议:{reflection['improvement']}")
print("\n 达到最大迭代次数,返回最佳结果")
return self._format_result(draft, results)
def _plan_research(self, task: ResearchTask) -> List[Dict]:
"""规划调研步骤"""
prompt = f"""
你是一个市场调研专家。请为以下任务制定详细的调研计划。
调研主题:{task.topic}
具体要求:{json.dumps(task.requirements, ensure_ascii=False)}
可用工具:
- search_web: 搜索网络信息
- query_database: 查询内部数据库
- analyze_data: 分析数据趋势
- fetch_report: 获取行业报告
请输出 JSON 格式的计划:
[
{{
"step": 1,
"action": "工具名称",
"params": {{"参数": "值"}},
"purpose": "这步的目的"
}}
]
注意:根据之前的反思调整计划。
当前反思历史:{json.dumps(self.reflections[-1] if self.reflections else {}, ensure_ascii=False)}
"""
response = self.llm.generate(prompt)
return json.loads(response)
def _execute_plan(self, plan: List[Dict]) -> Dict:
"""执行调研计划"""
results = {}
for step in plan:
step_num = step["step"]
action = step["action"]
params = step["params"]
purpose = step["purpose"]
print(f"\n 步骤 {step_num}: {purpose}")
print(f" 工具: {action}, 参数: {params}")
try:
result = self.tools[action](**params)
results[step_num] = {
"success": True,
"data": result,
"purpose": purpose
}
print(f" 成功")
except Exception as e:
results[step_num] = {
"success": False,
"error": str(e),
"purpose": purpose
}
print(f" 失败: {e}")
return results
def _synthesize_results(self, task: ResearchTask, results: Dict) -> str:
"""综合结果生成报告"""
prompt = f"""
请根据调研结果生成市场调研报告。
调研主题:{task.topic}
具体要求:{json.dumps(task.requirements, ensure_ascii=False)}
调研数据:
{json.dumps(results, ensure_ascii=False, indent=2)}
请生成结构化的调研报告,包括:
1. 市场概况
2. 关键发现
3. 数据支撑
4. 建议结论
"""
return self.llm.generate(prompt)
def _evaluate_quality(self, task: ResearchTask, draft: str) -> Dict:
"""评估报告质量"""
prompt = f"""
请评估以下调研报告的质量。
调研主题:{task.topic}
具体要求:{json.dumps(task.requirements, ensure_ascii=False)}
报告内容:
{draft}
请从以下维度评分(1-10 分):
1. 完整性:是否覆盖所有要求?
2. 准确性:数据是否可靠?
3. 可读性:结构是否清晰?
4. 洞察深度:分析是否深入?
输出 JSON:
{{
"score": 总分,
"completeness": 分数,
"accuracy": 分数,
"readability": 分数,
"insight": 分数,
"issues": ["问题1", "问题2"]
}}
"""
response = self.llm.generate(prompt)
return json.loads(response)
def _reflect_on_failure(self, task: ResearchTask, plan: List[Dict],
results: Dict, evaluation: Dict) -> Dict:
"""反思失败原因"""
prompt = f"""
调研任务未达标,请分析原因并提出改进建议。
任务:{task.topic}
计划:{json.dumps(plan, ensure_ascii=False)}
结果问题:{json.dumps(evaluation["issues"], ensure_ascii=False)}
请分析:
1. 计划是否合理?
2. 数据是否充足?
3. 分析是否深入?
输出 JSON:
{{
"root_cause": "根本原因",
"improvement": "改进建议",
"next_plan_adjustments": ["调整1", "调整2"]
}}
"""
response = self.llm.generate(prompt)
return json.loads(response)
def _format_result(self, draft: str, results: Dict) -> ResearchResult:
"""格式化最终结果"""
# 提取关键信息
return ResearchResult(
summary=draft[:200] + "...",
key_findings=[], # 从 draft 中提取
data_sources=[str(k) for k in results.keys()],
confidence_score=0.85
)
def _print_plan(self, plan: List[Dict]):
"""打印计划"""
print("\n 调研计划:")
for step in plan:
print(f" {step['step']}. {step['purpose']} ({step['action']})")
# 使用示例
def search_web(query: str) -> str:
"""搜索网络信息"""
return f"搜索结果:{query} 的相关信息..."
def query_database(sql: str) -> str:
"""查询数据库"""
return f"查询结果:{sql}"
def analyze_data(data: str) -> str:
"""分析数据"""
return f"分析结果:{data}"
def fetch_report(industry: str) -> str:
"""获取行业报告"""
return f"报告:{industry} 行业分析"
# 创建 Agent
agent = ResearchAgent(
llm_client=openai_client,
tools={
"search_web": search_web,
"query_database": query_database,
"analyze_data": analyze_data,
"fetch_report": fetch_report
}
)
# 执行调研任务
task = ResearchTask(
topic="新能源汽车市场趋势分析",
requirements=[
"市场规模及增长率",
"主要竞争者分析",
"技术发展趋势",
"政策影响"
]
)
result = agent.research(task)

7.4 执行示例输出#

==================================================
第 1 轮调研
==================================================
调研计划:
1. 获取新能源汽车行业报告 (fetch_report)
2. 搜索市场增长数据 (search_web)
3. 分析竞争格局 (analyze_data)
4. 查询政策信息 (query_database)
步骤 1: 获取新能源汽车行业报告
工具: fetch_report, 参数: {"industry": "新能源汽车"}
成功
步骤 2: 搜索市场增长数据
工具: search_web, 参数: {"query": "2024年新能源汽车市场规模增长率"}
成功
步骤 3: 分析竞争格局
工具: analyze_data, 参数: {"data": "前两步的数据"}
成功
步骤 4: 查询政策信息
工具: query_database, 参数: {"sql": "SELECT * FROM policies WHERE industry='新能源汽车'"}
失败: 数据库连接超时
质量评分:6/10
- 缺少政策影响分析
- 数据来源单一
改进建议:增加政策信息的搜索渠道,不依赖单一数据库
==================================================
第 2 轮调研
==================================================
调研计划:
1. 获取新能源汽车行业报告 (fetch_report)
2. 搜索市场增长数据 (search_web)
3. 搜索新能源汽车补贴政策 (search_web) ← 调整
4. 分析竞争格局 (analyze_data)
...
调研完成!质量评分:8/10

常见问题 FAQ#

Q1:ReAct 和 Chain-of-Thought 有什么区别?

A:Chain-of-Thought(思维链)是纯粹的推理,ReAct 是推理 + 行动的结合。CoT 只”想”,ReAct 会”想”也会”做”。

Q2:Plan-and-Execute 的计划失败了怎么办?

A:两种策略:一是重新规划,根据失败原因调整计划;二是回退到 ReAct 模式,动态调整。

Q3:Reflexion 反思多次还是失败怎么办?

A:设置最大迭代次数,多次失败后可以:

  1. 降低任务复杂度
  2. 请求人工介入
  3. 返回部分结果 + 说明

Q4:如何选择合适的架构?

A:

  • 简单任务、需要快速响应 → ReAct
  • 任务步骤清晰 → Plan-and-Execute
  • 质量要求高、可接受多轮迭代 → Reflexion
  • 实际项目常组合使用

Q5:这些架构可以和 RAG 结合吗?

A:可以。RAG 作为工具被 Agent 调用。例如在 ReAct 的 Action 步骤中调用 RAG 获取知识,或者在 Plan-and-Execute 的计划中包含 RAG 检索步骤。


小结#

Agent 规划架构是 Agent 能力的核心:

架构一句话总结适用场景
ReAct边想边做,灵活适应不确定性高的任务
Plan-and-Execute先规划后执行,高效结构化任务
Reflexion做完反思,持续改进高质量要求任务

选择建议:

  • 从 ReAct 开始,理解基本循环
  • 需要效率时切换到 Plan-and-Execute
  • 需要质量时加入 Reflexion
  • 复杂场景组合使用

三种架构不是互斥的,而是互补的。实际项目中,混合使用往往效果最好。


下篇预告#

规划架构解决了「怎么做事」的问题,但 Agent 还需要记住之前的对话、拥有专业技能、连接外部数据源。


参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Agent 规划架构:ReAct、Plan-and-Execute 与 Reflexion
https://blog.souloss.com/posts/machine-learning/agent-guide/react-and-planning-architecture/
作者
Souloss
发布于
2024-12-16
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时