【实战智能体】《大模型应用开发_动手做AI_Agent》_126.[第7章 Agent实战之智能调度] Plan-and-Execute vs ReAct——两种Agent范式的本质区别

为什么你的Agent总在"想"和"做"之间反复横跳?Plan-and-Execute与ReAct的本质差异,决定了你的AI是"战略家"还是"急先锋"——选错范式,Agent性能直接腰斩!
目录
- 一、范式初识:从人类思维说起
- 二、Plan-and-Execute:先谋后动的战略家
- 三、ReAct:边想边做的急先锋
- 四、核心差异对比:四维拆解法
- 五、实战选型指南:什么场景用什么
- 六、代码层面的关键实现差异
- 七、混合范式:未来的演进方向
嗨,大家好呀,我是你的老朋友精通代码大仙。接下来我们一起学习 《大模型应用开发_动手做AI_Agent》,震撼你的学习轨迹!
“磨刀不误砍柴工,但磨太久刀,柴都被别人砍完了。”
这句糙话,道尽了我们程序员做Agent时的纠结。你是不是也这样——刚开始学Agent开发,看到网上各种"智能体"Demo炫酷得不行,自己动手一写,要么Agent想太多不动手,要么动手了才发现路走偏了?
第7章我们进入Agent实战的核心地带:智能调度。而调度的灵魂,就在于你选什么范式(Paradigm)。Plan-and-Execute和ReAct,这两个名字你肯定听过,但它们的本质区别到底是什么?为什么同样的任务,换种范式效果天差地别?
今天这篇,我们就把这层窗户纸捅破。选错范式,你的Agent可能在高并发场景下Token账单爆炸;选对范式,复杂任务也能行云流水。这不是玄学,是工程决策。
一、范式初识:从人类思维说起
点题:两种范式对应人类的两种做事风格
咱们先不搞那些学术定义,聊聊生活。
你周末要搞个大扫除,有两种搞法:
第一种:先拿张纸,把"擦窗户、拖地、整理衣柜、洗床单"列个顺序,估计每项多久,然后按计划一项项做完。这叫Plan-and-Execute。
第二种:拿起抹布就开始擦,擦着擦着发现窗户太脏得先喷清洁剂,喷完等的时候顺手把地扫了,扫地发现拖把坏了又下单买新的……边干边调整。这叫ReAct(Reasoning + Acting)。
两种都能完成大扫除,但心态完全不同,适用场景也完全不同。
Agent的这两种范式,正是对人类这两种思维模式的建模。
痛点分析:新手最容易犯的"范式混淆症"
我见过太多同学,代码一跑起来就蒙圈:
“我用ReAct做数据分析,让它查三个表做关联,结果它查完第一个表就开始瞎分析,后面两个表完全忘了查……”
这就是典型的范式错配。ReAct的"边想边做"模式,天生不适合需要前置全局信息的任务。它的工作记忆(context window)在反复推理中被消耗,容易"顾头不顾尾"。
另一个极端:
“我用Plan-and-Execute做客服机器人,用户问’你们支持退款吗’,它非要先规划:‘步骤1,理解问题;步骤2,查询政策;步骤3,组织语言……’,用户等了3秒才收到回复。”
简单查询类任务,Plan-and-Execute的"仪式感"反而成了累赘。
解决方案:先理解本质,再谈选型
记住这个口诀:
复杂任务看全局,用Plan;简单任务要响应,用ReAct;不确定时,先ReAct探路,复杂子任务再Plan。
具体判断标准:
- 任务步骤是否可预先确定?是→Plan,否→ReAct
- 执行过程中是否需要频繁外部反馈?是→ReAct,否→Plan
- 对延迟敏感还是质量敏感?延迟敏感→ReAct,质量敏感→Plan
小结
范式不是"哪个更好",是"哪个更合适"。理解人类思维的两种模式,是选对范式的第一步。
二、Plan-and-Execute:先谋后动的战略家
点题:三层架构,环环相扣
Plan-and-Execute,直译"规划-执行",但它的完整形态其实是Plan-Execute-Reflect三层循环。
Planner(规划器):大模型的"慢思考"模式,把复杂任务拆解为可执行的子任务序列。这里的输出是结构化的计划,不是自然语言。
Executor(执行器):可以是另一个大模型(专门做执行),也可以是确定性代码(调用API、查数据库)。关键是按计划执行,不擅自发挥。
Re-Planner(重规划器):当执行结果与预期不符时,触发重新规划。这是容错机制,也是Plan-and-Execute能处理动态环境的关键。
痛点分析:规划阶段的"过度自信"与"规划失效"
新手写Planner,最容易踩两个坑。
坑一:过度规划
# 错误的Planner输出示例
plan = """
1. 理解用户意图
2. 分析情感倾向
3. 识别关键实体
4. 查询知识库
5. 生成候选回复1
6. 生成候选回复2
7. 评估回复质量
8. 选择最优回复
9. 格式化输出
"""
一个"查天气"的请求,规划了9步。Planner把简单问题复杂化,执行器跟着受罪,Token疯狂燃烧。
坑二:计划与执行脱节
# Planner生成的计划
plan = ["搜索2024年Python教程", "筛选评分>4.5的", "按发布时间排序"]
# 但Executor的可用工具只有
tools = ["web_search", "calculator"] # 没有筛选和排序工具!
计划里假设的能力,执行器根本没有。结果执行到一半报错,或者执行器"自由发挥"偏离计划。
解决方案:让规划"可执行、可验证、可回滚"
可执行:Planner必须知道Executor有什么工具。用**工具描述(Tool Description)**约束规划输出。
# 正确的做法:Planner接收工具列表
available_tools = [
{"name": "web_search", "description": "搜索网络信息", "params": {"query": "string"}},
{"name": "read_file", "description": "读取本地文件", "params": {"path": "string"}}
]
# Planner输出必须匹配工具名和参数
plan = [
{"step": 1, "tool": "web_search", "params": {"query": "2024年Python教程"}},
{"step": 2, "tool": "read_file", "params": {"path": "/tmp/search_result.txt"}}
]
可验证:每个子任务要有明确的完成标准(Done Criteria)。
plan = [
{
"step": 1,
"task": "获取北京天气",
"tool": "weather_api",
"params": {"city": "北京"},
"done_criteria": "返回结果包含temperature和condition字段"
}
]
可回滚:执行失败时,能定位到具体步骤,选择重试、跳过或重新规划。
class PlanExecutor:
def execute(self, plan):
for i, step in enumerate(plan):
try:
result = self.execute_step(step)
self.checkpoint.save(i, result) # 保存检查点
except Exception as e:
# 三种策略
return self.retry(step) # 重试
# return self.skip(step) # 跳过
# return self.replan(plan, i, e) # 从第i步重新规划
小结
Plan-and-Execute的精髓是**“谋定而后动,动则有据,败则可返”**。规划器是大脑,执行器是手脚,检查点是安全绳。
三、ReAct:边想边做的急先锋
点题:Thought-Action-Observation循环
ReAct的论文标题很直白:《ReAct: Synergizing Reasoning and Acting in Language Models》。推理与行动的协同,是它的核心。
这个循环的关键在于:每一步都基于最新信息做决策。没有预设的计划,只有"当下最优"的选择。
典型的ReAct轨迹长这样:
Question: 2024年诺贝尔物理学奖得主是谁?他们因什么获奖?
Thought 1: 我需要搜索2024年诺贝尔物理学奖的最新信息。
Action 1: Search["2024年诺贝尔物理学奖得主"]
Observation 1: 2024年诺贝尔物理学奖授予John J. Hopfield和Geoffrey E. Hinton...
Thought 2: 我已经知道得主名字,但需要确认他们的具体贡献。
Action 2: Search["Hopfield Hinton 诺贝尔物理学奖 获奖原因"]
Observation 2: 他们因"基础性发现和发明,使使用人工神经网络实现机器学习成为可能"而获奖。
Thought 3: 我现在有足够信息回答用户了。
Final Answer: 2024年诺贝尔物理学奖授予...
痛点分析:陷入"思考漩涡"与"行动瘫痪"
ReAct的灵活性是双刃剑,新手常遇到两种故障模式。
故障一:过度思考(Over-thinking)
Thought 1: 用户问的是北京天气,我需要确认"北京"是指中国首都还是其他同名地点。
Thought 2: 如果是中国首都,我需要调用天气API;如果是其他地点,可能需要澄清。
Thought 3: 但考虑到用户用中文提问,大概率指中国首都。
Thought 4: 不过为了准确,我应该先确认地点...
Thought 5: 但确认会增加交互轮次,影响体验...
...(无限循环)
模型在"想"上消耗大量Token,迟迟不行动。这在GPT-4等强推理模型上尤其明显——它们太"谨慎"了。
故障二:短视行动(Short-sighted Acting)
Thought 1: 用户要比较iPhone 15和华为Mate 60。
Action 1: Search["iPhone 15 参数"]
Observation 1: [iPhone 15详细参数...]
Thought 2: 我已经拿到iPhone 15信息,可以回复用户了。
Final Answer: iPhone 15的主要参数是...
完全忘了还要查华为Mate 60!ReAct没有全局计划,容易"见树不见林"。
解决方案:用结构约束和记忆增强驯服ReAct
结构约束:强制输出格式
REACT_PROMPT = """你必须按以下格式响应:
Thought: [你的推理过程,必须包含:1)当前已知信息 2)还缺什么信息 3)下一步行动理由]
Action: [工具名,必须是以下之一: Search, Calculator, GetWeather]
Action Input: [工具参数]
如果信息已足够:
Final Answer: [直接回答用户]
规则:
- Thought必须分析"是否已收集全部必要信息"
- 比较类问题必须收集全部比较对象的信息后才能回答
- 禁止在信息不全时输出Final Answer
"""
记忆增强:维护关键状态
class ReActAgent:
def __init__(self):
self.collected_info = {} # 已收集的信息
self.pending_goals = [] # 待完成的目标
def run(self, query):
# 初始化目标
self.pending_goals = self.extract_goals(query) # ["查iPhone15", "查Mate60", "比较"]
while self.pending_goals:
thought = self.llm.generate_thought(
query=query,
collected=self.collected_info,
pending=self.pending_goals
)
action, action_input = self.parse_action(thought)
obs = self.execute(action, action_input)
# 更新状态和检查目标完成
self.collected_info.update(self.extract_info(obs))
self.pending_goals = self.update_goals(self.pending_goals, self.collected_info)
return self.synthesize_answer(self.collected_info)
截断保护:防止无限循环
def run_with_limits(self, query, max_steps=10, max_tokens=4000):
for step in range(max_steps):
if self.total_tokens > max_tokens:
return self.fallback_response("思考过长,请简化问题")
# ...正常执行
小结
ReAct是"敏捷开发"思维:快速迭代,小步快跑。但需要结构约束防止发散,记忆机制弥补短视,熔断机制防止失控。
四、核心差异对比:四维拆解法
点题:从四个维度看透本质
| 维度 | Plan-and-Execute | ReAct |
|---|---|---|
| 思维模式 | 瀑布式:先全局规划,再分步执行 | 敏捷式:边执行边调整 |
| Token消耗 | 规划阶段集中消耗,执行阶段可控 | 持续消耗,随步数线性增长 |
| 错误恢复 | 检查点回滚,重新规划 | 下一步即时修正,无全局回滚 |
| 可解释性 | 计划即文档,执行轨迹清晰 | 需追溯思考链,理解成本较高 |
痛点分析:只看表面差异,忽视深层trade-off
很多同学的对比停留在"一个有计划一个没计划",导致选型时只看任务复杂度,忽略了其他关键因素。
真实案例:客服系统的选型灾难
某团队做智能客服,选了Plan-and-Execute,理由是"用户问题可能涉及多轮查询,需要规划"。结果上线后发现:
- 80%的查询是单轮问答(“你们营业时间?”“怎么退款?”)
- Plan的 overhead 让平均响应延迟从1.5秒变成4秒
- 用户投诉"机器人反应慢"
他们只看了"最复杂的情况",没看分布。
另一个案例:数据分析Agent用ReAct,用户问"对比我司和竞品过去三年的营收、利润、增长率"。
- ReAct查完2021年营收就开始分析,忘了还有2022、2023
- 或者查完营收忘了查利润
- 三轮对话后context window爆炸,早期信息丢失
他们只看了"灵活性",没看信息完整性需求。
解决方案:建立多维决策矩阵
def select_paradigm(task_profile):
"""
任务画像决定范式选择
"""
score_plan = 0
score_react = 0
# 维度1:步骤可预测性
if task_profile["steps_predictable"]:
score_plan += 2
else:
score_react += 2
# 维度2:信息依赖模式
if task_profile["needs_global_info"]: # 需要全局信息才能决策
score_plan += 2
if task_profile["feedback_driven"]: # 强依赖外部反馈
score_react += 2
# 维度3:延迟敏感度
if task_profile["latency_sensitive"]:
score_react += 1 # ReAct可以早返回,但注意是"可以"不是"一定"
# 维度4:容错成本
if task_profile["error_cost_high"]: # 错误代价高(如医疗、金融)
score_plan += 2 # Plan的可回滚更有价值
# 维度5:任务长度
if task_profile["expected_steps"] > 10:
score_plan += 1 # ReAct长链条容易失控
return "Plan-and-Execute" if score_plan >= score_react else "ReAct"
实际决策时,还要考虑混合策略:
# 外层用ReAct快速响应,复杂子任务用Plan-and-Execute
def hybrid_agent(user_query):
# 第一步:ReAct判断意图和复杂度
intent_analysis = react_classifier.classify(user_query)
if intent_analysis["complexity"] == "simple":
return react_agent.answer(user_query) # 简单查询,ReAct直接答
elif intent_analysis["complexity"] == "complex":
# 复杂任务,提取子任务用Plan-and-Execute
subtasks = intent_analysis["subtasks"]
return plan_execute_agent.run(subtasks)
else:
# 不确定,先ReAct探路,必要时切换
return adaptive_agent.run(user_query)
小结
没有银弹。Plan-and-Execute是"重型武器",ReAct是"瑞士军刀"。理解trade-off,才能因时制宜。
五、实战选型指南:什么场景用什么
点题:五类典型场景的范式匹配
| 场景类型 | 推荐范式 | 关键原因 |
|---|---|---|
| 数据分析报告生成 | Plan-and-Execute | 多数据源关联,需要全局schema理解 |
| 实时客服对话 | ReAct | 低延迟,对话流不可预测 |
| 代码生成与调试 | 混合:Plan定框架,ReAct填细节 | 架构可规划,实现细节需迭代 |
| 科学研究辅助 | Plan-and-Execute | 假设-验证的严谨性要求 |
| 游戏NPC行为 | ReAct | 环境动态变化,需要即时反应 |
痛点分析:教条主义选型
反模式一:盲目追新
“ReAct是论文新提出的,肯定更先进,都用ReAct!”
ReAct论文是2022年的,Plan-and-Execute的思想在2023年的LLMCompiler、2024年的各种Agent框架中持续演进。范式没有代差,只有适配度差异。
反模式二:一刀切
“我们系统统一用Plan-and-Execute,规范好管理。”
结果简单查询也要等规划,用户体验崩盘。或者"全用ReAct",复杂报表生成经常漏步骤。
解决方案:场景化决策流程图
具体场景深度解析
场景1:SQL生成(推荐Plan-and-Execute)
# 错误做法:ReAct直接生成
# 容易漏JOIN条件,或者WHERE子句不全
# 正确做法:Plan-and-Execute
plan = [
{"step": "schema_linking", "task": "识别相关表和字段"},
{"step": "condition_extraction", "task": "提取所有过滤条件"},
{"step": "sql_draft", "task": "生成草稿SQL"},
{"step": "validation", "task": "检查语法和语义"},
{"step": "execution", "task": "执行并返回结果"}
]
# 每一步可验证,出错可定位
场景2:工具调用链(推荐ReAct)
# 场景:根据用户描述自动选择并组合工具
# "帮我找北京明天适合户外活动的地点,要人少"
# ReAct的灵活优势
Thought 1: 需要天气信息和地点推荐,先查天气
Action 1: GetWeather(city="北京", date="明天")
Observation 1: 晴天,25度,适合户外
Thought 2: 天气好,现在找人少的地方。需要调用地图API
Action 2: SearchPlaces(city="北京", type="户外", crowd_level="low")
...
# 工具组合不可预先确定,ReAct更合适
场景3:长文档生成(推荐混合范式)
# 先生成大纲(Plan),再逐节写作(ReAct迭代)
# Phase 1: Plan
outline = planner.generate_outline(
topic="2024年AI行业发展报告",
sections=["技术突破", "商业应用", "政策监管", "未来趋势"]
)
# Phase 2: 每节用ReAct写作,但受大纲约束
for section in outline.sections:
content = react_writer.write(
section=section,
constraints=f"必须覆盖大纲要点: {section.key_points}",
max_iterations=5
)
# 验证是否覆盖要点,不足则补充
小结
选型不是一次决策,是持续调优。从场景出发,用数据验证,比教条更有价值。
六、代码层面的关键实现差异
点题:状态管理与Prompt设计的分水岭
Plan-and-Execute和ReAct在代码实现上,最核心的差异体现在状态管理和Prompt设计两个层面。
痛点分析:把两种范式写成一种代码
我见过最离谱的代码,是用ReAct的循环结构硬套Plan-and-Execute:
# 反模式:假Plan真ReAct
def fake_plan_agent(query):
# 号称是Plan-and-Execute,实际没有分离规划和执行
plan = llm.generate(f"请规划如何回答: {query}") # 生成文本计划,不结构化
for step in plan.split("\n"): # 按行解析,脆弱
thought = f"现在执行: {step}"
action = llm.generate(f"{thought}\n请决定行动") # 又变成ReAct式的即时决策
# ...混乱不堪
这种代码既没拿到Plan的全局性,又丢了ReAct的灵活性,两头不靠。
解决方案:两种范式的标准实现模板
Plan-and-Execute标准模板
from dataclasses import dataclass
from typing import List, Dict, Any, Callable
from enum import Enum
class StepStatus(Enum):
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
@dataclass
class PlanStep:
id: str
description: str
tool: str
parameters: Dict[str, Any]
dependencies: List[str] # 依赖的其他步骤ID
status: StepStatus = StepStatus.PENDING
result: Any = None
class PlanAndExecuteAgent:
def __init__(self, tools: Dict[str, Callable], llm):
self.tools = tools
self.llm = llm
self.plan_history: List[List[PlanStep]] = [] # 支持重规划的历史
def planner(self, query: str, available_tools: List[str],
previous_failure: str = None) -> List[PlanStep]:
"""生成结构化计划,非自然语言"""
prompt = f"""你是一个任务规划专家。将用户请求拆解为可执行步骤。
可用工具: {available_tools}
用户请求: {query}
{f'之前计划失败原因: {previous_failure}' if previous_failure else ''}
输出必须是JSON格式:
{{
"steps": [
{{
"id": "step_1",
"description": "步骤描述",
"tool": "工具名(必须在可用工具列表中)",
"parameters": {{"参数名": "参数值或占位符"}},
"dependencies": [] # 依赖的步骤ID
}}
]
}}
规则:
1. 工具名必须严格匹配可用工具列表
2. 有依赖关系的步骤,dependencies必须填写
3. 参数值如果是从前序步骤获取,用{{step_id.result.field}}标记
"""
response = self.llm.generate(prompt)
plan_data = json.loads(response)
return [PlanStep(**step) for step in plan_data["steps"]]
def executor(self, step: PlanStep, context: Dict[str, Any]) -> Any:
"""执行单步,纯执行无决策"""
# 解析参数(处理依赖引用)
resolved_params = self._resolve_params(step.parameters, context)
# 调用工具
tool = self.tools[step.tool]
result = tool(**resolved_params)
return result
def run(self, query: str) -> Any:
# 生成初始计划
plan = self.planner(query, list(self.tools.keys()))
self.plan_history.append(plan)
# 拓扑排序,按依赖执行
execution_order = self._topological_sort(plan)
context = {} # 步骤结果上下文
for step_id in execution_order:
step = next(s for s in plan if s.id == step_id)
step.status = StepStatus.RUNNING
try:
result = self.executor(step, context)
step.result = result
step.status = StepStatus.COMPLETED
context[step.id] = result
except Exception as e:
step.status = StepStatus.FAILED
# 决策:重试、跳过、还是重新规划?
recovery_action = self._decide_recovery(step, str(e), plan)
if recovery_action == "replan":
# 重新规划,从当前失败步骤开始
new_plan = self.planner(
query,
list(self.tools.keys()),
previous_failure=f"步骤{step.id}失败: {str(e)}"
)
# 合并已完成步骤和新计划
plan = self._merge_plans(plan, new_plan, step_id)
execution_order = self._topological_sort(plan)
elif recovery_action == "skip":
step.status = StepStatus.COMPLETED # 标记为完成但结果为空
context[step.id] = None
else: # retry
# 简单重试,实际可加入指数退避
result = self.executor(step, context)
step.result = result
step.status = StepStatus.COMPLETED
context[step.id] = result
# 综合所有结果生成最终答案
return self._synthesize(plan, context)
ReAct标准模板
from dataclasses import dataclass
from typing import Optional, Tuple
@dataclass
class ReActStep:
thought: str
action: Optional[str]
action_input: Optional[str]
observation: Optional[str]
is_final: bool = False
class ReActAgent:
def __init__(self, tools: Dict[str, Callable], llm,
max_iterations: int = 10):
self.tools = tools
self.llm = llm
self.max_iterations = max_iterations
# ReAct的Prompt模板,严格约束格式
self.prompt_template = """回答用户问题,通过思考-行动-观察的循环。
可用工具:
{tool_descriptions}
历史轨迹:
{trajectory}
规则:
1. 必须按格式输出,Thought和Action必须成对出现(Final Answer除外)
2. Thought必须分析当前已知信息和下一步计划
3. 不要重复已经执行过的行动
4. 如果信息足够,立即输出Final Answer
开始:
Question: {question}
"""
def parse_output(self, text: str) -> Tuple[str, Optional[str], Optional[str]]:
"""严格解析Thought/Action/Observation"""
thought = ""
action = None
action_input = None
# 提取Thought
if "Thought:" in text:
thought = text.split("Thought:")[1].split("Action:")[0].strip()
# 提取Action
if "Action:" in text and "Final Answer:" not in text:
action_part = text.split("Action:")[1].split("Action Input:")[0].strip()
action = action_part
# 提取Action Input
if "Action Input:" in text:
action_input = text.split("Action Input:")[1].split("Observation:")[0].strip()
# 检查是否结束
if "Final Answer:" in text:
return text.split("Final Answer:")[1].strip(), None, None, True
return thought, action, action_input, False
def run(self, question: str) -> str:
trajectory = [] # 完整历史
iterations = 0
while iterations < self.max_iterations:
# 构建当前Prompt
tool_descriptions = "\n".join([
f"{name}: {func.__doc__}"
for name, func in self.tools.items()
])
trajectory_text = "\n".join([
f"Thought: {s.thought}\nAction: {s.action}\n"
f"Action Input: {s.action_input}\nObservation: {s.observation}"
for s in trajectory
])
prompt = self.prompt_template.format(
tool_descriptions=tool_descriptions,
trajectory=trajectory_text,
question=question
)
# 生成下一步
response = self.llm.generate(prompt)
thought, action, action_input, is_final = self.parse_output(response)
if is_final:
return thought # Final Answer的内容
# 执行行动
if action and action in self.tools:
try:
result = self.tools[action](action_input)
observation = str(result)
except Exception as e:
observation = f"错误: {str(e)}"
else:
observation = f"错误: 未知工具 '{action}',可用工具: {list(self.tools.keys())}"
# 记录步骤
trajectory.append(ReActStep(
thought=thought,
action=action,
action_input=action_input,
observation=observation
))
iterations += 1
# 检查是否陷入循环(重复相同的thought/action)
if self._is_looping(trajectory):
return "抱歉,我似乎在循环思考,请简化问题或提供更多上下文。"
return "达到最大迭代次数,未能完成回答。"
def _is_looping(self, trajectory: List[ReActStep], window: int = 3) -> bool:
"""检测是否陷入循环"""
if len(trajectory) < window * 2:
return False
recent = trajectory[-window:]
previous = trajectory[-window*2:-window]
# 比较thought和action的相似度
recent_sig = [(s.thought[:50], s.action) for s in recent]
previous_sig = [(s.thought[:50], s.action) for s in previous]
return recent_sig == previous_sig
关键差异总结
| 方面 | Plan-and-Execute | ReAct |
|---|---|---|
| 核心数据结构 | 计划图(DAG) | 线性轨迹(List) |
| LLM调用模式 | 规划时一次/多次,执行时可能零次 | 每步都调用LLM |
| 状态持久化 | 计划版本、执行检查点 | 轨迹历史 |
| 并发可能 | 无依赖步骤可并行 | 本质串行 |
| 调试难度 | 计划可见,易定位 | 需追溯思考链 |
小结
代码层面的差异,根源于思维模型的差异。Plan-and-Execute需要图结构处理依赖,ReAct需要严格的格式约束防止发散。
七、混合范式:未来的演进方向
点题:ReWOO、LLMCompiler等新一代方案
2023-2024年,学术界和工业界都在探索"取两者之长"的混合范式。
ReWOO(Reasoning WithOut Observation):把ReAct的"观察"成本降下来。先规划所有工具调用,然后批量执行,减少LLM调用次数。
LLMCompiler:明确分离规划、任务调度和执行。规划生成DAG,调度器优化并行,执行器高效运行。
Hierarchical Agents:高层用Plan做战略,低层用ReAct做战术。
痛点分析:过早优化与架构复杂化
“听说LLMCompiler很先进,我们也上!”
结果团队花了两个月实现DAG调度、并行执行、依赖解析,却发现90%的任务是单步骤查询。复杂的架构反而降低了可维护性。
解决方案:渐进式演进路径
# 阶段1:从纯ReAct开始,快速验证
agent = ReActAgent(tools, llm)
# 阶段2:识别瓶颈,对复杂任务引入轻量Plan
def stage2_agent(query):
if is_complex(query):
# 简单规划:提取关键子目标
subgoals = llm.extract_subgoals(query)
return execute_with_checkpoints(subgoals)
else:
return react_agent.run(query)
# 阶段3:全功能Plan-and-Execute,支持重规划
agent = PlanAndExecuteAgent(tools, llm, enable_replan=True)
# 阶段4:混合调度,动态选择策略
agent = AdaptiveAgent([
("simple", ReActAgent(tools, llm)),
("complex", PlanAndExecuteAgent(tools, llm)),
("batch", ReWOOAgent(tools, llm))
])
小结
范式演进是需求驱动的,不是技术驱动。先跑起来,再测瓶颈,最后优化,永远是最佳路径。
写在最后
聊到这里,Plan-and-Execute和ReAct的本质区别,你应该有清晰的体感了。
Plan-and-Execute是战略思维:先看清全局,再步步为营,错了能回头。它适合那些"输不起"的场景——医疗诊断、金融决策、复杂数据分析。代价是前置的思考成本,和可能的过度规划。
ReAct是战术思维:快速响应,边打边学,灵活应变。它适合那些"等不起"的场景——实时对话、探索性任务、工具组合不确定。代价是可能短视,可能陷入循环,可能Token失控。
但最厉害的Agent开发者,不是"会选范式"的人,是能根据任务动态组合范式的人。简单查询用ReAct秒回,复杂分析用Plan-and-Execute保质量,批量任务用ReWOO省成本——这才是"智能调度"的真谛。
做Agent和做人有点像。有时候你需要停下来想清楚再动,有时候你需要先动起来再找路。关键是,你要知道自己在哪种模式,以及为什么。
编程之路不易,但每一步踩过的坑都算数。保持好奇,持续实验,你也能做出让人眼前一亮的AI Agent。下次见!
关注私信备注:“资料代找获取”,全网计算机学习资料代找:例如:
《课程:2026 年多模态大模型实战训练营》
《课程:AI 大模型工程师系统课程 (22 章完整版 持续更新)》
《课程:AI 大模型系统实战课第四期 (2026 年开课 持续更新)》
《课程:2026 年 AGI 大模型系统课 23 期》
《课程:2026 年 AGI 大模型系统课 21 期》
《课程:AI 大模型实战课 8 期 (2026 年 2 月最新完结版)》
《课程:AI 大模型系统实战课三期》
《课程:AI 大模型系统课程 (2026 年 2 月开课 持续更新)》
《课程:AI 大模型全阶课程 (2025 年 12 月开课 2026 年 6 月结课)》
《课程:AI 大模型工程师全阶课程 (2025 年 10 月开课 2026 年 4 月结课)》
《课程:2026 年最新大模型 Agent 开发系统课 (持续更新)》
《课程:LLM 多模态视觉大模型系统课》
《课程:大模型 AI 应用开发企业级项目实战课 (2026 年 1 月开课)》
《课程:大模型智能体线上速成班 V2.0》
《课程:Java+AI 大模型智能应用开发全阶课》
《课程:Python+AI 大模型实战视频教程》
《书籍:软件工程 3.0: 大模型驱动的研发新范式.pdf》
《课程:人工智能大模型系统课 (2026 年 1 月底完结版)》
《课程:AI 大模型零基础到商业实战全栈课第五期》
《课程:Vue3.5+Electron + 大模型跨平台 AI 桌面聊天应用实战 (2025)》
《课程:AI 大模型实战训练营 从入门到实战轻松上手》
《课程:2026 年 AI 大模型 RAG 与 Agent 智能体项目实战开发课》
《课程:大模型训练营配套补充资料》
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)