长程规划提示:让大模型分步完成复杂任务

当你让模型「写一份市场分析报告」「把一个旧项目迁移到新框架」「规划一次长途旅行的完整行程」时,常会遇到一种尴尬:模型开头说得头头是道,越往后越漏步骤、越跑越偏,最后交出的东西要么缺关键部分,要么自相矛盾。这类任务的共同点是步骤多、路径长、对最终结果要求高,单靠一条「请帮我完成 X」的提示很难稳定拿下。本文讲清为什么复杂任务需要显式规划,梳理几种主流规划范式,给出可落地的提示结构,并附一个用 Python 实现的「先规划再执行」轻量编排骨架。

为什么复杂任务需要显式规划

把一个长程任务直接丢给模型,问题通常出在三个地方:

  • 上下文窗口的物理限制:任务越长,需要同时记住的前提、约束、中间结论就越多。即便模型上下文窗口足够大,随着内容堆积,靠后的指令容易被「稀释」,模型对早期约束的遵从度会下降。显式规划把任务切成小段,每段只关心当下需要的上下文,等于给模型减负。
  • 误差累积(错误雪球):长链路里前一步的小错会顺着后续步骤放大。一条提示一口气算十步,第 3 步算错,第 4 到第 10 步全建立在错误之上。把任务拆成可验证的子步骤后,错误被限制在单个节点,能在「滚雪球」之前被发现和修正。
  • 目标漂移(goal drift):没有显式锚点,模型在长生成中容易偏离最初目标,比如把「写技术周报」慢慢写成「行业泛泛而谈」。规划阶段写下的目标清单与检查点,相当于一路上的路标,让每一步都对着最初意图做对齐。

一句话概括:显式规划把「一次押注全部正确」变成「多次小步、可验证、可纠正」,从根本上降低了长程任务的整体失败率。

主流规划范式概述

研究者已经提出多种把「规划」注入提示的方法,下面三个最具代表性,均已通过论文原文核验。

Plan-and-Solve(计划再求解)【已核验】

论文 Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models(Wang 等,arXiv:2305.04091,ACL 2023)。它针对 Zero-shot-CoT 的「漏步骤」问题,把推理拆成两步:先写一个计划把整体任务划分为若干子任务,再按计划逐个完成子任务;其增强版 PS+ 进一步加入更细致的执行指令。核心思想与本文的「先规划再执行」骨架直接对应。

Tree of Thoughts(思维树,ToT)【已核验】

论文 Tree of Thoughts: Deliberate Problem Solving with Large Language Models(Yao 等,arXiv:2305.10601,NeurIPS 2023)。ToT 把 Chain-of-Thought 推广为在多个「思维」分支间探索的框架:模型可生成多条候选推理路径,自我评估每条的优劣,必要时前瞻回溯做全局选择。实验里 Game of 24 任务上,GPT-4 用普通 CoT 仅 4% 成功率,ToT 达到 74%。它解决的是「路径不确定、需要试错搜索」的长程任务。

ReAct(推理加行动,含反思)【已核验】

论文 ReAct: Synergizing Reasoning and Acting in Language Models(Yao 等,arXiv:2210.03629,ICLR 2023)。ReAct 让模型以交错方式同时生成推理轨迹行动(如调用外部工具、查知识库),推理帮助模型跟踪并更新行动计划、处理异常,行动让模型从外部获取额外信息。它天然携带「反思」能力:当行动结果不对,模型在推理轨迹里自我纠正。这正好对应本文提示结构中的「自我修正」环节。

三者定位不同,可用一张表区分:

范式核心动作适合场景是否需外部工具
Plan-and-Solve先出计划,再按步执行步骤清晰、路径确定的任务
Tree of Thoughts多分支探索、评估、回溯需要搜索试错的任务
ReAct推理与行动交错、可调用工具需查外部信息或环境的任务

补充:论文 Reflexion: Language Agents with Verbal Reinforcement Learning(Shinn 等,arXiv:2303.11366)提出用语言化的自我反思做「 verbal reinforcement」,可作为 ReAct 反思机制的延伸阅读,本文暂不逐项核验,标记为【待核实】。

提示结构:目标拆解、检查点、回滚与自我修正

无论选哪种范式,落到提示工程上,一套稳健的长程规划提示通常包含四个构件。

1. 目标拆解

在动手前先让模型产出结构化计划。告诉它任务是什么、约束有哪些、希望拆成几个有序子步骤,并要求输出机器可解析的格式(如 JSON 的 steps 列表)。拆解越具体,后续执行越稳。

你是任务规划助手。请把下面的目标拆成 3 到 6 个有序子步骤。
目标:{goal}
约束:{constraints}
只输出 JSON,字段为 steps,不要任何解释。

2. 检查点(checkpoint)

每个子步骤执行完,不要直接进下一步,而是先过一道「检查点」:用一个轻量提示判断本步产出是否达标(格式对不对、是否回答了本步问题、有无明显事实错误)。检查点把误差累积挡在节点内。

步骤:{step}
本步产出:{output}
请只回答 OK 或 FAIL,并在 FAIL 时说明原因。
判断标准:产出须直接回应本步目标,且不包含无来源的关键断言。

3. 回滚(rollback)

当某步连续未通过检查点、或在执行中触发不可恢复的异常时,应回滚到上一个已知良好的状态,而不是带着错误继续。实践中可以把「已验证的上下文」单独保存,失败时丢弃当前步、保留前序成果,并记录该分支被放弃的原因,避免无谓重试。

4. 自我修正(self-correction)

未通过检查点时,不要立刻放弃。把检查点给出的失败原因作为反馈,让模型基于同样的计划重新执行该步。这就是 ReAct 式反思在提示层的落地:错误原因被显式送回,模型在第二轮往往能补上遗漏或修正偏差。可设置重试上限(如 2 次),超过上限再回滚。

把这四件套串起来,提示就从「一次押注」变成「规划、执行、验证、修正、必要时回滚」的闭环。

实战:用 Python 实现「先规划再执行」编排骨架

下面用一个不依赖重型框架的轻量骨架,演示如何把上面四件套工程化。它使用 OpenAI 兼容协议客户端,base_url 可指向国内服务(如 DeepSeek、通义千问),从而兼容大多数 OpenAI 风格接口。

import json

import openai

    # 兼容 OpenAI 协议的客户端,base_url 可指向国内服务(如 DeepSeek、通义千问)
client = openai.OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.deepseek.com/v1",
)


def call_model(messages, temperature=0.2):
    # 统一封装一次对话补全调用,返回文本内容
    resp = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages,
        temperature=temperature,
    )
    return resp.choices[0].message.content


def make_plan(goal, constraints):
    # 构件1:目标拆解,让模型产出有序子步骤的 JSON
    system = "你是任务规划助手,只输出 JSON,不要解释。"
    user = (
        f"把目标拆成 3 到 6 个有序子步骤,字段为 steps。"
        f"目标:{goal}\n约束:{constraints}"
    )
    text = call_model([
        {"role": "system", "content": system},
        {"role": "user", "content": user},
    ])
    return json.loads(text)


def execute_step(step, context):
    # 执行单个子步骤,把已验证的上下文作为背景传入
    user = f"当前步骤:{step}\n已有上下文:{context}\n请给出本步骤产出。"
    return call_model([{"role": "user", "content": user}])


def evaluate_step(step, output):
    # 构件2:检查点,判断本步是否达标
    user = (
        f"步骤:{step}\n产出:{output}\n"
        f"只回答 OK 或 FAIL,并在 FAIL 时说明原因。"
    )
    verdict = call_model([{"role": "user", "content": user}])
    return verdict.strip().startswith("OK")


def run(goal, constraints="", max_retry=2):
    # 主循环:规划、执行、检查点、自我修正、回滚
    plan = make_plan(goal, constraints)
    context = ""
    for step in plan["steps"]:
        attempt = 0
        while attempt <= max_retry:
            # 构件4:未通过检查点时,带反馈自我修正
            output = execute_step(step, context)
            if evaluate_step(step, output):
                context += f"\n[{step}] {output}"
                break
            attempt += 1
        else:
            # 构件3:超过重试上限触发回滚,保留前序成果并标记
            context += f"\n[{step}] (回滚:未通过检查点)"
    return context


if __name__ == "__main__":
    result = run("为用户生成一份本周工作周报并提炼摘要")
    print(result)

骨架的关键点:计划与执行分离,上下文只累积「已通过检查点」的部分,未通过则进入带反馈的重试,重试耗尽便回滚。你可以把 evaluate_step 换成更强的校验(如格式断言、单元测试、外部 API 比对),把 make_plan 换成 ToT 式的多分支生成,逐步逼近论文里的能力。

小结

  • 长程复杂任务用单条提示容易因上下文限制、误差累积、目标漂移而翻车,显式规划是必要的。
  • Plan-and-Solve(先计划再执行)、Tree of Thoughts(多分支探索回溯)、ReAct(推理行动交错含反思)是三种主流范式,分别适合确定路径、需搜索、需外部工具的任务。
  • 落到提示工程,稳健结构包含四件套:目标拆解、检查点、回滚、自我修正。
  • 用 Python 编排时,让计划与执行分离、上下文只保留已验证成果,能在不引入重型框架的前提下获得稳定可控的长程能力。

参考与延伸阅读

  1. Wang L. 等. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models(arXiv:2305.04091,ACL 2023)【已核验】. https://arxiv.org/abs/2305.04091
  2. Yao S. 等. Tree of Thoughts: Deliberate Problem Solving with Large Language Models(arXiv:2305.10601,NeurIPS 2023)【已核验】. https://arxiv.org/abs/2305.10601
  3. Yao S. 等. ReAct: Synergizing Reasoning and Acting in Language Models(arXiv:2210.03629,ICLR 2023)【已核验】. https://arxiv.org/abs/2210.03629
  4. Shinn T. 等. Reflexion: Language Agents with Verbal Reinforcement Learning(arXiv:2303.11366)【待核实,作为 ReAct 反思机制的延伸】. https://arxiv.org/abs/2303.11366
  5. OpenAI. Prompt engineering(拆分复杂任务等战术). https://platform.openai.com/docs/guides/prompt-engineering
  6. Anthropic. Prompt engineering overview(含 prompt chaining 与 thinking 索引). https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview
本文累计阅读