纲要
- 智能体优化的必要性
- 计划与执行模式
- 核心原理
- 流程与节点设计
- 完整可运行示例
- 反思模式
- 核心原理
- 流程与节点设计
- 完整可运行示例
- 两种模式的对比与选型建议
- 总结与相关度说明
智能体优化的必要性
在之前的实践中,我们构建了单智能体和多智能体应用,但基础的 React 循环在处理复杂、需要多步推理的任务时,往往缺乏全局视角和自我修正能力。为此,业界提出了多种架构优化方案,其中计划与执行 和反思 是两种最经典且实用的模式。它们同样可以基于 LangGraph 实现,通过引入规划或批判节点,显著提升输出质量。
计划与执行模式
核心原理
计划与执行模式模拟人类解决复杂问题的过程:先整体规划,再逐步执行,并在执行中动态调整计划。其工作流包含三个关键阶段:
- 规划:根据用户目标生成任务步骤清单。
- 执行:逐项完成清单中的任务,每个子任务可由独立工具或智能体处理。
- 重规划:检查已完成的步骤结果,更新计划,可能添加新步骤或调整顺序,直至获得最终答案。
#mermaid-svg-qcCUxj3DonDheeaN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qcCUxj3DonDheeaN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qcCUxj3DonDheeaN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qcCUxj3DonDheeaN .error-icon{fill:#552222;}#mermaid-svg-qcCUxj3DonDheeaN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qcCUxj3DonDheeaN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qcCUxj3DonDheeaN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qcCUxj3DonDheeaN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qcCUxj3DonDheeaN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qcCUxj3DonDheeaN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qcCUxj3DonDheeaN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qcCUxj3DonDheeaN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qcCUxj3DonDheeaN .marker.cross{stroke:#333333;}#mermaid-svg-qcCUxj3DonDheeaN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qcCUxj3DonDheeaN p{margin:0;}#mermaid-svg-qcCUxj3DonDheeaN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qcCUxj3DonDheeaN .cluster-label text{fill:#333;}#mermaid-svg-qcCUxj3DonDheeaN .cluster-label span{color:#333;}#mermaid-svg-qcCUxj3DonDheeaN .cluster-label span p{background-color:transparent;}#mermaid-svg-qcCUxj3DonDheeaN .label text,#mermaid-svg-qcCUxj3DonDheeaN span{fill:#333;color:#333;}#mermaid-svg-qcCUxj3DonDheeaN .node rect,#mermaid-svg-qcCUxj3DonDheeaN .node circle,#mermaid-svg-qcCUxj3DonDheeaN .node ellipse,#mermaid-svg-qcCUxj3DonDheeaN .node polygon,#mermaid-svg-qcCUxj3DonDheeaN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qcCUxj3DonDheeaN .rough-node .label text,#mermaid-svg-qcCUxj3DonDheeaN .node .label text,#mermaid-svg-qcCUxj3DonDheeaN .image-shape .label,#mermaid-svg-qcCUxj3DonDheeaN .icon-shape .label{text-anchor:middle;}#mermaid-svg-qcCUxj3DonDheeaN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qcCUxj3DonDheeaN .rough-node .label,#mermaid-svg-qcCUxj3DonDheeaN .node .label,#mermaid-svg-qcCUxj3DonDheeaN .image-shape .label,#mermaid-svg-qcCUxj3DonDheeaN .icon-shape .label{text-align:center;}#mermaid-svg-qcCUxj3DonDheeaN .node.clickable{cursor:pointer;}#mermaid-svg-qcCUxj3DonDheeaN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qcCUxj3DonDheeaN .arrowheadPath{fill:#333333;}#mermaid-svg-qcCUxj3DonDheeaN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qcCUxj3DonDheeaN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qcCUxj3DonDheeaN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qcCUxj3DonDheeaN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qcCUxj3DonDheeaN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qcCUxj3DonDheeaN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qcCUxj3DonDheeaN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qcCUxj3DonDheeaN .cluster text{fill:#333;}#mermaid-svg-qcCUxj3DonDheeaN .cluster span{color:#333;}#mermaid-svg-qcCUxj3DonDheeaN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qcCUxj3DonDheeaN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qcCUxj3DonDheeaN rect.text{fill:none;stroke-width:0;}#mermaid-svg-qcCUxj3DonDheeaN .icon-shape,#mermaid-svg-qcCUxj3DonDheeaN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qcCUxj3DonDheeaN .icon-shape p,#mermaid-svg-qcCUxj3DonDheeaN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qcCUxj3DonDheeaN .icon-shape .label rect,#mermaid-svg-qcCUxj3DonDheeaN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qcCUxj3DonDheeaN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qcCUxj3DonDheeaN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qcCUxj3DonDheeaN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 还有未完成步骤
全部完成
用户目标
规划节点: 生成步骤列表
执行节点: 完成当前步骤
重规划节点: 评估进度
输出最终答案
该模式的长处在于清晰的长期计划,且执行子任务时可使用较弱模型以降低成本。缺点是延迟较高,不适合实时对话场景。
完整可运行示例
下面使用 LangGraph 构建一个简化的计划与执行智能体,它会先制定步骤,然后调用模拟搜索工具逐步执行。
首先安装依赖:
bash
pip install langgraph langchain-openai python-dotenv
python
# plan_execute.py
import os
from typing import TypedDict, List
from dotenv import load_dotenv
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
from langgraph.checkpoint.memory import MemorySaver
load_dotenv()
# ---------- 结构化输出模型 ----------
class Plan(BaseModel):
steps: List[str] = Field(description="执行步骤列表")
class Act(BaseModel):
action: str = Field(description="'plan' 表示继续执行,'response' 表示直接回答")
updated_plan: List[str] = Field(default=[], description="更新后的剩余步骤")
response: str = Field(default="", description="如果 action 为 response,则提供答案")
# ---------- 状态定义 ----------
class PlanExecuteState(TypedDict):
input: str
plan: List[str]
executed_steps: List[str]
final_answer: str
# ---------- LLM 初始化 ----------
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
planner_llm = llm.with_structured_output(Plan)
replanner_llm = llm.with_structured_output(Act)
# ---------- 模拟搜索工具 ----------
def fake_search(query: str) -> str:
if "短跑" in query or "女子" in query:
return "中国女子短跑最快选手是韦永丽,成绩为10.99秒。"
return "未找到相关信息。"
# ---------- 节点函数 ----------
def planner_node(state: PlanExecuteState) -> PlanExecuteState:
prompt = ChatPromptTemplate.from_template(
"针对以下目标,制定一个简单的逐步计划,每步应独立且可执行,最后一步结果应为最终答案。\n"
"目标:{input}\n计划:"
)
chain = prompt | planner_llm
plan = chain.invoke({"input": state["input"]})
return {"plan": plan.steps, "executed_steps": []}
def agent_node(state: PlanExecuteState) -> PlanExecuteState:
if not state["plan"]:
return state
step = state["plan"][0] # 取第一个未执行的步骤
result = fake_search(step)
executed = state.get("executed_steps", []) + [f"执行"{step}" → {result}"]
return {"plan": state["plan"][1:], "executed_steps": executed}
def replanner_node(state: PlanExecuteState) -> PlanExecuteState:
prompt = ChatPromptTemplate.from_template(
"原始目标:{input}\n已完成步骤及结果:{executed}\n剩余步骤:{plan}\n"
"请判断是否可以直接回答。如果可以,用 'response' 动作输出答案;否则用 'plan' 动作提供更新后的剩余步骤。"
)
chain = prompt | replanner_llm
act = chain.invoke({
"input": state["input"],
"executed": state["executed_steps"],
"plan": state["plan"]
})
if act.action == "response":
return {"final_answer": act.response, "plan": []}
return {"plan": act.updated_plan}
def route(state: PlanExecuteState) -> str:
if state.get("final_answer"):
return "end"
return "continue" if state["plan"] else "end"
# ---------- 构建图 ----------
builder = StateGraph(PlanExecuteState)
builder.add_node("planner", planner_node)
builder.add_node("agent", agent_node)
builder.add_node("replanner", replanner_node)
builder.set_entry_point("planner")
builder.add_edge("planner", "agent")
builder.add_edge("agent", "replanner")
builder.add_conditional_edges("replanner", route, {"continue": "agent", "end": END})
memory = MemorySaver()
app = builder.compile(checkpointer=memory)
# ---------- 测试 ----------
if __name__ == "__main__":
config = {"configurable": {"thread_id": "plan-demo"}}
result = app.invoke({"input": "中国女子短跑最快的选手是谁?"}, config)
if result.get("final_answer"):
print("最终答案:", result["final_answer"])
else:
print("执行记录:", result["executed_steps"])
运行示例将看到智能体先规划步骤,再逐步执行并最终给出答案。
反思模式
核心原理
反思模式在生成器之后增加一个批判者角色,形成"写作→评审→改进"的循环。生成节点创建内容,反思节点给出详细反馈,生成节点据此修改,如此反复,直至满足质量要求。
#mermaid-svg-8CVJU0n2wHfJVKlQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8CVJU0n2wHfJVKlQ .error-icon{fill:#552222;}#mermaid-svg-8CVJU0n2wHfJVKlQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8CVJU0n2wHfJVKlQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .marker.cross{stroke:#333333;}#mermaid-svg-8CVJU0n2wHfJVKlQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8CVJU0n2wHfJVKlQ p{margin:0;}#mermaid-svg-8CVJU0n2wHfJVKlQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster-label text{fill:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster-label span{color:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster-label span p{background-color:transparent;}#mermaid-svg-8CVJU0n2wHfJVKlQ .label text,#mermaid-svg-8CVJU0n2wHfJVKlQ span{fill:#333;color:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .node rect,#mermaid-svg-8CVJU0n2wHfJVKlQ .node circle,#mermaid-svg-8CVJU0n2wHfJVKlQ .node ellipse,#mermaid-svg-8CVJU0n2wHfJVKlQ .node polygon,#mermaid-svg-8CVJU0n2wHfJVKlQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .rough-node .label text,#mermaid-svg-8CVJU0n2wHfJVKlQ .node .label text,#mermaid-svg-8CVJU0n2wHfJVKlQ .image-shape .label,#mermaid-svg-8CVJU0n2wHfJVKlQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-8CVJU0n2wHfJVKlQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .rough-node .label,#mermaid-svg-8CVJU0n2wHfJVKlQ .node .label,#mermaid-svg-8CVJU0n2wHfJVKlQ .image-shape .label,#mermaid-svg-8CVJU0n2wHfJVKlQ .icon-shape .label{text-align:center;}#mermaid-svg-8CVJU0n2wHfJVKlQ .node.clickable{cursor:pointer;}#mermaid-svg-8CVJU0n2wHfJVKlQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .arrowheadPath{fill:#333333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8CVJU0n2wHfJVKlQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8CVJU0n2wHfJVKlQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8CVJU0n2wHfJVKlQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster text{fill:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ .cluster span{color:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8CVJU0n2wHfJVKlQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8CVJU0n2wHfJVKlQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-8CVJU0n2wHfJVKlQ .icon-shape,#mermaid-svg-8CVJU0n2wHfJVKlQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8CVJU0n2wHfJVKlQ .icon-shape p,#mermaid-svg-8CVJU0n2wHfJVKlQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8CVJU0n2wHfJVKlQ .icon-shape .label rect,#mermaid-svg-8CVJU0n2wHfJVKlQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8CVJU0n2wHfJVKlQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8CVJU0n2wHfJVKlQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8CVJU0n2wHfJVKlQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 需改进
已满意
用户请求
生成节点: 创建初稿
反思节点: 评审并给出建议
输出最终内容
该模式尤其适合需要反复打磨的创作任务,如文章撰写、代码优化等。缺点同样是多轮调用带来更高的延迟和成本。
完整可运行示例
构建一个文章撰写智能体,通过反思迭代提升文章质量。
python
# reflection_writer.py
import os
from typing import TypedDict
from dotenv import load_dotenv
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
load_dotenv()
class WriterState(TypedDict):
task: str
draft: str
feedback: str
iteration: int
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
def generate_draft(state: WriterState) -> WriterState:
prompt = f"你是一名文章助手。任务:{state['task']}\n"
if state.get("feedback"):
prompt += f"上一次的反馈意见:{state['feedback']}\n请根据反馈修改文章。"
response = llm.invoke([HumanMessage(content=prompt)])
return {"draft": response.content, "iteration": state.get("iteration", 0) + 1}
def reflect_on_draft(state: WriterState) -> WriterState:
prompt = f"你是一名严格编辑。请评审以下文章,指出不足并给出改进建议。\n文章:{state['draft']}\n建议:"
response = llm.invoke([HumanMessage(content=prompt)])
return {"feedback": response.content}
def should_continue(state: WriterState) -> str:
return "end" if state.get("iteration", 0) >= 3 else "continue"
builder = StateGraph(WriterState)
builder.add_node("generator", generate_draft)
builder.add_node("reflector", reflect_on_draft)
builder.set_entry_point("generator")
builder.add_edge("generator", "reflector")
builder.add_conditional_edges("reflector", should_continue, {"continue": "generator", "end": END})
memory = MemorySaver()
app = builder.compile(checkpointer=memory)
if __name__ == "__main__":
config = {"configurable": {"thread_id": "reflect-demo"}}
final = app.invoke({"task": "写一篇关于科学用脑的短文,约300字,通俗易懂。"}, config)
print("最终文章:\n", final["draft"])
print("\n迭代次数:", final["iteration"])
运行后会看到文章在多轮反思后质量明显提升。
两种模式的对比与选型建议
| 维度 | 计划与执行 | 反思 |
|---|---|---|
| 核心思想 | 全局规划→逐步执行→动态调整 | 生成→评审→改进循环 |
| 典型应用 | 复杂多步任务、信息检索类 | 文案写作、代码优化等创造性任务 |
| 延迟 | 较高 | 较高 |
| 模型成本 | 规划节点可用强模型,执行节点可用弱模型 | 生成和反思节点均需一定能力 |
| 实现复杂度 | 较复杂,需要三个主要节点 | 相对简单,两个主要节点 |
两种模式可以组合使用,例如在计划执行的每个步骤中嵌入反思,以获得更好的效果。
总结
本博客详细讲解了智能体架构优化的两种经典模式:计划与执行、反思,并给出了基于 LangGraph 的完整可运行代码。掌握这些模式后,你可以根据任务需求选择合适的优化策略,或进行创新组合,从而构建更强大、更可靠的 AI 应用。
本文覆盖了计划与执行、反思的原理、流程和代码实现,并补充了示例代码。