前言
本文主要描述Plan-and-Execute开发中的ReAct模式,并且使用一个demo,彻底搞懂怎么在实际工作中使用Plan-and-Execute模式
话不多说,我们开始
代码结构
text
.
├── main.py # 主入口,串起规划、执行、分析三个阶段
├── planner.py # Planner,负责让 LLM 先生成排查计划
├── executor.py # Executor,负责按计划调用工具
├── analyzer.py # Analyzer,负责根据工具结果做最终分析
└── tools.py # 工具层,模拟告警、日志、错误分析等数据源
先规划 → 再执行 → 最后总结,这就是典型的 Plan-and-Execute 模式
- ReAct 更像一个值班同学一边查一边想:先看告警,不够再看日志,再不够继续查 SQL
- Plan-and-Execute 更像先开一个排障 checklist:先查告警,再查日志,再分析错误,最后汇总根因
代码解析
-
main.py,代码入口,分成三部完成需求
make_plan(user_input)让 LLM 根据用户输入生成一个计划executor.run(plan)按计划调用工具,并收集每一步结果analyze(user_input, observations)把用户问题和工具结果交给 LLM,生成最终结论
-
planner.py,调用一次llm,让大模型自动生成计划- 自动扫描
tools.py里的函数,把函数名、参数、docstring 都提取出来 - 构造prompt,明确llm的角色以及可以调用的tools,并且按照固定的格式返回
- 自动扫描
-
executor.py,按计划调用工具,并收集每一步结果 -
tools,所有能够调用的工具都记录在此query_alarm,查询服务的监控告警query_logs,查询服务日志analyze_errors,分析错误日志
-
analyzer.py,再次调用llm,将获得数据结果与需求进行综合分析得出结论
执行链路
把这几个模块串起来,完整执行链路是这样的:
Plan-and-Execute 特点
计划现行,先让模型把任务拆成计划,再由执行器按计划完成,最后再统一汇总
比如一次线上故障排查,可能要同时看告警、日志、链路追踪、数据库、发布记录、配置变更。那就把这些需要采集的信息列一个计划,然后逐一获取数据,最后再来汇总分析
优点:后续所有的操作全是围绕着最初制定的计划来执行,不会出现跑偏的情况,并且不需要频繁与大模型交互,减少时间、token的损耗
缺点:一但制定的计划不合理,那后续的工作就肯定事倍功半,因为在运行途中没有主动纠错的能力
和 ReAct 的核心区别
ReAct 是边执行边决策
Plan-and-Execute 是先决策再执行
| 维度 | Plan-and-Execute | ReAct |
|---|---|---|
| 决策方式 | 先生成计划,再执行 | 每一轮根据 Observation 决定下一步 |
| 可控性 | 更强,计划可审查 | 相对弱,路径更动态 |
| 灵活性 | 一般,依赖初始计划质量 | 更强,能根据中间结果调整 |
| 成本 | 通常更可控 | 多轮调用时成本更高 |
| 延迟 | 路径明确时更低 | 轮数多时延迟更高 |
| 可解释性 | 计划天然可展示 | 过程可解释,但轨迹可能更长 |
| 工程治理 | 更容易加审批、限流、审计 | 需要对每轮 Action 做治理 |
| 适合任务 | 流程清晰、步骤稳定、可批处理 | 探索性强、信息不确定、需要动态调整 |
更适合 Plan-and-Execute 的场景
流程相对固定的任务
这类任务的特点是:步骤大体稳定,顺序大体明确,执行过程中不需要与大模型参与
- 标准化巡检
- 常规故障排查
- 批量数据分析
- 固定格式报告生成
- 发布前检查
- 安全基线扫描
需要审批和审计的任务
如果 agent 涉及高风险操作,
1)修改配置
2)重启服务
3)扩容缩容
4)执行 SQL
5)发起回滚
计划先出来,系统可以先展示给人看:
json
[
{
"step": 1,
"tool": "query_alarm",
"args": {"service": "order-service"},
"reason": "确认服务是否处于告警状态"
},
{
"step": 2,
"tool": "rollback_release",
"args": {"service": "order-service", "version": "v1.2.3"},
"reason": "最近发布后错误率上升,尝试回滚"
}
]
这时候系统可以拦住第二步,要求人工确认
批处理的任务
帮我分析最近 20 个告警,按服务归类,找出最可能的共性根因。这类任务如果用 ReAct,很可能一轮一轮查,过程会比较长
Plan-and-Execute 可以先生成一个批处理计划:
text
1)拉取最近 20 个告警
2)按 service 聚合
3)查询每个 service 的错误率和日志
4)提取共性关键词
5)生成汇总报告
这种任务不需要模型每一步重新想。它需要的是稳定执行和最后归纳
更适合 ReAct 的场景
笔者觉得主要是探索性任务。
比如:
- 问题边界不清楚
- 不知道下一步该查什么
- 工具结果会强烈影响后续路径
- 需要不断缩小问题范围
- 任务目标会随着中间证据变化
比如线上故障里,用户只说一句:
text
系统有点慢,帮我看看。
这时候你很难一开始就列出完整计划。因为"慢"可能来自网关、服务、数据库、缓存、第三方依赖,也可能是用户网络问题
ReAct 更适合这种情况:
text
先查整体告警 → 发现订单服务异常 → 查订单日志 → 发现 DB timeout → 查数据库指标 → 发现慢 SQL → 查最近发布 → 定位变更
混合使用
更常见的做法是混合使用。
比如:
-
先 Plan-and-Execute 生成一个大方向计划
-
每个复杂步骤内部再用 ReAct 动态探索
-
最后统一 Analyzer 汇总
举个例子:
text总计划: 1)检查告警 2)检查日志 3)检查数据库 4)检查发布变更 5)输出报告 其中第 3 步"检查数据库"内部,可以用 ReAct: Thought: 先看连接数 Action: query_db_connections Observation: 连接数打满 Thought: 继续查慢 SQL Action: query_slow_sql Observation: 某条 SQL 扫描 300 万行 Final Answer: 数据库瓶颈来自慢 SQL 导致连接池耗尽
这样既有全局计划,也有局部灵活性
代码改进
-
规划plan的时候加入人工确认,如果模型的plan不合理或者还需要加入新步骤的时候,需要人工补充
-
限制最大步骤数。否则模型一口气规划 30 步,浪费时间还耗费token
-
增加工具白名单和权限,或者直接调用mcp
-
支持失败重规划,Plan-and-Execute 的短板是计划不容易中途修正,可以加一个 Replanner,比如某一步工具失败,或者结果明显不足,就把当前 observations 发给模型,让它重新规划后续步骤。
- Plan → Execute → 判断是否足够 → 不足则 Replan → Execute → Analyze,这样就比纯 Plan-and-Execute 更灵活
总结
Plan-and-Execute 的本质先先规划,再执行
它的优点是结构清晰、成本可控、方便审计,也更适合流程明确的工程任务
它的缺点是灵活性不如 ReAct,如果初始计划质量不高,后续执行就容易跑偏
所以任务清楚、流程稳定,用 Plan-and-Execute;问题模糊、需要探索,用 ReAct;场景复杂,就把两者组合起来
联系我
- 联系我,做深入的交流
至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...