纲要
- 智能体优化的必要性
- 计划与执行模式
- 核心原理
- 流程与节点设计
- 完整可运行示例
- 反思模式
- 核心原理
- 流程与节点设计
- 完整可运行示例
- 两种模式的对比与选型建议
- API 速览
- Demo 示例
- 总结
- 官方文档与参考链接
- 润色纠正的前后对比
智能体优化的必要性
在构建单智能体与多智能体应用的过程中,基础的 ReAct 循环(Reasoning + Acting)在处理复杂、多步推理任务时,常因缺乏全局规划与自我修正能力,导致执行路径次优或最终结果质量不稳定。为解决此类问题,业界提出了多种架构优化策略。
其中,计划与执行(Plan-and-Execute) 与 反思(Reflection) 是两种经典且广泛实践的模式。这两种模式均可基于 LangGraph 框架实现,通过引入规划节点或批判节点,有效提升智能体在复杂任务中的输出质量与执行可靠性。
计划与执行模式
核心原理
计划与执行模式模拟人类解决复杂问题的认知过程:首先进行全局规划,然后按步骤执行,并在执行过程中根据中间结果动态调整计划。该工作流包含三个关键阶段:
- 规划(Planning):根据用户输入的目标,生成结构化的任务步骤清单。
- 执行(Executing):按顺序执行清单中的子任务,每个子任务可调用独立工具或由专用子智能体处理。
- 重规划(Replanning):检查已完成步骤的执行结果,评估当前进度,据此更新剩余步骤或调整执行顺序,直至满足终止条件并输出最终答案。
该模式的核心优势在于其清晰的长期规划能力,且执行子任务时可选用能力较弱的模型以控制成本。其主要劣势在于多节点串行调用导致较高的延迟,因此不适用于实时对话场景。
流程与节点设计
基于 LangGraph 实现计划与执行模式时,通常需要定义以下核心节点与状态:
- 状态(State):使用
TypedDict定义,包含用户输入、当前计划列表、已执行步骤记录、最终答案等字段。 - 规划节点(Planner Node):调用 LLM 生成初始步骤列表,输出结构化数据(如
Plan模型)。 - 执行节点(Agent Node):从计划列表中取出第一个未执行步骤,调用工具或函数执行,并将结果追加到已执行记录中。
- 重规划节点(Replanner Node):根据已执行结果与剩余计划,判断是否可直接回答;若否,则生成更新后的剩余步骤列表。
- 路由函数(Router):根据重规划节点的输出,决定进入下一轮执行还是终止流程。
完整可运行示例
以下示例使用 LangGraph 构建一个简化版计划与执行智能体。该智能体首先制定步骤,然后调用模拟搜索工具逐步执行,最终给出答案。
环境准备
安装所需依赖:
pip install langgraph langchain-openai python-dotenv
完整代码
# 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) -> dict:
prompt = ChatPromptTemplate.from_template(
"针对以下目标,制定一个简单的逐步计划,每步应独立且可执行,最后一步结果应为最终答案。\n"
"目标:{input}\n计划:"
)
chain = prompt | planner_llm
plan = chain.invoke({"input": state["input"]})
return {"plan": plan.steps}
def agent_node(state: PlanExecuteState) -> dict:
if not state["plan"]:
return {}
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) -> dict:
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.get("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"])
运行上述代码后,智能体会先规划步骤,再逐步调用模拟搜索工具,最终给出答案。
反思模式
核心原理
反思模式在生成器(Generator)之后引入一个批判者(Critic)角色,形成“生成 → 评审 → 改进”的迭代循环。生成节点负责创建初始内容,反思节点对内容进行评审并提供详细改进建议,生成节点据此修改内容,如此反复直至达到预设质量阈值。
该模式尤其适用于需要反复打磨的创造性任务,如文章撰写、代码优化、方案设计等。其主要代价在于多轮 LLM 调用带来的较高延迟与成本。
流程与节点设计
基于 LangGraph 实现反思模式时,通常需要定义以下核心节点与状态:
- 状态(State):包含任务描述、当前草稿、反馈意见、迭代次数等字段。
- 生成节点(Generator Node):根据任务描述和(若有)上一次反馈意见,生成或修改内容。
- 反思节点(Reflector Node):评审当前草稿,指出不足并提出具体改进建议。
- 条件路由(Router):根据迭代次数或内容质量评分,决定继续迭代还是终止输出。
完整可运行示例
以下示例构建一个文章撰写智能体,通过反思迭代提升文章质量。
# 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) -> dict:
prompt = f"你是一名文章助手。任务:{state['task']}\n"
if state.get("feedback"):
prompt += f"上一次的反馈意见:{state['feedback']}\n请根据反馈修改文章。"
else:
prompt += "请撰写初稿。"
response = llm.invoke([HumanMessage(content=prompt)])
return {"draft": response.content, "iteration": state.get("iteration", 0) + 1}
def reflect_on_draft(state: WriterState) -> dict:
prompt = (
f"你是一名严格编辑。请评审以下文章,指出不足并给出具体改进建议。\n"
f"文章:{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"])
运行后,智能体会在多次反思迭代中逐步优化文章内容,最终输出质量较高的版本。
两种模式的对比与选型建议
| 维度 | 计划与执行 | 反思 |
|---|---|---|
| 核心思想 | 全局规划 → 逐步执行 → 动态调整 | 生成 → 评审 → 改进循环 |
| 典型应用 | 复杂多步任务、信息检索、数据收集 | 文章写作、代码优化、创意设计 |
| 延迟 | 较高(多节点串行) | 较高(多轮迭代) |
| 模型成本 | 规划节点可用强模型,执行节点可用弱模型 | 生成与反思节点均需一定推理能力 |
| 实现复杂度 | 较复杂(三个主要节点 + 路由逻辑) | 相对简单(两个主要节点 + 终止条件) |
| 扩展性 | 可嵌套子智能体或工具 | 可与其他模式组合使用 |
在实际应用中,两种模式可以组合使用。例如,在计划与执行的每个子步骤中嵌入反思机制,以进一步提升执行质量。
API 速览
本节梳理博客代码中涉及的核心 API。
LangGraph StateGraph
- 所属库:
langgraph.graph - 方法签名:
StateGraph(state_schema: Type) - 说明:构建状态图的核心类,
state_schema为TypedDict类型,定义图状态的字段。 - 主要方法:
add_node(name: str, function: Callable):添加节点add_edge(from: str, to: str):添加普通边add_conditional_edges(from: str, router: Callable, path_map: dict):添加条件边set_entry_point(name: str):设置入口节点compile(checkpointer: Optional[BaseCheckpointer] = None):编译图为可执行应用
ChatOpenAI.with_structured_output
- 所属库:
langchain_openai - 方法签名:
with_structured_output(schema: Type[BaseModel]) - 说明:将 LLM 输出绑定为结构化 Pydantic 模型,返回的 LLM 实例调用
invoke后直接返回模型实例。
MemorySaver
- 所属库:
langgraph.checkpoint.memory - 方法签名:
MemorySaver() - 说明:提供基于内存的状态检查点保存能力,用于支持会话状态持久化与中断恢复。
Demo 示例
以下提供一个完整、可运行的 HTML 文件,演示计划与执行模式的可视化交互流程。
运行说明:将以下代码保存为 index.html,在浏览器中直接打开即可运行。页面会模拟计划与执行过程,并动态展示每个阶段的状态变化。
技术点总结:
- 使用纯前端模拟
LangGraph的节点流转逻辑 - 展示规划、执行、重规划的完整闭环
- 通过可视化日志呈现每一步的状态变化
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>计划与执行模式可视化 Demo</title>
<style>
* { box-sizing: border-box; }
body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; background: #f8fafc; color: #0f172a; }
h1 { font-size: 1.8rem; font-weight: 600; margin-bottom: 0.5rem; }
.subtitle { color: #475569; margin-bottom: 2rem; }
.card { background: white; border-radius: 12px; padding: 1.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 1.5rem; border: 1px solid #e2e8f0; }
.card h3 { margin-top: 0; font-weight: 500; color: #1e293b; }
.status-bar { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.badge { padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.8rem; font-weight: 500; }
.badge-planner { background: #dbeafe; color: #1d4ed8; }
.badge-agent { background: #d1fae5; color: #065f46; }
.badge-replanner { background: #fef3c7; color: #92400e; }
.badge-end { background: #e2e8f0; color: #334155; }
.log-area { background: #f1f5f9; border-radius: 8px; padding: 1rem; font-family: 'JetBrains Mono', monospace; font-size: 0.85rem; max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; }
.btn { background: #0f172a; color: white; border: none; padding: 0.6rem 1.5rem; border-radius: 8px; font-weight: 500; cursor: pointer; transition: background 0.2s; }
.btn:hover { background: #1e293b; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.flex-row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
</style>
</head>
<body>
<h1>计划与执行模式 · 可视化模拟</h1>
<p class="subtitle">模拟 LangGraph 智能体的 Planner → Agent → Replanner 流转</p>
<div class="card">
<div class="flex-row" style="justify-content: space-between;">
<div>
<span class="badge badge-planner" id="phaseBadge">⏳ 待启动</span>
<span style="margin-left: 0.75rem; font-size: 0.9rem; color: #475569;" id="stepCounter">步骤 0</span>
</div>
<button class="btn" id="runBtn">▶ 执行完整流程</button>
</div>
</div>
<div class="card">
<h3>📋 状态日志</h3>
<div class="log-area" id="logArea">等待执行...</div>
</div>
<script>
// ---------- 模拟状态 ----------
const state = {
input: "中国女子短跑最快的选手是谁?",
plan: [],
executedSteps: [],
finalAnswer: "",
phase: "idle", // idle | planner | agent | replanner | done
stepIndex: 0
};
const logArea = document.getElementById('logArea');
const phaseBadge = document.getElementById('phaseBadge');
const stepCounter = document.getElementById('stepCounter');
const runBtn = document.getElementById('runBtn');
function log(msg) {
logArea.textContent += msg + '\n';
logArea.scrollTop = logArea.scrollHeight;
}
function setPhase(phase, label) {
state.phase = phase;
const map = {
idle: { text: '⏳ 待启动', cls: 'badge-planner' },
planner: { text: '📋 规划中', cls: 'badge-planner' },
agent: { text: '⚙️ 执行中', cls: 'badge-agent' },
replanner: { text: '🔄 重规划', cls: 'badge-replanner' },
done: { text: '✅ 完成', cls: 'badge-end' }
};
const info = map[phase] || map.idle;
phaseBadge.textContent = info.text;
phaseBadge.className = `badge ${info.cls}`;
if (label) stepCounter.textContent = label;
}
// ---------- 模拟节点 ----------
function plannerNode(input) {
setPhase('planner', '生成计划');
log('📌 [Planner] 生成步骤列表...');
const steps = [
"搜索中国女子短跑选手信息",
"查询最快选手成绩",
"整理并输出最终答案"
];
state.plan = steps;
log(`📋 [Planner] 计划: ${steps.join(' → ')}`);
return steps;
}
function agentNode() {
setPhase('agent', `执行步骤 ${state.stepIndex + 1}`);
if (state.plan.length === 0) return null;
const step = state.plan.shift();
log(`🔍 [Agent] 执行: "${step}"`);
// 模拟搜索
let result;
if (step.includes("短跑") || step.includes("选手")) {
result = "中国女子短跑最快选手是韦永丽,成绩为10.99秒。";
} else {
result = "查询完成,已获取相关信息。";
}
state.executedSteps.push(`执行“${step}” → ${result}`);
log(`✅ [Agent] 结果: ${result}`);
return result;
}
function replannerNode() {
setPhase('replanner', '评估进度');
log('🔄 [Replanner] 评估已执行结果...');
// 模拟判断:如果已经执行了足够步骤,直接给出答案
if (state.executedSteps.length >= 3) {
state.finalAnswer = "中国女子短跑最快选手是韦永丽,成绩为10.99秒。";
log(`💬 [Replanner] 可直接回答: ${state.finalAnswer}`);
return "response";
}
// 否则继续执行剩余步骤
log(`📌 [Replanner] 剩余步骤: ${state.plan.length > 0 ? state.plan.join(', ') : '无'}`);
return "plan";
}
// ---------- 执行主流程 ----------
async function runFullPipeline() {
if (runBtn.disabled) return;
runBtn.disabled = true;
logArea.textContent = '';
log('🚀 启动计划与执行流程...');
log(`📝 用户目标: ${state.input}`);
// 重置状态
state.plan = [];
state.executedSteps = [];
state.finalAnswer = "";
state.stepIndex = 0;
// 1. Planner
plannerNode(state.input);
// 2. 循环 Agent + Replanner
let maxIter = 10;
while (maxIter-- > 0 && state.phase !== 'done') {
// Agent
const result = agentNode();
if (!result && state.plan.length === 0) {
// 没有更多步骤,尝试结束
break;
}
state.stepIndex++;
// Replanner
const action = replannerNode();
if (action === "response") {
setPhase('done', '完成');
log(`🎯 最终答案: ${state.finalAnswer}`);
break;
}
// 如果计划为空且没有最终答案,强制结束
if (state.plan.length === 0 && !state.finalAnswer) {
// 构造一个默认答案
state.finalAnswer = state.executedSteps.join('\n');
setPhase('done', '完成');
log(`🎯 流程结束,汇总结果:\n${state.finalAnswer}`);
break;
}
// 模拟异步延迟
await new Promise(r => setTimeout(r, 300));
}
if (state.phase !== 'done') {
setPhase('done', '完成');
log('⚠️ 达到最大迭代次数,流程终止。');
}
log('🏁 流程执行完毕');
runBtn.disabled = false;
}
runBtn.addEventListener('click', runFullPipeline);
// 初始状态
setPhase('idle', '准备就绪');
log('💡 点击 "执行完整流程" 按钮开始模拟');
</script>
</body>
</html>
官方文档与参考链接
官方文档
参考链接
总结
本文系统性地阐述了智能体架构优化的两种经典模式——计划与执行、反思,并提供了基于 LangGraph 的完整可运行代码示例。
计划与执行模式通过全局规划与动态重规划,适用于多步信息检索与复杂任务处理;反思模式通过生成-评审-改进的迭代循环,适用于内容创作与质量优化场景。
两种模式可根据任务特性单独选用或组合使用,为构建高可靠性 AI Agent 应用提供了切实可行的架构参考。
391



被折叠的 条评论
为什么被折叠?



