第 15 章 规划 Planning

第 15 章 规划 Planning

本章要解决的问题

复杂任务要先列计划再执行------计划生成后环境变了怎么办?ReAct 和 Plan-and-Execute 怎么选?

章节大纲

  • 15.1 任务分解:从目标到子任务
  • 15.2 计划生成与动态修正
  • 15.3 ReAct vs Plan-and-Execute 对比
  • 15.4 主流框架对照与变体
  • 🛠 解决方案:计划过期失效的动态重规划

15.1 模式原理:从目标到子任务

15.1.1 一句话定义

规划(Planning)是让模型在动手前先产出执行计划------把一个大目标分解成有序的、可执行的子任务序列,然后按计划推进。 它与提示链(第 10 章)的本质区别在于:提示链的步骤是预先写死的,规划模式的步骤是模型按任务动态生成的。

复制代码
提示链:步骤固定(开发者写死)── 适合可预见的流程
规划:  步骤动态(模型按任务生成)── 适合每次任务都不同的场景

15.1.2 为什么需要规划:不规划的三个代价

让模型直接"蒙头执行"复杂任务,会踩三个坑:

  1. 漏步骤:目标隐含多个环节,模型顺着答只覆盖了一部分(比如"筹备产品发布会"只写了文案,漏了场地、预算、排期)。
  2. 顺序错乱:步骤之间有依赖(先调研再定方案),模型可能先做后置步骤。
  3. 不可审计:没有计划就没有"预期路径",无法判断执行是否偏离。

规划的收益正是:把"黑盒执行"变成"有清单、可检查、可修正"的推进过程。这也是为什么大型任务(项目交付、报告产出、多步骤 Agent)几乎都离不开规划。

15.1.3 任务分解的粒度控制

计划不是越细越好,两条经验法则:

粒度 特点 适用
粗粒度(3~5 步) 灵活、抗变化、步骤易失效 开放式任务、环境多变
中粒度(5~10 步) 平衡 大多数业务任务
细粒度(10+ 步) 清晰但僵化、易过期 流程稳定的任务

计划的粒度应与环境的不确定性成反比:环境越动态,计划越要粗,留出调整空间。

15.2 计划生成与动态修正

15.2.1 计划的结构化输出

计划必须结构化,否则无法校验和执行。推荐格式(JSON):

图 1:计划 JSON 结构

python 复制代码
PLAN_PROMPT = """你是任务规划器。把用户目标分解成执行计划,只输出 JSON:
{
  "objective": "对目标的一句话重述",
  "steps": [
    {"id": 1, "action": "做什么", "depends_on": [0],
     "output": "这一步产出什么", "verify": "怎么确认做对了"}
  ],
  "risks": ["可能的风险"]
}
目标:{goal}"""

关键设计点:

  1. depends_on 显式声明依赖------为并行化留口子(呼应第 12 章:无依赖的步骤可并行执行)。
  2. verify 每步自检方式------为执行中的校验留钩子(呼应第 13、17 章)。
  3. risks 提前暴露风险------让执行器对已知风险有预案。

15.2.2 计划的动态修正:Plan-and-Execute 的"重规划"机制

计划最大的敌人是环境变化 :原计划假设"数据源可用",执行时发现挂了;假设"预算 5 万",中途被告知只有 3 万。此时必须重规划

图 2:动态重规划机制

图 3:Plan-and-Execute

Plan-and-Execute 架构天然支持这一点:执行器每完成一步,回看"计划是否仍成立",不成立就重新规划剩余步骤:

python 复制代码
def plan_and_execute(goal, max_plan_rounds=3):
    plan = generate_plan(goal)               # 生成计划
    for round in range(max_plan_rounds):
        result = execute_plan(plan)          # 按计划执行
        review = check_execution(plan, result)  # 检查是否偏离
        if review["on_track"]:
            return result
        # 偏离 → 带着执行结果重规划剩余步骤
        plan = replan(goal, plan, review["issues"])
    return result

重规划的触发条件(三选一即可):

  1. 某一步执行失败且无法重试(工具挂了、数据源不可用)。
  2. 执行结果与计划假设冲突("市场数据"实际是"竞品数据")。
  3. 用户中途改需求(新增约束/缩小范围)。

重规划 ≠ 从头再来:重规划应保留已完成步骤的结果,只重排"剩余步骤"------不然就是反复烧钱(呼应第 13 章改进检测的"回退"思路)。

15.2.3 执行中的计划校验

光有计划不校验等于没有。执行器在每步完成后做三件事:

  1. 产出校验 :该步的 verify 规则过没过(格式/字段/外部验证)。
  2. 计划一致性:当前结果与计划预期是否吻合,偏差是否可接受。
  3. 目标收敛:做完这步是否离目标更近(防止"绕路执行")。

15.3 ReAct vs Plan-and-Execute 对比

这是规划模式最重要的选型问题,直接决定架构。ReAct(Reasoning + Acting)是 Agent 领域最经典的推理-执行范式。

15.3.1 两种范式的工作原理

ReAct(思考→行动→观察,交错进行)

text 复制代码
思考:我需要知道用户订单状态 → 调用查订单工具
行动:query_order("A123")
观察:{"status": "已发货", "eta": "明天"}
思考:已发货且明天到 → 可以回答用户了
行动:直接回答

每一步都是"想一步 → 做一步 → 看结果 → 再想"的紧密循环。计划藏在思考里,没有独立的计划产物。

Plan-and-Execute(先计划→再执行,两段式)

text 复制代码
[计划阶段]
生成计划:①查订单 ②查物流 ③生成回复(3 步,带依赖)

[执行阶段]
第1步:查订单 → 完成
第2步:查物流 → 完成
第3步:生成回复 → 完成 → 返回

计划先行产出,执行器按清单逐项推进,偏离时重规划。

15.3.2 对比表

维度 ReAct Plan-and-Execute
结构 单循环,思考行动交错 两段式,计划先行
灵活性 极高,随时调整 中,靠重规划调整
可解释性 每步可见但无总览 有计划清单,全局清晰
成本 思考步数多,token 高 路径明确时通常更省;路径频繁变化时重规划会增加成本
上下文占用 每步思考累积,容易长 计划固化后上下文干净
复杂任务 容易迷失,绕路 有清单兜底,不易漏步
适用 探索型任务(不确定怎么做) 常规型任务(路径基本可知)

图 4:ReAct vs Plan-and-Execute

15.3.3 选型决策:一句话

知道怎么做 → Plan-and-Execute(省成本、防漏步);不知道怎么做、需要边做边探 → ReAct(灵活探索)。

工程上的常见折中是混合式:先用 Plan-and-Execute 生成粗计划,执行到某一步发现"这一步到底怎么做不确定"时,在该步内降级为 ReAct 探索("计划外带探索")。这是目前生产环境里性价比最高的形态。

15.4 完整示例:Plan-and-Execute 报告生成器

python 复制代码
import json
from openai import OpenAI

client = OpenAI(base_url="https://api.deepseek.com", api_key="<你的Key>")

def generate_plan(goal):
    resp = client.chat.completions.create(
        model="deepseek-chat",
        messages=[{"role": "user", "content": f"""把目标分解为执行计划,只输出 JSON:
{{"objective": "...", "steps": [{{"id": 1, "action": "...",
  "depends_on": [], "verify": "..."}}], "risks": []}}
目标:{goal}"""}],
        temperature=0.2, response_format={"type": "json_object"},
    )
    try:
        return json.loads(resp.choices[0].message.content)
    except json.JSONDecodeError:
        return {"objective": goal, "steps": [], "risks": ["规划生成失败,需人工介入"]}

def execute_step(step, context):
    """执行单个计划步骤(真实场景里调工具/子链)"""
    resp = client.chat.completions.create(
        model="deepseek-chat",
        messages=[{"role": "user", "content":
            f"执行任务步骤:{step['action']}\n上下文:{json.dumps(context, ensure_ascii=False)}"}],
        temperature=0.3,
    )
    return resp.choices[0].message.content

def replan(goal, plan, done_steps, issues):
    """保留已完成步骤的结果,重排剩余步骤。
    done_steps 包含原步骤结构和执行结果,便于重规划时参考。"""
    resp = client.chat.completions.create(
        model="deepseek-chat",
        messages=[{"role": "user", "content": f"""原计划执行出现问题,请重规划剩余步骤。
目标:{goal}
已完成步骤及其结果:{json.dumps(done_steps, ensure_ascii=False)}
出现的问题:{json.dumps(issues, ensure_ascii=False)}
只输出 JSON:{{"remaining_steps": [{{"id": 1, "action": "...",
  "depends_on": [], "verify": "..."}}], "risks": []}}"""}],
        temperature=0.2, response_format={"type": "json_object"},
    )
    try:
        result = json.loads(resp.choices[0].message.content)
    except json.JSONDecodeError:
        result = {"remaining_steps": [], "risks": ["重规划失败,需人工介入"]}
    # 保留已完成步骤 + 追加重规划后的剩余步骤
    result["completed"] = done_steps
    return result

def run(goal, max_plan_rounds=3):
    plan = generate_plan(goal)
    done, issues = [], []
    for round in range(max_plan_rounds):
        context = {"done": done}
        try:
            for step in plan.get("remaining_steps", plan["steps"]):
                result = execute_step(step, context)
                done.append({"id": step.get("id"), "step": step["action"],
                             "result": result, "verify": step.get("verify", "")})
            return done              # 全步成功
        except Exception as e:
            issues.append(str(e))
            plan = replan(goal, plan, done, issues)   # 重规划剩余
    return done

report = run("生成一份 2026 Q3 电商行业分析报告")

工程要点

  1. 计划用 JSON 结构化输出,depends_on 为并行留口子。
  2. 执行异常 → 带着已完成结果重规划(不推倒重来)。
  3. 重规划次数设上限(max_plan_rounds),防死循环(呼应第 13 章停止条件)。
  4. 生产加固 :每个 LLM 调用应加 timeout 参数和重试逻辑(如 tenacity 库),API 异常时降级为人工介入而非崩溃;并行执行步骤时用信号量限流(第 12 章);用户输入的 goal 应做长度限制和注入检测(第 22 章)。

15.5 主流框架对照与变体

15.5.1 框架对照

实现方式 特点 适用
自研(本章主线) 计划/执行/重规划三函数,完全可控 教学、定制化
LangChain PlanAndExecuteAgentExecutor 框架内置规划器+执行器 快速搭建
LangGraph 规划节点 计划节点+条件边重规划 复杂图结构
BabyAGI / AutoGPT 式任务队列 动态生成任务队列,不断追加 探索型自动化

15.5.2 变体一:层级规划(Hierarchical Planning)

高层规划(大目标 → 阶段)与低层规划(阶段 → 具体步骤)分离。高层规划器不关心细节,低层规划器在阶段执行时再细化。适合超大型任务,代价是系统复杂度上升(呼应第 16 章多智能体:层级规划往往是多 Agent 协作的基础)。

15.5.3 变体二:规划 + 并行(Plan-and-Parallelize)

利用计划的 depends_on:把无依赖的步骤并行执行(呼应第 12 章)。计划阶段就标注哪些步骤可并行,执行阶段据此 Fan-out,显著缩短总时长。

15.5.4 变体三:反思型规划(Reflective Planning)

每执行完一步,用反思(第 13 章)评估"这一步的产出质量"和"计划是否仍合理",把反思结论喂给重规划。规划 + 反思 + 重规划构成完整闭环,是复杂 Agent 系统的标配。

🛠 解决方案:计划过期失效的动态重规划

常见问题

  1. "计划生成得很好,但执行时环境全变了":计划过期是常态不是异常。对策:Plan-and-Execute 的"重规划"机制(15.2.2),带已完成结果重排剩余步骤。
  2. "ReAct 走着走着迷路了":思考步累积导致上下文膨胀、目标漂移。对策:换 Plan-and-Execute(路径可预知时);或给 ReAct 加"目标重申"(每 N 步回顾原始目标)。
  3. "计划步骤漏了关键环节" :计划质量差。对策:计划提示词加 verify/risks 字段强制自查;对高风险任务用"规划 + 反思"双模型(一个出计划、一个审计划,呼应第 13 章互评)。
  4. "重规划反复发生,成本爆炸":重规划也要设上限(3 次),超过直接转人工(呼应第 24 章熔断)。频繁重规划本身说明任务不适合规划模式,考虑 ReAct 或降级。
  5. "计划太细,一步失效全盘乱":粒度控制问题。对策:环境动态 → 计划粗粒度(15.1.3),把细化留给执行时。

解决方案速查表

现象 根因 解决方案
计划过期 环境变化 重规划(保留已完成)
ReAct 迷路 上下文膨胀 目标重申 / 换 Plan-Execute
漏关键步骤 计划质量差 verify/risks 字段 + 双模型审计划
反复重规划 任务不适合规划 上限 3 次 + 转人工
计划僵化 粒度太细 粗粒度 + 执行时细化

实战提示

  1. 计划的产出要可校验 :每步带 verify,没有校验的计划等于没有计划。
  2. 重规划是核心能力:plan-and-execute 的价值不在"计划准",而在"计划错了能快速纠偏"。
  3. 先粗后细:第一次生成粗计划,执行中逐步细化,别指望一次规划到底。
  4. 选型别纠结:路径可知用 Plan-and-Execute,路径未知用 ReAct,两者混合最高性价比。
相关推荐
workflower1 小时前
TF-IDF 的基本思想
人工智能·机器学习·机器人·云计算·无人机
数据狐(Datafox)1 小时前
mercadolibre.item_get 工程实战:美客多商品详情API技术解析与落地应用
java·人工智能·mysql·json
打破砂锅问到底0071 小时前
2 小时从零炼一个 64M 小模型:MiniMind 源码精读与显存踩坑
人工智能
IT_陈寒1 小时前
Redis持久化配置漏了这一步,线上数据丢了5小时
前端·人工智能·后端
大力财经1 小时前
抖音生活服务品牌零售行业峰会在杭州举办,探索线下生意新增量
大数据·人工智能·区块链
xsd202411181 小时前
检测视觉大模型全景解析:从Grounding DINO到Molmo,AI如何“指哪打哪“
人工智能
咖啡星人k1 小时前
2026 智能体安全进阶:把注入和越权写进SPEC,MonkeyCode 云端跑通
人工智能·安全·机器学习
sel_91 小时前
深度学习激活函数详解:从 Sigmoid、Tanh、ReLU 到 GELU、SiLU、Mish,一文掌握所有常用激活函数
人工智能·深度学习