ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

D03-L2-PlanAndExecute深度解析

D03-L2-PlanAndExecute深度解析 先计划再执行Plan-and-Execute 范式深度解析附完整 Python 实现适合人群已理解 ReAct 循环、想掌握第二种主流 Agent 规划范式的开发者 引言ReAct 很好但有一个致命短板上一篇我们手写了 ReAct模型边想边做每一步都调用一次大模型、交换一次上下文。灵活是灵活但每一个步骤都在烧 Token而且步骤不可控——你不知道它会在第几步停下来。想象一个场景你要处理一份 50 行的数据处理流水线。如果用 ReAct模型每处理一步就要想一次、调一次 API成本高、还不稳定。Plan-and-Execute先计划再执行就是针对这个问题的答案先把完整计划一次性想清楚再按计划执行中途除非出错不再反复想。一、Plan-and-Execute 的核心思想一句话把规划和执行分离成两个角色。用户目标 ↓ Planner规划器一次性生成完整步骤计划 ↓ Executor执行器按计划逐个执行工具 ↓ 某步失败→ Replanner重规划器基于错误调整剩余计划 ↓ 全部步骤完成 → 汇总结果 → 最终答案三个角色各司其职角色职责调用 LLM 的次数Planner把目标拆成有序步骤清单1 次计划阶段Executor执行每一步调工具、拿结果不调 LLM只执行Replanner执行出问题时调整剩余计划按需异常时关键差异ReAct 是每一步都让 LLM 思考而 Plan-and-Execute 是只让 LLM 想一次剩下交给程序执行。规划是智能的执行是确定性的。二、Plan-and-Execute vs ReAct一张表看懂维度ReActPlan-and-Execute规划时机边做边想逐步先整体规划再执行Token 消耗高每步都推理低只在规划/重规划时推理步骤可控性不可控模型自由发挥可控计划清单明确灵活应变强随时调整方向弱计划外的变化需触发重规划适合任务探索型信息搜集、开放问答流程型数据处理、批量任务、多步流水线失败恢复自然纠错思考换路依赖 Replanner 触发选型口诀任务步骤可提前预判→ Plan-and-Execute边走边看→ ReAct。三、完整实现Planner → Executor → Replanner下面用 OpenAI SDK 实现一个最小但完整的 Plan-and-Execute 系统。功能给定目标Planner 生成步骤计划Executor 调用工具执行某一步失败时 Replanner 修正剩余计划。3.1 准备工作pipinstallopenai并设置环境变量OPENAI_API_KEY。3.2 完整代码importjsonfromopenaiimportOpenAI clientOpenAI()# 自动读取 OPENAI_API_KEY# ---------- 工具 ----------defsearch(query:str)-str:模拟搜索真实项目替换为 Tavily / SerpAPI 等db{2024年奥运会在哪里举办:2024 年奥运会在法国巴黎举办。,北京与巴黎的时差:北京与巴黎时差 7 小时冬令时巴黎比北京晚 7 小时。,}returndb.get(query,f未找到与「{query}」相关的资料)defcalculator(expr:str)-str:计算数学表达式演示用生产环境请勿直接使用 evalreturnstr(eval(expr))TOOLS{search:search,calculator:calculator}# ---------- Planner一次性生成计划 ----------PLANNER_PROMPT你是一位任务规划器。请把用户目标拆解为 2~5 个有序步骤。 每个步骤只能调用一个工具。可用工具 - search: {query: 搜索关键词} - calculator: {expr: 数学表达式} 只输出 JSON 数组不要输出任何其他内容。格式 [{tool: search, args: {query: ...}, goal: 这一步的目的}] defplan(goal:str)-list:调用 LLM 生成步骤计划respclient.chat.completions.create(modelgpt-4o-mini,messages[{role:system,content:PLANNER_PROMPT},{role:user,content:f用户目标{goal}},],)textresp.choices[0].message.content# 兼容模型输出中可能的代码块包裹texttext.strip().removeprefix(json).removesuffix().strip()stepsjson.loads(text)ifnotisinstance(steps,list)orlen(steps)0:raiseValueError(计划格式异常)returnsteps# ---------- Replanner执行失败时重规划剩余部分 ----------REPLANNER_PROMPT你是任务重规划器。执行过程中某个步骤失败了请根据错误信息 重新生成【剩余步骤】的计划。可用工具search / calculator。 只输出 JSON 数组格式同前。defreplan(goal:str,done:list,error:str)-list:基于已完成的步骤与错误信息重新生成剩余计划respclient.chat.completions.create(modelgpt-4o-mini,messages[{role:system,content:REPLANNER_PROMPT},{role:user,content:(f用户目标{goal}\nf已完成步骤{json.dumps(done,ensure_asciiFalse)}\nf失败信息{error}\nf请重新生成剩余步骤的计划JSON 数组。)},],)textresp.choices[0].message.content.strip()texttext.removeprefix(json).removesuffix().strip()returnjson.loads(text)# ---------- Executor确定性执行单步 ----------defexecute_step(step:dict):执行一个步骤返回 (是否成功, 结果文本)toolstep.get(tool)argsstep.get(args,{})iftoolnotinTOOLS:returnFalse,f未知工具{tool}try:resultTOOLS[tool](**args)returnTrue,resultexceptExceptionase:# 工具执行异常returnFalse,f工具执行失败{e}# ---------- 主流程Plan → Execute → (Replan) → Summarize ----------defrun(goal:str)-str:# 1) 规划stepsplan(goal)print( 初始计划,json.dumps(steps,ensure_asciiFalse,indent2))results,done[],[]i0whileilen(steps):stepsteps[i]print(f⚙️ 执行步骤{i1}/{len(steps)}{step.get(tool)}{step.get(args)})ok,outexecute_step(step)ifok:results.append({step:step,result:out})done.append(step)i1else:# 2) 失败 → 触发重规划print(f⚠️ 步骤失败{out}触发重规划…)stepsreplan(goal,done,out)i0# 从头执行新的剩余计划保持顺序简单# 3) 汇总把步骤结果交给 LLM 生成最终答案summaryclient.chat.completions.create(modelgpt-4o-mini,messages[{role:system,content:你是总结助手根据执行记录用中文简洁回答用户目标。},{role:user,content:(f用户目标{goal}\n执行记录{json.dumps(results,ensure_asciiFalse,indent2)})},],)returnsummary.choices[0].message.contentif__name____main__:answerrun(2024年奥运会在哪里举办举办地巴黎与北京的时差是几小时)print(f✅ 最终答案{answer})3.3 运行效果示意 初始计划 [ {tool: search, args: {query: 2024年奥运会在哪里举办}, goal: 查询举办地}, {tool: search, args: {query: 北京与巴黎的时差}, goal: 查询时差} ] ⚙️ 执行步骤 1/2search {query: 2024年奥运会在哪里举办} ⚙️ 执行步骤 2/2search {query: 北京与巴黎的时差} ✅ 最终答案2024 年奥运会在法国巴黎举办巴黎比北京晚 7 小时。对比 ReAct整个过程LLM 只被调用 2 次1 次规划 1 次汇总执行全部由确定性代码完成——这就是省 Token 的秘密。四、工程实践中的三个关键点4.1 计划要做校验不能盲信 LLMPlanner 返回的 JSON 可能格式错乱或出现未知工具。三个保险解析容错剥离代码块包裹、处理 JSON 解析失败示例已做白名单校验tool必须存在于TOOLS未知工具直接跳过步骤上限计划步骤数限制在 2~5防止 LLM 生成 20 步的离谱计划。4.2 重规划的触发条件要克制不是所有失败都要重规划。建议分级处理可重试错误网络抖动、临时 429→ 先重试不重规划逻辑错误工具参数不对、检索无结果→ 才触发 Replanner重规划次数上限如 2 次→ 超限直接终止并返回错误避免无限循环。4.3 安全提醒 ⚠️示例中calculator使用eval()仅用于演示生产环境存在代码注入风险请改用ast.literal_eval或专用计算库并对工具做白名单与权限校验。五、适用场景与选型建议强烈推荐用 Plan-and-Execute 的场景数据处理流水线清洗 → 转换 → 聚合 → 导出步骤固定批量报表生成多数据源抓取后统一汇总️日程编排查交通 → 查酒店 → 排行程顺序明确与人工流程对齐需要向业务方展示接下来会做什么的确定性步骤。仍应选 ReAct 的场景开放探索答案在哪都不知道需要边搜边调整多轮对话式推理用户会不断补充信息。工程上两者常混用用 Plan-and-Execute 定骨架遇到计划外的分叉再降级为 ReAct 模式——这也是图编排框架如 LangGraph能同时支持两种模式的原因。✅ 总结Plan-and-Execute 规划与执行分离Planner 一次性出计划Executor 确定性执行Replanner 按需修正相比 ReActToken 消耗更低、步骤可控、稳定可预测代价是灵活性下降工程三件套计划校验 分级重试/重规划 重规划次数上限选型口诀能预判步骤就先计划探索性任务才边想边做与 ReAct、Reflexion 组成三大规划范式按任务特性搭配使用。 觉得有用就点赞 收藏 关注更多 AI Agent 干货持续输出。
返回列表