Plan-and-Execute 架构模式
Plan-and-Execute 是一种将任务规划和执行分离的 Agent 架构模式。其核心思想是"先规划后执行":规划器(Planner)生成完整的执行计划,执行器(Executor)按计划逐步执行子任务,支持执行过程中的动态调整。
一、核心原理
1.1 设计哲学
Plan-and-Execute 的核心设计哲学是规划与执行解耦:
┌─────────────────────────────────────────────────────────────┐
│ Plan-and-Execute 设计哲学 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ReAct 模式: │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 思考 │ ──→ │ 行动 │ ──→ │ 观察 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ↑ │ │
│ └──────────────────────────────────┘ │
│ 边思考边执行,每步都需要 LLM 推理 │
│ │
│ Plan-and-Execute 模式: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Phase 1: Planning │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 任务 │ ──→ │ 规划器 │ ──→ │ 计划 │ │ │
│ │ │ 输入 │ │Planner │ │ Plan │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Phase 2: Execution │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 步骤1 │ ──→ │ 步骤2 │ ──→ │ 步骤N │ │ │
│ │ │ 执行 │ │ 执行 │ │ 执行 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ 执行器(Executor)按计划逐步执行 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘1.2 核心组件
| 组件 | 职责 | 输入 | 输出 |
|---|---|---|---|
| Planner(规划器) | 分解任务、生成计划 | 用户任务 | 执行计划(Plan) |
| Executor(执行器) | 执行子任务 | 子任务 + 上下文 | 执行结果 |
| Replanner(重规划器) | 动态调整计划 | 执行结果 + 原计划 | 更新后的计划 |
| Memory(记忆) | 存储中间状态 | 执行记录 | 状态查询 |
1.3 两阶段详解
┌─────────────────────────────────────────────────────────────┐
│ 两阶段工作流程详解 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Phase 1: Planning(规划阶段) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 任务理解 │ │
│ │ • 分析用户意图 │ │
│ │ • 提取关键信息 │ │
│ │ • 识别约束条件 │ │
│ │ │ │
│ │ 2. 子任务分解 │ │
│ │ • 将大任务拆分为小任务 │ │
│ │ • 确定任务粒度 │ │
│ │ • 定义任务边界 │ │
│ │ │ │
│ │ 3. 依赖分析 │ │
│ │ • 识别任务间依赖关系 │ │
│ │ • 构建执行顺序 │ │
│ │ • 标记可并行任务 │ │
│ │ │ │
│ │ 4. 工具匹配 │ │
│ │ • 为每个子任务分配工具 │ │
│ │ • 预估资源需求 │ │
│ │ • 制定备选方案 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Phase 2: Execution(执行阶段) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ for each step in plan: │ │
│ │ 1. 检查前置依赖是否完成 │ │
│ │ 2. 调用对应工具执行 │ │
│ │ 3. 记录结果 + 更新状态 │ │
│ │ 4. [可选] 动态调整后续计划 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘1.4 与 ReAct 对比
| 对比维度 | Plan-and-Execute | ReAct |
|---|---|---|
| 决策时机 | 预先规划 | 实时决策 |
| 执行方式 | 按计划执行 | 边思考边执行 |
| 可预测性 | 高(计划可见) | 低(动态生成) |
| 并行能力 | 支持(无依赖任务) | 不支持 |
| 容错能力 | 需要重规划 | 自然适应 |
| Token 效率 | 高(规划一次) | 低(每步推理) |
二、工作流程
2.1 完整工作流程图
┌─────────────────────────────────────────────────────────────────────┐
│ Plan-and-Execute 完整工作流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 用户输入 │ │
│ │ (Task) │ │
│ └──────┬──────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 规划阶段 (Planning) │ │
│ │ ┌───────────────────────────────────────────────────────┐ │ │
│ │ │ Planner │ │ │
│ │ │ │ │ │
│ │ │ Task → 理解 → 分解 → 排序 → Plan │ │ │
│ │ │ │ │ │
│ │ │ 输出: │ │ │
│ │ │ [Step1, Step2, Step3, ..., StepN] │ │ │
│ │ │ + 依赖关系 │ │ │
│ │ │ + 工具分配 │ │ │
│ │ └───────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 执行阶段 (Execution) │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Step 1 │───→│ Step 2 │───→│ Step N │ │ │
│ │ │ 执行 │ │ 执行 │ │ 执行 │ │ │
│ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │
│ │ │ │ │ │ │
│ │ ↓ ↓ ↓ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 检查 │ │ 检查 │ │ 检查 │ │ │
│ │ │ 结果 │ │ 结果 │ │ 结果 │ │ │
│ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │
│ │ │ │ │ │ │
│ │ └──────────────┼──────────────┘ │ │
│ │ │ │ │
│ │ ↓ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ 需要重规划? │ │ │
│ │ └────────┬────────┘ │ │
│ │ │ │ │
│ │ ┌─────────────┴─────────────┐ │ │
│ │ ↓ ↓ │ │
│ │ ┌─────────┐ ┌───────────┐ │ │
│ │ │ 是 │ │ 否 │ │ │
│ │ │ Replan │ │ 继续执行 │ │ │
│ │ └─────────┘ └───────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────┐ │
│ │ 生成最终结果 │ │
│ │ (Final Output) │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘2.2 计划表示
# 计划的数据结构
@dataclass
class Plan:
"""执行计划"""
goal: str # 总目标
steps: List[PlanStep] # 步骤列表
dependencies: Dict[str, List[str]] # 依赖关系
@dataclass
class PlanStep:
"""单个步骤"""
id: str # 步骤ID
description: str # 步骤描述
tool: str # 使用的工具
tool_input: Dict[str, Any] # 工具输入
depends_on: List[str] # 依赖的步骤ID
status: StepStatus # 状态
class StepStatus(Enum):
"""步骤状态"""
PENDING = "pending" # 待执行
RUNNING = "running" # 执行中
COMPLETED = "completed" # 已完成
FAILED = "failed" # 失败
SKIPPED = "skipped" # 已跳过2.3 执行流程详解
┌─────────────────────────────────────────────────────────────┐
│ 执行流程详解 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 示例任务:分析销售数据并生成报告 │
│ │
│ Plan: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Step 1: load_data │ │
│ │ - 工具: file_reader │ │
│ │ - 输入: "sales_2024.csv" │ │
│ │ - 依赖: 无 │ │
│ │ │ │
│ │ Step 2: clean_data │ │
│ │ - 工具: data_cleaner │ │
│ │ - 输入: {data: Step1.result} │ │
│ │ - 依赖: [Step1] │ │
│ │ │ │
│ │ Step 3: analyze_data │ │
│ │ - 工具: data_analyzer │ │
│ │ - 输入: {data: Step2.result} │ │
│ │ - 依赖: [Step2] │ │
│ │ │ │
│ │ Step 4: generate_report │ │
│ │ - 工具: report_generator │ │
│ │ - 输入: {analysis: Step3.result} │ │
│ │ - 依赖: [Step3] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 执行过程: │
│ │
│ [Step 1] load_data │
│ ├─ 检查依赖: ✓ 无依赖 │
│ ├─ 执行工具: file_reader("sales_2024.csv") │
│ ├─ 结果: DataFrame(1000 rows, 10 columns) │
│ └─ 状态: completed ✓ │
│ │
│ [Step 2] clean_data │
│ ├─ 检查依赖: ✓ Step1 已完成 │
│ ├─ 执行工具: data_cleaner(Step1.result) │
│ ├─ 结果: DataFrame(950 rows, 10 columns) # 去除空值 │
│ └─ 状态: completed ✓ │
│ │
│ [Step 3] analyze_data │
│ ├─ 检查依赖: ✓ Step2 已完成 │
│ ├─ 执行工具: data_analyzer(Step2.result) │
│ ├─ 结果: {total: 1000000, top_product: "A", ...} │
│ └─ 状态: completed ✓ │
│ │
│ [Step 4] generate_report │
│ ├─ 检查依赖: ✓ Step3 已完成 │
│ ├─ 执行工具: report_generator(Step3.result) │
│ ├─ 结果: "sales_report_2024.pdf" │
│ └─ 状态: completed ✓ │
│ │
│ 最终输出: sales_report_2024.pdf │
│ │
└─────────────────────────────────────────────────────────────┘三、代码实现
3.1 基础实现
"""
Plan-and-Execute Agent 基础实现
"""
from typing import List, Dict, Any, Optional
from dataclasses import dataclass, field
from enum import Enum
import json
# 导入 LangChain 相关模块
from langchain.llms import BaseLLM
from langchain.tools import BaseTool
from langchain.prompts import PromptTemplate
class StepStatus(Enum):
"""步骤状态"""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
@dataclass
class PlanStep:
"""计划步骤"""
id: str
description: str
tool: str
tool_input: Dict[str, Any]
depends_on: List[str] = field(default_factory=list)
status: StepStatus = StepStatus.PENDING
result: Optional[Any] = None
@dataclass
class Plan:
"""执行计划"""
goal: str
steps: List[PlanStep]
def get_ready_steps(self) -> List[PlanStep]:
"""获取可以执行的步骤(依赖已满足)"""
ready = []
for step in self.steps:
if step.status != StepStatus.PENDING:
continue
# 检查依赖
deps_satisfied = all(
self.get_step(dep_id).status == StepStatus.COMPLETED
for dep_id in step.depends_on
)
if deps_satisfied:
ready.append(step)
return ready
def get_step(self, step_id: str) -> Optional[PlanStep]:
"""获取指定步骤"""
for step in self.steps:
if step.id == step_id:
return step
return None
def is_completed(self) -> bool:
"""检查计划是否完成"""
return all(
step.status == StepStatus.COMPLETED
for step in self.steps
)
class Planner:
"""规划器:生成执行计划"""
PLANNER_PROMPT = """
你是一个任务规划专家。请将用户的任务分解为具体的执行步骤。
可用工具:
\{tool_descriptions\}
任务:\{task\}
请生成执行计划,格式如下(JSON格式):
\{
"goal": "任务目标",
"steps": [
\{
"id": "step_1",
"description": "步骤描述",
"tool": "工具名称",
"tool_input": \{"param": "value"\},
"depends_on": []
\}
]
\}
要求:
1. 每个步骤使用一个工具
2. 明确标注步骤间的依赖关系
3. 步骤粒度适中,不要过大或过小
计划:
"""
def __init__(self, llm: BaseLLM, tools: List[BaseTool]):
self.llm = llm
self.tools = {tool.name: tool for tool in tools}
def plan(self, task: str) -> Plan:
"""生成执行计划"""
tool_descriptions = "\n".join([
f"- {name}: {tool.description}"
for name, tool in self.tools.items()
])
prompt = self.PLANNER_PROMPT.format(
tool_descriptions=tool_descriptions,
task=task
)
response = self.llm(prompt)
# 解析 JSON
plan_dict = self._parse_json(response)
# 构建 Plan 对象
steps = [
PlanStep(
id=s["id"],
description=s["description"],
tool=s["tool"],
tool_input=s.get("tool_input", {}),
depends_on=s.get("depends_on", [])
)
for s in plan_dict.get("steps", [])
]
return Plan(goal=plan_dict.get("goal", task), steps=steps)
def _parse_json(self, text: str) -> Dict:
"""从文本中解析 JSON"""
import re
json_match = re.search(r'```json\s*(.*?)\s*```', text, re.DOTALL)
if json_match:
return json.loads(json_match.group(1))
return json.loads(text)
class Executor:
"""执行器:执行计划步骤"""
def __init__(self, tools: List[BaseTool]):
self.tools = {tool.name: tool for tool in tools}
self.results: Dict[str, Any] = {} # 存储步骤结果
def execute_step(self, step: PlanStep, plan: Plan) -> Any:
"""执行单个步骤"""
if step.tool not in self.tools:
raise ValueError(f"未知工具: {step.tool}")
tool = self.tools[step.tool]
# 替换输入中的步骤引用
tool_input = self._resolve_input(step.tool_input, plan)
# 执行工具
result = tool.run(tool_input)
# 存储结果
self.results[step.id] = result
step.result = result
step.status = StepStatus.COMPLETED
return result
def _resolve_input(self, tool_input: Any, plan: Plan) -> Any:
"""解析输入中的步骤引用"""
if isinstance(tool_input, dict):
return {
k: self._resolve_input(v, plan)
for k, v in tool_input.items()
}
elif isinstance(tool_input, str):
# 检查是否是步骤引用,如 "Step1.result"
if "." in tool_input:
parts = tool_input.split(".")
step_id = parts[0]
if step_id in self.results:
return self.results[step_id]
return tool_input
class Replanner:
"""重规划器:动态调整计划"""
REPLAN_PROMPT = """
当前计划执行遇到问题,需要调整。
原计划:
\{original_plan\}
已完成的步骤:
\{completed_steps\}
失败的步骤:
\{failed_step\}
失败原因:\{error\}
请生成调整后的计划(JSON格式):
\{
"adjustment": "keep|modify|restart",
"new_steps": [...],
"reason": "调整原因"
\}
"""
def __init__(self, llm: BaseLLM):
self.llm = llm
def replan(
self,
plan: Plan,
failed_step: PlanStep,
error: str
) -> Plan:
"""重新规划"""
prompt = self.REPLAN_PROMPT.format(
original_plan=self._format_plan(plan),
completed_steps=[s.id for s in plan.steps if s.status == StepStatus.COMPLETED],
failed_step=failed_step.id,
error=error
)
response = self.llm(prompt)
# 解析并返回新计划
# ... 实现略
return plan
def _format_plan(self, plan: Plan) -> str:
return "\n".join([
f"- {s.id}: {s.description} [{s.status.value}]"
for s in plan.steps
])
class PlanExecuteAgent:
"""Plan-and-Execute Agent"""
def __init__(
self,
llm: BaseLLM,
tools: List[BaseTool],
max_replans: int = 3
):
self.llm = llm
self.tools = tools
self.planner = Planner(llm, tools)
self.executor = Executor(tools)
self.replanner = Replanner(llm)
self.max_replans = max_replans
def run(self, task: str) -> str:
"""运行 Agent"""
# Phase 1: Planning
print(f"[Planning] 正在规划任务: {task}")
plan = self.planner.plan(task)
print(f"[Planning] 生成计划,共 {len(plan.steps)} 个步骤")
# Phase 2: Execution
replan_count = 0
while not plan.is_completed():
# 获取可执行的步骤
ready_steps = plan.get_ready_steps()
if not ready_steps:
# 没有可执行步骤,可能是有循环依赖或全部失败
print("[Execution] 无法继续执行")
break
# 执行步骤
for step in ready_steps:
print(f"[Execution] 执行步骤: {step.id} - {step.description}")
step.status = StepStatus.RUNNING
try:
result = self.executor.execute_step(step, plan)
print(f"[Execution] 步骤 {step.id} 完成")
except Exception as e:
print(f"[Execution] 步骤 {step.id} 失败: {e}")
step.status = StepStatus.FAILED
# 尝试重规划
if replan_count < self.max_replans:
print(f"[Replanning] 正在重新规划...")
plan = self.replanner.replan(plan, step, str(e))
replan_count += 1
break
# 生成最终结果
return self._generate_final_output(plan)
def _generate_final_output(self, plan: Plan) -> str:
"""生成最终输出"""
completed = [s for s in plan.steps if s.status == StepStatus.COMPLETED]
failed = [s for s in plan.steps if s.status == StepStatus.FAILED]
output = f"任务执行完成\n"
output += f"- 完成步骤: {len(completed)}/{len(plan.steps)}\n"
if failed:
output += f"- 失败步骤: {', '.join(s.id for s in failed)}\n"
# 返回最后一个成功步骤的结果
if completed:
last_result = completed[-1].result
output += f"\n结果: {last_result}"
return output
# 使用示例
if __name__ == "__main__":
from langchain_openai import OpenAI
from langchain.tools import Tool
# 定义工具
def search_tool(query: str) -> str:
return f"搜索结果: {query}"
def analyze_tool(data: str) -> str:
return f"分析结果: {data}"
tools = [
Tool(name="search", func=search_tool, description="搜索信息"),
Tool(name="analyze", func=analyze_tool, description="分析数据")
]
# 创建 Agent
llm = OpenAI(temperature=0)
agent = PlanExecuteAgent(llm=llm, tools=tools)
# 运行
result = agent.run("研究人工智能发展趋势并生成报告")
print(result)3.2 使用 LangGraph 实现
"""
使用 LangGraph 实现 Plan-and-Execute
推荐的生产环境实现方式
"""
from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
import operator
# 定义状态
class PlanExecuteState(TypedDict):
"""Plan-Execute 状态"""
input: str # 用户输入
plan: List[str] # 执行计划
past_steps: Annotated[List, operator.add] # 已执行步骤
response: str # 最终响应
def create_plan_execute_graph():
"""创建 Plan-Execute 图"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
# 规划节点
def plan_step(state: PlanExecuteState):
"""生成执行计划"""
task = state["input"]
prompt = f"""将以下任务分解为步骤:
任务:\{task\}
输出格式:
1. 步骤一
2. 步骤二
...
"""
response = llm.invoke(prompt)
plan = response.content.strip().split("\n")
return \{"plan": plan\}
# 执行节点
def execute_step(state: PlanExecuteState):
"""执行单个步骤"""
plan = state["plan"]
past_steps = state.get("past_steps", [])
# 获取下一个要执行的步骤
next_step = plan[len(past_steps)]
# 执行步骤(这里简化处理)
result = f"执行 {next_step} 完成"
return \{"past_steps": [(next_step, result)]\}
# 条件判断
def should_continue(state: PlanExecuteState):
"""判断是否继续执行"""
plan = state["plan"]
past_steps = state.get("past_steps", [])
if len(past_steps) < len(plan):
return "execute"
return "respond"
# 响应节点
def respond(state: PlanExecuteState):
"""生成最终响应"""
past_steps = state.get("past_steps", [])
response = "任务执行完成:\n"
for step, result in past_steps:
response += f"- {step}: {result}\n"
return \{"response": response\}
# 创建图
workflow = StateGraph(PlanExecuteState)
# 添加节点
workflow.add_node("planner", plan_step)
workflow.add_node("execute", execute_step)
workflow.add_node("respond", respond)
# 设置入口
workflow.set_entry_point("planner")
# 添加边
workflow.add_edge("planner", "execute")
workflow.add_conditional_edges(
"execute",
should_continue,
{
"execute": "execute",
"respond": "respond"
}
)
workflow.add_edge("respond", END)
return workflow.compile()
# 使用示例
if __name__ == "__main__":
graph = create_plan_execute_graph()
result = graph.invoke({
"input": "分析销售数据并生成报告"
})
print(result["response"])四、适用场景
4.1 最佳适用场景
| 场景类型 | 具体示例 | 优势体现 |
|---|---|---|
| 复杂工作流 | 数据处理管道 | 规划可验证,执行可控 |
| 多工具协同 | 搜索→分析→报告 | 工具依赖明确,可并行 |
| 审计合规 | 企业流程自动化 | 执行轨迹完整可追溯 |
| 批量处理 | ETL 数据任务 | 计划复用,效率高 |
4.2 场景详解
┌─────────────────────────────────────────────────────────────┐
│ Plan-and-Execute 适用场景详解 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 数据分析工作流 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 任务:分析用户行为数据,生成洞察报告 │ │
│ │ │ │
│ │ Plan: │ │
│ │ Step1: 加载数据 (file_loader) │ │
│ │ Step2: 数据清洗 (data_cleaner) │ │
│ │ Step3: 统计分析 (statistical_analyzer) │ │
│ │ Step4: 可视化图表 (chart_generator) │ │
│ │ Step5: 生成报告 (report_generator) │ │
│ │ │ │
│ │ 优势:步骤清晰,每步结果可验证,支持断点续执行 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 多步骤信息收集 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 任务:调研竞品并生成分析报告 │ │
│ │ │ │
│ │ Plan: │ │
│ │ Step1: 搜索竞品A信息 (search) │ │
│ │ Step2: 搜索竞品B信息 (search) ─┐ 可并行执行 │ │
│ │ Step3: 搜索竞品C信息 (search) ─┘ │ │
│ │ Step4: 对比分析 (analyzer) │ │
│ │ Step5: 生成报告 (reporter) │ │
│ │ │ │
│ │ 优势:无依赖步骤可并行,提升效率 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 企业流程自动化 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 任务:处理客户订单 │ │
│ │ │ │
│ │ Plan: │ │
│ │ Step1: 验证订单信息 (validator) │ │
│ │ Step2: 检查库存 (inventory_checker) │ │
│ │ Step3: 创建发货单 (shipping_creator) │ │
│ │ Step4: 发送确认邮件 (email_sender) │ │
│ │ Step5: 更新订单状态 (status_updater) │ │
│ │ │ │
│ │ 优势:执行轨迹完整,满足审计要求 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘4.3 不适用场景
| 场景 | 原因 | 推荐替代方案 |
|---|---|---|
| 高度动态任务 | 计划容易过时 | ReAct 模式 |
| 简单问答 | 规划开销大 | 直接执行 |
| 探索性任务 | 无法预先规划 | ReAct + Reflexion |
| 创意生成 | 无固定流程 | 单次 LLM 调用 |
五、局限性与优化
5.1 主要局限性
| 局限性 | 具体表现 | 影响 |
|---|---|---|
| 规划质量依赖 | 规划器能力不足导致计划不合理 | 执行失败率高 |
| 动态适应差 | 环境变化时计划可能过时 | 需要频繁重规划 |
| 重规划成本 | 失败后重规划消耗额外资源 | 效率降低 |
| 初始延迟 | 需要先完成规划才能执行 | 响应时间增加 |
5.2 优化策略
┌─────────────────────────────────────────────────────────────┐
│ Plan-and-Execute 优化策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 渐进式规划 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:一次性规划可能不准确 │ │
│ │ │ │
│ │ 优化方案: │ │
│ │ • 先规划大致框架,细节逐步填充 │ │
│ │ • 关键步骤详细规划,其他步骤粗略规划 │ │
│ │ • 执行过程中按需细化下一步计划 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 智能重规划 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:失败后完全重新规划成本高 │ │
│ │ │ │
│ │ 优化方案: │ │
│ │ • 局部修复:只调整受影响的步骤 │ │
│ │ • 备选路径:预设多个备选方案 │ │
│ │ • 回滚重试:失败步骤尝试其他参数 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 并行执行 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:串行执行效率低 │ │
│ │ │ │
│ │ 优化方案: │ │
│ │ • 识别无依赖的步骤 │ │
│ │ • 使用线程池并行执行 │ │
│ │ • 结果合并后继续后续步骤 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 计划缓存 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:相似任务重复规划 │ │
│ │ │ │
│ │ 优化方案: │ │
│ │ • 缓存历史计划模板 │ │
│ │ • 相似任务复用计划结构 │ │
│ │ • 参数化模板提高复用性 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘5.3 与 ReAct 结合
"""
Plan-ReAct 混合架构
结合两者优势:规划的可控性 + 执行的灵活性
"""
class HybridAgent:
"""混合架构 Agent"""
def run(self, task: str) -> str:
# 1. 高层规划
plan = self.planner.plan(task)
for step in plan.steps:
# 2. 每个步骤使用 ReAct 执行
step_result = self.react_executor.execute(step)
# 3. 关键步骤进行验证
if step.is_critical:
if not self.validator.validate(step_result):
# 4. 失败时重规划
plan = self.replanner.adjust(plan, step, step_result)
return self.aggregate_results()六、面试常见问题
Q1: Plan-and-Execute 模式与 ReAct 模式有什么区别?
A:
| 对比维度 | Plan-and-Execute | ReAct |
|---|---|---|
| 决策时机 | 预先规划 | 实时决策 |
| 执行流程 | 按计划顺序执行 | 边思考边执行 |
| 可预测性 | 高(计划可见) | 低(动态生成) |
| 并行能力 | 支持 | 不支持 |
| Token 效率 | 高(规划一次) | 低(每步推理) |
| 适应变化 | 需要重规划 | 自然适应 |
| 适用场景 | 结构化任务 | 探索性任务 |
选择建议:
- 任务可预先结构化 → Plan-and-Execute
- 任务需要动态探索 → ReAct
- 企业级应用 → Plan-and-Execute(可审计)
Q2: 如何处理计划执行失败的情况?
A:
失败处理策略:
def handle_failure(step, error, plan):
"""处理执行失败"""
# 1. 错误分析
error_type = classify_error(error)
# 2. 根据错误类型选择策略
if error_type == "tool_error":
# 工具错误:尝试备选工具
return retry_with_alternative(step)
elif error_type == "dependency_error":
# 依赖错误:检查前置步骤
return check_and_fix_dependencies(step, plan)
elif error_type == "input_error":
# 输入错误:修正输入参数
return fix_input_and_retry(step)
else:
# 未知错误:重新规划
return replan(plan, step, error)Q3: 如何实现步骤的并行执行?
A:
import concurrent.futures
def execute_parallel(plan):
"""并行执行无依赖的步骤"""
results = {}
while not plan.is_completed():
# 获取可执行的步骤
ready_steps = get_ready_steps(plan, results)
# 并行执行
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {
executor.submit(execute_step, step): step
for step in ready_steps
}
for future in concurrent.futures.as_completed(futures):
step = futures[future]
try:
results[step.id] = future.result()
step.status = "completed"
except Exception as e:
step.status = "failed"
handle_failure(step, e)
return resultsQ4: Plan-and-Execute 如何保证执行的可审计性?
A:
审计追踪实现:
@dataclass
class ExecutionRecord:
"""执行记录"""
step_id: str
step_description: str
tool_name: str
tool_input: Dict
tool_output: Any
start_time: datetime
end_time: datetime
status: str
error: Optional[str] = None
class AuditableExecutor:
"""可审计的执行器"""
def __init__(self):
self.records: List[ExecutionRecord] = []
def execute_step(self, step: PlanStep) -> Any:
record = ExecutionRecord(
step_id=step.id,
step_description=step.description,
tool_name=step.tool,
tool_input=step.tool_input,
start_time=datetime.now(),
status="running"
)
try:
result = self.tools[step.tool].run(step.tool_input)
record.tool_output = result
record.status = "completed"
except Exception as e:
record.error = str(e)
record.status = "failed"
raise
finally:
record.end_time = datetime.now()
self.records.append(record)
return result
def export_audit_log(self) -> str:
"""导出审计日志"""
return json.dumps([
{
"step_id": r.step_id,
"tool": r.tool_name,
"input": r.tool_input,
"output": str(r.tool_output)[:100], # 截断
"duration": (r.end_time - r.start_time).total_seconds(),
"status": r.status
}
for r in self.records
], indent=2)Q5: 什么时候应该选择 Plan-and-Execute 而不是 ReAct?
A:
选择决策树:
任务是否可以预先结构化?
├── 是 → 任务是否有明确的依赖关系?
│ ├── 是 → Plan-and-Execute
│ └── 否 → 考虑 ReAct
│
└── 否 → 任务是否需要探索性执行?
├── 是 → ReAct
└── 否 → 考虑 Plan-and-Execute(带重规划)具体场景判断:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 数据处理管道 | Plan-and-Execute | 步骤固定,可并行 |
| 网页信息抓取 | ReAct | 需要实时观察页面 |
| 报表生成任务 | Plan-and-Execute | 流程固定,可审计 |
| 开放式问答 | ReAct | 需要动态探索答案 |
| 订单处理流程 | Plan-and-Execute | 状态明确,需审计 |
| 创意写作任务 | 单次 LLM | 无需复杂规划 |
Q6: 如何评估 Plan-and-Execute Agent 的效果?
A:
评估指标体系:
| 指标类别 | 具体指标 | 计算方式 |
|---|---|---|
| 任务完成率 | 成功率 | 成功任务数 / 总任务数 |
| 计划质量 | 计划合理性 | 人工评分或执行成功率 |
| 执行效率 | 平均执行时间 | 总时间 / 任务数 |
| 重规划率 | 重规划次数 | 重规划次数 / 任务数 |
| 并行效率 | 并行加速比 | 串行时间 / 并行时间 |
| 成本效益 | Token 消耗 | 总 Token 数 / 任务数 |
评估代码示例:
def evaluate_agent(agent, test_cases):
"""评估 Agent 性能"""
results = []
for case in test_cases:
start_time = time.time()
result = agent.run(case["input"])
end_time = time.time()
results.append({
"success": result == case["expected"],
"time": end_time - start_time,
"steps": len(agent.executor.results),
"replans": agent.replan_count,
"tokens": count_tokens(agent.history)
})
return {
"success_rate": mean([r["success"] for r in results]),
"avg_time": mean([r["time"] for r in results]),
"avg_steps": mean([r["steps"] for r in results]),
"avg_replans": mean([r["replans"] for r in results])
}七、总结
| 概念 | 一句话总结 | 面试关键词 |
|---|---|---|
| Plan-and-Execute | 规划与执行分离的两阶段架构 | 两阶段、解耦 |
| Planner | 负责生成执行计划的组件 | 任务分解、依赖分析 |
| Executor | 按计划执行步骤的组件 | 工具调用、状态管理 |
| Replanner | 动态调整计划的组件 | 失败恢复、灵活调整 |
| 核心优势 | 可预测、可并行、可审计 | 企业级应用首选 |
| 主要局限 | 规划质量依赖、动态适应差 | 需结合 ReAct 使用 |
一句话总结:Plan-and-Execute 是将规划和执行分离的 Agent 架构,适合结构化、可预测的任务场景,是企业级 Agent 应用的首选架构模式。
最后更新:2026年3月18日