规划与任务分解
规划(Planning)是 AI Agent 的核心能力之一。它让 Agent 能够将复杂的目标分解为一系列可执行的步骤,并按合理的顺序完成这些步骤。没有规划能力的 Agent 只能处理简单的单步任务,面对复杂需求时会陷入混乱。
为什么需要规划
当用户给 Agent 一个复杂的请求时,如果 Agent 直接开始执行,往往会遇到以下问题:
- 遗漏任务:复杂请求可能包含多个子任务,Agent 可能遗漏其中的某些部分
- 顺序混乱:某些步骤有依赖关系,必须按特定顺序执行
- 资源浪费:没有合理规划可能导致重复工作或无效操作
- 难以追踪:缺少清晰的计划使得任务进度难以监控
举个例子,假设用户请求:"帮我准备下周五的客户演示,我需要研究客户行业、制作幻灯片、练习演讲,还要给团队发会议邀请。"
这个请求实际上包含了四个子任务。如果 Agent 尝试一次性处理,可能会遗漏某些步骤,或者以错误的顺序执行(比如在制作幻灯片之前就练习演讲)。
规划模块的核心作用就是将这种模糊、复杂的目标转化为清晰、有序的行动计划。
规划的核心组件
根据 Lilian Weng 的经典框架,AI Agent 的规划模块包含四个子模块:
| 组件 | 作用 | 说明 |
|---|---|---|
| 子目标分解 | 将大目标拆分为小目标 | 降低任务复杂度,便于逐步执行 |
| 思维链 | 逐步思考推理过程 | 帮助模型理清思路,提高推理质量 |
| 反思 | 回顾和评估执行结果 | 发现问题,改进策略 |
| 自我批评 | 检验和修正决策 | 提高决策的可靠性 |
这四个组件协同工作,让 Agent 能够系统地处理复杂任务。
任务分解策略
顺序任务分解
顺序任务是指各步骤之间存在依赖关系,必须按特定顺序执行。前一个步骤的输出可能是后一个步骤的输入。
这种分解方式的关键是识别步骤之间的依赖关系。例如,在制作幻灯片之前必须先完成研究,因为研究结果是幻灯片内容的基础。
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from typing import List
class SubTask(BaseModel):
"""子任务结构"""
id: int = Field(description="任务编号")
description: str = Field(description="任务描述")
depends_on: List[int] = Field(default=[], description="依赖的任务编号")
class TaskPlan(BaseModel):
"""任务计划"""
goal: str = Field(description="原始目标")
subtasks: List[SubTask] = Field(description="子任务列表")
def decompose_sequential_task(goal: str) -> TaskPlan:
"""分解顺序任务"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个任务规划专家。请将用户的复杂目标分解为有序的子任务。
要求:
1. 每个子任务必须具体、可执行
2. 明确标注任务之间的依赖关系
3. 按合理的执行顺序排列
返回 JSON 格式的任务计划。"""),
("user", "{goal}")
])
chain = prompt | llm.with_structured_output(TaskPlan)
return chain.invoke({"goal": goal})
# 示例
goal = "帮我准备下周五的客户演示,包括研究客户行业、制作幻灯片、练习演讲和发会议邀请"
plan = decompose_sequential_task(goal)
for task in plan.subtasks:
deps = f" (依赖: {task.depends_on})" if task.depends_on else ""
print(f"{task.id}. {task.description}{deps}")
输出示例:
1. 研究客户行业,了解其业务模式、竞争格局和最新动态
2. 根据研究结果,制作演示幻灯片 (依赖: [1])
3. 练习演讲,确保流畅表达 (依赖: [2])
4. 给团队发送会议邀请 (依赖: [2])
并行任务分解
并行任务是指各步骤之间没有依赖关系,可以同时执行或以任意顺序执行。并行分解可以提高效率,充分利用资源。
from typing import List, Literal
from pydantic import BaseModel, Field
class ParallelSubTask(BaseModel):
"""并行子任务"""
id: int
description: str
can_parallelize: bool = Field(default=True, description="是否可并行执行")
group: str = Field(description="任务分组,同组可并行")
class ParallelPlan(BaseModel):
"""并行任务计划"""
goal: str
phases: List[List[ParallelSubTask]] = Field(description="分阶段的任务列表")
def decompose_parallel_task(goal: str) -> ParallelPlan:
"""分解并行任务"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个任务规划专家。请分析用户目标并识别可以并行执行的任务。
要求:
1. 识别哪些任务可以同时执行
2. 将任务分为不同的执行阶段
3. 同一阶段的任务没有相互依赖
返回分阶段的任务计划。"""),
("user", "{goal}")
])
chain = prompt | llm.with_structured_output(ParallelPlan)
return chain.invoke({"goal": goal})
# 示例
goal = "帮我整理一下:检查邮件、查看日程、获取今日天气,然后汇总报告"
plan = decompose_parallel_task(goal)
for i, phase in enumerate(plan.phases, 1):
print(f"\n阶段 {i}:")
for task in phase:
print(f" - {task.description}")
输出示例:
阶段 1:
- 检查邮件收件箱
- 查看今日日程安排
- 获取今日天气信息
阶段 2:
- 汇总以上信息生成报告
嵌套任务分解
有些任务需要多层分解。一个大任务分解为子任务后,某个子任务本身可能仍然很复杂,需要进一步分解。这形成了任务的层次结构。
from typing import List, Optional
from pydantic import BaseModel, Field
class NestedTask(BaseModel):
"""嵌套任务"""
id: str = Field(description="任务ID,如 1, 1.1, 1.1.1")
description: str
subtasks: Optional[List["NestedTask"]] = Field(default=None, description="子任务")
def decompose_nested_task(goal: str, max_depth: int = 2) -> NestedTask:
"""分解嵌套任务"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", f"""你是一个任务规划专家。请将用户目标分解为层次化的任务结构。
要求:
1. 最多分解到 {max_depth} 层深度
2. 每个任务应该足够具体,或者需要进一步分解
3. 使用层级ID标识任务(如 1, 1.1, 1.2)
返回嵌套的任务结构。"""),
("user", "{goal}")
])
chain = prompt | llm.with_structured_output(NestedTask)
return chain.invoke({"goal": goal})
def print_nested_task(task: NestedTask, indent: int = 0):
"""打印嵌套任务"""
prefix = " " * indent
print(f"{prefix}{task.id}. {task.description}")
if task.subtasks:
for subtask in task.subtasks:
print_nested_task(subtask, indent + 1)
# 示例
goal = "帮我规划一次三天两夜的旅行"
plan = decompose_nested_task(goal)
print_nested_task(plan)
输出示例:
1. 规划三天两夜旅行
1.1. 选择目的地
1.2. 预订交通
1.2.1. 比较航班价格
1.2.2. 预订往返机票
1.3. 预订住宿
1.3.1. 搜索酒店
1.3.2. 比较价格和评价
1.3.3. 完成预订
1.4. 规划行程
1.4.1. 规划第一天活动
1.4.2. 规划第二天活动
1.4.3. 规划第三天活动
规划模式
单步规划 vs 动态规划
单步规划是指在任务开始时一次性生成完整的执行计划,然后按计划执行。这种方式适合结构清晰、变化较少的任务。
def single_step_planning(goal: str) -> List[str]:
"""单步规划:一次性生成完整计划"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""请为以下目标制定一个完整的执行计划:
目标:{goal}
要求:
1. 列出所有需要执行的步骤
2. 步骤之间要有清晰的顺序
3. 每个步骤要具体可执行
请直接输出步骤列表,每行一个步骤。"""
response = llm.invoke(prompt)
steps = [line.strip() for line in response.content.split("\n") if line.strip()]
return steps
# 执行计划
def execute_plan(steps: List[str]):
"""按计划执行"""
results = []
for i, step in enumerate(steps, 1):
print(f"执行步骤 {i}/{len(steps)}: {step}")
# 实际执行逻辑...
results.append(f"步骤 {i} 完成")
return results
动态规划是指在执行过程中根据实际情况调整计划。当环境变化或遇到意外情况时,Agent 可以重新规划。这种方式更灵活,适合不确定性较高的任务。
from typing import Optional
from enum import Enum
class TaskStatus(Enum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
FAILED = "failed"
class DynamicPlanner:
"""动态规划器"""
def __init__(self, goal: str):
self.goal = goal
self.tasks: List[dict] = []
self.current_task_idx = 0
self.llm = ChatOpenAI(model="gpt-4", temperature=0)
# 初始化计划
self._create_initial_plan()
def _create_initial_plan(self):
"""创建初始计划"""
prompt = f"""请为以下目标创建执行计划:
目标:{self.goal}
返回 JSON 数组格式的任务列表,每个任务包含:
- id: 任务编号
- description: 任务描述
- status: 初始状态为 pending"""
response = self.llm.invoke(prompt)
import json
self.tasks = json.loads(response.content)
def get_next_task(self) -> Optional[dict]:
"""获取下一个待执行的任务"""
for task in self.tasks:
if task["status"] == TaskStatus.PENDING.value:
return task
return None
def update_task_status(self, task_id: int, status: TaskStatus, result: str = ""):
"""更新任务状态"""
for task in self.tasks:
if task["id"] == task_id:
task["status"] = status.value
task["result"] = result
break
def replan(self, reason: str):
"""根据情况重新规划"""
completed = [t for t in self.tasks if t["status"] == TaskStatus.COMPLETED.value]
failed = [t for t in self.tasks if t["status"] == TaskStatus.FAILED.value]
prompt = f"""原目标:{self.goal}
已完成的任务:
{completed}
失败的任务:
{failed}
重新规划原因:{reason}
请根据当前情况调整计划,返回新的任务列表。"""
response = self.llm.invoke(prompt)
import json
new_tasks = json.loads(response.content)
# 合并已完成的任务和新任务
self.tasks = completed + [t for t in new_tasks if t["id"] not in [c["id"] for c in completed]]
def execute(self):
"""执行计划"""
while True:
task = self.get_next_task()
if not task:
break
print(f"执行任务: {task['description']}")
try:
# 执行任务
result = self._execute_task(task)
self.update_task_status(task["id"], TaskStatus.COMPLETED, result)
print(f"任务完成: {task['description']}")
except Exception as e:
self.update_task_status(task["id"], TaskStatus.FAILED, str(e))
print(f"任务失败: {task['description']}, 原因: {e}")
# 动态重新规划
self.replan(f"任务 {task['description']} 失败: {e}")
print("所有任务执行完毕")
# 使用示例
planner = DynamicPlanner("帮我组织一次团队建设活动")
planner.execute()
Plan-and-Execute 模式
Plan-and-Execute 模式将规划和执行明确分离:先制定完整的计划,然后按计划执行。这种方式结构清晰,便于调试和监控。
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
import operator
class PlanExecuteState(TypedDict):
"""Plan-and-Execute 状态"""
goal: str
plan: List[str]
current_step: int
results: Annotated[List[str], operator.add]
final_answer: str
def plan_step(state: PlanExecuteState) -> dict:
"""规划步骤"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""请为以下目标制定详细的执行计划:
目标:{state['goal']}
要求:
1. 将目标分解为具体步骤
2. 步骤要按执行顺序排列
3. 每个步骤应该清晰、可执行
直接输出步骤列表,每行一个步骤。"""
response = llm.invoke(prompt)
plan = [line.strip() for line in response.content.split("\n")
if line.strip() and not line.strip().startswith("#")]
return {"plan": plan, "current_step": 0}
def execute_step(state: PlanExecuteState) -> dict:
"""执行步骤"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
current_idx = state["current_step"]
current_task = state["plan"][current_idx]
prompt = f"""请执行以下任务:
任务:{current_task}
原始目标:{state['goal']}
已完成的工作:{state.get('results', [])}
请输出执行结果。"""
response = llm.invoke(prompt)
return {
"current_step": current_idx + 1,
"results": [f"步骤 {current_idx + 1}: {response.content}"]
}
def should_continue(state: PlanExecuteState) -> str:
"""判断是否继续执行"""
if state["current_step"] < len(state["plan"]):
return "execute"
return "finalize"
def finalize(state: PlanExecuteState) -> dict:
"""生成最终结果"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""原始目标:{state['goal']}
执行结果:
{chr(10).join(state['results'])}
请根据以上结果,给出最终的总结回答。"""
response = llm.invoke(prompt)
return {"final_answer": response.content}
# 构建工作流
workflow = StateGraph(PlanExecuteState)
workflow.add_node("plan", plan_step)
workflow.add_node("execute", execute_step)
workflow.add_node("finalize", finalize)
workflow.set_entry_point("plan")
workflow.add_edge("plan", "execute")
workflow.add_conditional_edges("execute", should_continue, {
"execute": "execute",
"finalize": "finalize"
})
workflow.add_edge("finalize", END)
app = workflow.compile()
# 执行
result = app.invoke({
"goal": "帮我准备一份关于人工智能发展趋势的报告",
"plan": [],
"current_step": 0,
"results": [],
"final_answer": ""
})
print(result["final_answer"])
自我反思与迭代改进
自我反思是规划模块的重要能力。Agent 在执行过程中或执行完成后,可以回顾自己的决策和结果,发现问题并改进策略。
反思机制
from pydantic import BaseModel, Field
from typing import List
class Reflection(BaseModel):
"""反思结果"""
success: bool = Field(description="任务是否成功")
analysis: str = Field(description="分析执行过程")
issues: List[str] = Field(description="发现的问题")
improvements: List[str] = Field(description="改进建议")
next_action: str = Field(description="下一步行动建议")
def reflect_on_execution(goal: str, actions: List[str], results: List[str]) -> Reflection:
"""对执行结果进行反思"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""请对以下任务执行过程进行反思:
目标:{goal}
执行的动作:
{chr(10).join(actions)}
得到的结果:
{chr(10).join(results)}
请分析:
1. 任务是否成功完成?
2. 执行过程中有什么问题?
3. 有哪些可以改进的地方?
4. 如果任务未完成,下一步应该做什么?
返回结构化的反思结果。"""
chain = llm.with_structured_output(Reflection)
return chain.invoke(prompt)
# 示例
goal = "查询北京天气并发送邮件通知"
actions = ["调用天气API", "发送邮件"]
results = ["北京:晴,25°C", "邮件发送失败:SMTP 连接超时"]
reflection = reflect_on_execution(goal, actions, results)
print(f"是否成功: {reflection.success}")
print(f"分析: {reflection.analysis}")
print(f"问题: {reflection.issues}")
print(f"改进建议: {reflection.improvements}")
print(f"下一步: {reflection.next_action}")
ReAct 模式中的反思
ReAct(Reasoning and Acting)模式天然包含了反思机制。Agent 在每一步都会先"思考",然后选择"行动",观察结果后再进行下一轮思考。这个过程本身就是一个持续反思的过程。
问题:找出目前最受欢迎的无线耳机并确认是否有货
思考 1:流行度是时间敏感的,我需要使用搜索工具获取最新信息。
行动 1:search_products("wireless headphones")
观察 1:搜索结果显示 Sony WH-1000XM5 最受欢迎...
思考 2:搜索成功获取了热门产品信息。现在需要确认库存。
行动 2:check_inventory("WH-1000XM5")
观察 2:库存充足,有 50 件...
思考 3:我已经获得了完整信息,可以回答用户的问题。
行动 3:输出最终答案
在 LangChain 中实现带反思的 Agent:
from langchain.agents import create_agent, Middleware
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage
@tool
def search(query: str) -> str:
"""搜索信息"""
return f"搜索结果:{query}"
@tool
def check_inventory(product: str) -> str:
"""检查库存"""
return f"{product} 库存充足"
class ReflectionMiddleware(AgentMiddleware):
"""反思中间件"""
def after_tool_call(self, tool_call, result):
"""工具调用后反思"""
print(f"[反思] 工具 {tool_call.name} 返回: {result[:100]}...")
return result
def on_tool_error(self, error, tool_call):
"""工具错误时反思"""
print(f"[反思] 工具 {tool_call.name} 失败: {error}")
print("[反思] 尝试其他方法...")
return f"工具 {tool_call.name} 执行失败,请尝试其他方法。"
llm = ChatOpenAI(model="gpt-4", temperature=0)
agent = create_agent(
model=llm,
tools=[search, check_inventory],
system_prompt="""你是一个智能助手。请使用 ReAct 模式工作:
1. 思考:分析当前情况,决定下一步行动
2. 行动:调用工具或输出答案
3. 观察:分析工具返回的结果
4. 重复以上步骤直到完成任务
如果某个工具调用失败,请反思原因并尝试其他方法。""",
middleware=[ReflectionMiddleware()]
)
# 执行
result = agent.invoke({
"messages": [HumanMessage(content="找出最受欢迎的无线耳机并确认是否有货")]
})
思维链与推理增强
Chain of Thought (CoT)
思维链(Chain of Thought)是一种提示技术,让模型将复杂问题分解为一系列中间推理步骤,而不是直接给出答案。这有助于模型更好地处理需要多步推理的问题。
def chain_of_thought_reasoning(question: str) -> str:
"""使用思维链进行推理"""
llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""请使用思维链方法解决以下问题。
问题:{question}
要求:
1. 一步步思考,展示推理过程
2. 每个推理步骤要清晰明确
3. 最后给出答案
让我们一步步思考:"""
response = llm.invoke(prompt)
return response.content
# 示例
question = "一个篮子里有 15 个苹果,小明拿走了 3 个,小红又放进去了 5 个,请问篮子里现在有多少个苹果?"
answer = chain_of_thought_reasoning(question)
print(answer)
输出示例:
让我们一步步思考:
步骤 1:篮子里最初有 15 个苹果。
步骤 2:小明拿走了 3 个苹果。
计算:15 - 3 = 12
现在篮子里有 12 个苹果。
步骤 3:小红又放进去了 5 个苹果。
计算:12 + 5 = 17
现在篮子里有 17 个苹果。
答案:篮子里现在有 17 个苹果。
Tree of Thoughts (ToT)
思维树(Tree of Thoughts)是思维链的扩展,它让模型生成多个可能的推理路径,然后评估每个路径的价值,选择最优路径继续探索。这种方式更适合需要探索和决策的问题。
from typing import List, Tuple
import json
class TreeOfThoughts:
"""思维树推理"""
def __init__(self, max_depth: int = 3, num_thoughts: int = 3):
self.llm = ChatOpenAI(model="gpt-4", temperature=0)
self.max_depth = max_depth
self.num_thoughts = num_thoughts
def generate_thoughts(self, problem: str, current_path: List[str] = None) -> List[str]:
"""生成可能的思考方向"""
context = "\n".join(current_path) if current_path else "这是开始"
prompt = f"""问题:{problem}
当前思考路径:
{context}
请生成 {self.num_thoughts} 个可能的下一步思考方向。
每个方向应该是一个具体的推理步骤。
以 JSON 数组格式返回,如:["思考1", "思考2", "思考3"]"""
response = self.llm.invoke(prompt)
try:
return json.loads(response.content)
except:
return response.content.split("\n")
def evaluate_thoughts(self, problem: str, thoughts: List[str], current_path: List[str]) -> List[Tuple[str, float]]:
"""评估每个思考方向的价值"""
context = "\n".join(current_path) if current_path else ""
prompt = f"""问题:{problem}
当前路径:{context}
候选思考方向:
{chr(10).join([f"{i+1}. {t}" for i, t in enumerate(thoughts)])}
请为每个思考方向评分(0-10分),评估其对解决问题的价值。
返回 JSON 数组,如:[8, 5, 7]"""
response = self.llm.invoke(prompt)
try:
scores = json.loads(response.content)
except:
scores = [5.0] * len(thoughts)
return list(zip(thoughts, scores))
def solve(self, problem: str) -> str:
"""使用思维树解决问题"""
best_path = []
def explore(path: List[str], depth: int):
if depth >= self.max_depth:
return path
thoughts = self.generate_thoughts(problem, path)
evaluated = self.evaluate_thoughts(problem, thoughts, path)
# 选择得分最高的方向
best_thought, best_score = max(evaluated, key=lambda x: x[1])
new_path = path + [best_thought]
return explore(new_path, depth + 1)
best_path = explore([], 0)
# 基于最佳路径生成最终答案
prompt = f"""问题:{problem}
思考路径:
{chr(10).join(best_path)}
请根据以上思考路径,给出最终答案。"""
return self.llm.invoke(prompt).content
# 使用示例
tot = TreeOfThoughts(max_depth=3, num_thoughts=3)
problem = "如何在一个月内提高英语口语能力?"
answer = tot.solve(problem)
print(answer)
规划在 LangGraph 中的实现
使用 LangGraph 可以更灵活地实现各种规划策略。以下是一个完整的规划-执行-反思循环:
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List, Literal
from langchain_openai import ChatOpenAI
import operator
class AgentState(TypedDict):
"""Agent 状态"""
goal: str
plan: List[str]
current_step: int
execution_results: Annotated[List[dict], operator.add]
reflection: dict
iterations: int
final_answer: str
llm = ChatOpenAI(model="gpt-4", temperature=0)
def plan_node(state: AgentState) -> dict:
"""规划节点"""
prompt = f"""请为以下目标制定执行计划:
目标:{state['goal']}
{f"之前的尝试失败,原因:{state['reflection'].get('issues', [])}" if state.get('reflection') else ""}
请输出具体的执行步骤列表。"""
response = llm.invoke(prompt)
plan = [line.strip() for line in response.content.split("\n")
if line.strip() and not line.strip().startswith("#")]
return {"plan": plan, "current_step": 0}
def execute_node(state: AgentState) -> dict:
"""执行节点"""
current_idx = state["current_step"]
current_task = state["plan"][current_idx]
# 执行任务(这里用 LLM 模拟)
prompt = f"请执行任务:{current_task}"
result = llm.invoke(prompt).content
return {
"current_step": current_idx + 1,
"execution_results": [{
"step": current_idx + 1,
"task": current_task,
"result": result
}]
}
def reflect_node(state: AgentState) -> dict:
"""反思节点"""
results = state["execution_results"]
prompt = f"""目标:{state['goal']}
执行结果:
{chr(10).join([f"步骤{r['step']}: {r['task']} -> {r['result'][:100]}..." for r in results])}
请反思:
1. 任务是否成功?
2. 有什么问题?
3. 需要重新规划吗?
返回 JSON 格式的反思结果。"""
response = llm.invoke(prompt)
import json
try:
reflection = json.loads(response.content)
except:
reflection = {"success": True, "needs_replanning": False}
return {
"reflection": reflection,
"iterations": state["iterations"] + 1
}
def route_after_execution(state: AgentState) -> Literal["execute", "reflect", "end"]:
"""执行后路由"""
# 检查是否还有未执行的步骤
if state["current_step"] < len(state["plan"]):
return "execute"
# 所有步骤完成,进入反思
return "reflect"
def route_after_reflection(state: AgentState) -> Literal["plan", "finalize", "end"]:
"""反思后路由"""
reflection = state.get("reflection", {})
# 检查是否需要重新规划
if reflection.get("needs_replanning", False) and state["iterations"] < 3:
return "plan"
# 检查是否成功
if reflection.get("success", True):
return "finalize"
# 超过最大迭代次数,强制结束
return "end"
def finalize_node(state: AgentState) -> dict:
"""生成最终结果"""
results = state["execution_results"]
prompt = f"""目标:{state['goal']}
执行过程:
{chr(10).join([f"步骤{r['step']}: {r['task']}" for r in results])}
执行结果:
{chr(10).join([r['result'] for r in results])}
请给出最终总结。"""
return {"final_answer": llm.invoke(prompt).content}
# 构建图
workflow = StateGraph(AgentState)
workflow.add_node("plan", plan_node)
workflow.add_node("execute", execute_node)
workflow.add_node("reflect", reflect_node)
workflow.add_node("finalize", finalize_node)
workflow.set_entry_point("plan")
workflow.add_edge("plan", "execute")
workflow.add_conditional_edges("execute", route_after_execution, {
"execute": "execute",
"reflect": "reflect"
})
workflow.add_conditional_edges("reflect", route_after_reflection, {
"plan": "plan",
"finalize": "finalize",
"end": END
})
workflow.add_edge("finalize", END)
app = workflow.compile()
# 执行
result = app.invoke({
"goal": "帮我分析最近的科技新闻趋势",
"plan": [],
"current_step": 0,
"execution_results": [],
"reflection": {},
"iterations": 0,
"final_answer": ""
})
print(result["final_answer"])
规划最佳实践
保持计划的可执行性
每个子任务都应该足够具体,让 Agent 能够明确知道要做什么。避免过于抽象的计划。
# 不好的计划
bad_plan = [
"研究市场",
"分析数据",
"写报告"
]
# 好的计划
good_plan = [
"搜索最近一个月的市场分析报告",
"提取关键数据和趋势信息",
"对比三个主要竞争对手的市场表现",
"撰写 500 字的市场趋势分析摘要"
]
设置合理的终止条件
规划系统需要知道何时停止:
- 达到目标状态
- 执行完所有计划步骤
- 超过最大迭代次数
- 连续失败次数超过阈值
平衡规划深度与执行效率
过深的计划分解会增加系统复杂度,过浅则可能导致任务不清晰。根据任务复杂度选择合适的分解深度:
- 简单任务:1 层分解
- 中等任务:2 层分解
- 复杂任务:2-3 层分解,配合动态规划
小结
规划是 AI Agent 处理复杂任务的核心能力:
- 任务分解是规划的基础,包括顺序分解、并行分解和嵌套分解
- Plan-and-Execute 模式将规划和执行分离,结构清晰
- 自我反思让 Agent 能够评估执行结果,必要时重新规划
- 思维链和思维树等推理增强技术可以提高规划质量
- LangGraph 提供了灵活的状态图机制来实现复杂的规划逻辑
下一章我们将学习如何使用 LangChain 构建完整的 Agent 应用。