Chapter 01
基础:规划是什么 & 那条权衡轴
起点页给出了概念地图和一条贯穿全程的「承诺↔适应」轴。这一章把轴本身讲透,并定义后面四章所有范式都要复用的词汇:分解、承诺、适应、三大家族、ReAct 基线。
本章你将建立的 schema
- 规划 = 在「自回归生成」之上加的一层控制流——决定何时停下调工具、把什么喂回、何时判完成
- 「承诺↔适应」是一条轴,不是一组对立选项;每种范式都是轴上的落点,各自付出特定代价
- 任务分解是所有规划的底层操作;分解粒度是一个会反噬的隐藏旋钮
- 三大家族(分解 / 多计划选择 / 反思)各自回答一个不同的问题
- ReAct 是最小、最适应的循环,也是后面所有"更省更并行"范式的对照基线
1.1规划是什么,为什么 agent 需要它
规划 = agent 在「目标」和「一串工具调用」之间架起的桥:决定做哪些步、什么顺序、出错怎么办。
单次 LLM 调用加单个工具调用,只能解决"一跳"问题。真实任务——订差旅、多跳问答、定位并修一个 bug——需要多步,步骤之间有依赖,执行途中还会有步骤失败。没有规划这一层,工程师就得为每个任务手写一套 if/else 状态机,把工具调用按顺序和分支串起来。规划层把这套控制流交给模型自己生成。
底层机制(比文档深一层):一个 LLM 本身是无状态的 next-token 预测器——给定输入 token,吐出下一个 token,仅此而已。它没有"循环"、没有"调用工具"、没有"判断完成"的内建能力。规划本质是在这个生成过程之外,套一层控制流:什么时候打断生成去执行一个工具、把工具结果以什么形式拼回上下文、什么条件下判定任务结束。不同的规划范式,就是不同形状的控制流——这句话是理解后面所有内容的钥匙。
规划像项目经理(PM)与一线执行的关系:PM 决定拆几个任务、谁先谁后、卡住了要不要重排。类比失效在记忆上——真人 PM 有持久的世界模型和记忆,而 LLM 规划器每一步能"记得"的,只有这一次显式塞进 prompt 的那些 token;上下文之外的一切,它都不知道。
场景走查:一个需要规划的任务长什么样
目标:「找出上周 GitHub 上 star 增长最快的 Python 项目,并总结它的 README」。把它摊开看:
如果目标改成「分别查北京、上海、广州三个城市明天的天气」,它和上面那个任务在"步骤依赖"上有什么本质区别?这个区别会指向轴的哪一端?
展开答案(先停 10 秒再点)
三个城市的天气查询彼此独立——查北京不需要先知道上海的结果。而上面的 README 任务是顺序依赖的。独立子任务可以并行、可以一次性把计划列全,指向轴的"提前承诺"那一端(省钱、可并行);顺序依赖且每步结果会影响下一步走向的任务,指向"临场适应"那一端。
这正是 §1.2 那条轴要回答的核心问题——而它也预告了第 2 章里 LLMCompiler(擅长并行独立任务)和 ReAct(擅长顺序适应)的分野。
1.2「承诺 ↔ 适应」权衡轴(本教程的核心)
一条轴:左端「提前把整个计划定死」,右端「每做一步再决定下一步」。七种范式都是这条轴上的落点。
七种范式表面上五花八门、名字各异,但它们都在回答同一个问题:在看到工具的真实结果之前,你愿意对计划承诺多少?把这个问题画成一条轴,七种范式立刻各就各位——你不再需要孤立地背七套机制,而是记住一条轴加每个范式的落点。
底层机制(比文档深一层):
承诺早(在信息不足时就把计划定死)买到两样东西:① 可并行——既然步骤间的依赖关系已经在计划里写明,没有依赖的步骤就能同时发;② 省 token——不需要每一步都把已有的观察结果重新喂回模型去"想下一步"。付出的代价是:计划建立在"假设的世界状态"上,一旦某一步的真实结果出乎意料,整个计划无法纠偏。
适应晚(每做一步、看到真实结果,再决定下一步)买到纠错能力:每个决策都基于最新信息。代价是两条:每一步都要把累积的全部上下文重新编码进模型(token 与延迟随轨迹长度线性增长),而且天然串行——下一步要等这一步的观察出来才能想。
"适应晚"的 token 成本,不是因为调用次数多,而是因为每一步都把之前所有的 Thought/Action/Observation 重新喂回去推理。这个机制是第 2 章 ReWOO 为什么能省 5 倍 token 的全部秘密——它不是少调了几次,而是不再重复编码 observation。现在记住这句话,到 §2.3 你会"啊哈"一下。
1.3任务分解:所有规划的底层操作
任务分解 = 把一个大目标切成若干可执行的子任务。无论哪个范式,第一步都是它。
模型不能直接"执行"一个抽象目标,只能执行具体的工具调用。分解就是从"帮我订差旅"到"查航班 / 比价 / 下单 / 订酒店"的那一步翻译。它是规划的最底层动作,七种范式的差别只在于怎么分、什么时候分,而不在于要不要分。
底层机制(比文档深一层):分解发生的时机本身就落在那条轴上。一次性全分解(Plan-and-Execute、ReWOO 的 planner 一口气列出全部子任务)是"提前承诺";增量分解(ReAct 每步只决定下一个子任务)是"临场适应"。还有一个容易被忽视的旋钮——分解粒度:拧太粗,子任务仍然太难、模型一步做不完;拧太细,步骤数爆炸,延迟和 token 成本飙升,这就是第 2 章会专门讲的"过度分解"失败模式。粒度没有万能值,它本身就是个要权衡的设计决策。
分解像庖丁解牛——沿着关节下刀,省力。类比失效在:庖丁知道牛的关节在哪,而 LLM 不一定找得到任务的"关节",它有时在错误的地方下刀(切出根本不存在的子任务,即"工具幻觉"),或者把一刀能解决的硬切成十刀(过度分解)。分解的质量本身就是规划质量的一部分。
1.4三大家族:每个家族回答一个不同的问题
把现代 LLM 规划范式归类,最清晰的一套来自 Huang 等人 2024 年的规划综述。它把方法分成五类,本教程聚焦其中最主流的三类(另两类——外部模块辅助、记忆增强——分别在第 4 章桥接经典规划时提到、以及并入 Reflexion 讲)。三大家族的根本区别,是它们各自回答一个不同的问题:
| 家族 | 它回答的问题 | 代表范式 | 本教程位置 |
|---|---|---|---|
| ① 任务分解 | "怎么把目标拆成步骤、按什么顺序执行?" | ReAct · Plan-and-Execute · ReWOO · LLMCompiler | 第 2 章(核心) |
| ② 多计划选择 | "生成多条候选路径,怎么评估并选出最好的一条?" | Tree of Thoughts · LATS | 第 3 章 |
| ③ 反思与提炼 | "上一次失败了,怎么把教训用上、让下一次更好?" | Reflexion | 第 3 章 |
这三个问题正交:一个真实系统可以同时用到——比如先分解(①),对其中难的一步做多路径搜索(②),整体失败后反思重试(③)。第 3 章末尾的 LATS 就是把三者缝在一起的范式。分类不是为了贴标签,而是为了在选型时知道"此刻缺的是哪种能力"。
"客服 agent 调外部 API 时经常报错,要能当场换个方法重试"——这个需求最直接命中哪个家族要回答的问题?
展开答案(先停 10 秒)
"当场换方法"指向临场适应,是任务分解家族里 ReAct 那一端的强项(每步看真实结果再决定)。注意它不是反思家族——反思(Reflexion)是"整次任务失败后,把教训写进记忆、下一次整体重试",是跨尝试的改进,不是同一次执行内的当场纠错。两者都"从失败中学",但时间尺度不同:一个在 step 之间,一个在 episode 之间。这个区分第 3 章会再钉一次。
1.5ReAct:最小的、最适应的基线
ReAct = 让模型在「推理(Thought)」和「行动(Action)」之间交替,每次行动后把真实「观察(Observation)」喂回,再想下一步。
ReAct(Yao 等人 2022)是最小的、最靠"适应"端的规划循环,也是后面所有"更省钱 / 更并行"范式诞生的对照基线——ReWOO、LLMCompiler 的论文都是拿 ReAct 当靶子来证明自己的改进。先把基线吃透,后面的对比才有锚点。
底层机制(比文档深一层):ReAct 把模型的解码循环强制成重复的 Thought → Action → Observation 三元组。关键在 Action 这一步:模型生成一个工具调用后,生成在此暂停,外部代码真正执行这个工具,把真实结果作为 Observation 文本拼回上下文,然后解码恢复,模型基于这个新信息想下一步。
这和纯思维链(CoT,一段不被打断的内心独白)的本质区别是:ReAct 的 token 流被外部真实字符串反复打断并重新接地。CoT 一旦在第二步推错,错误会顺着独白滚下去;ReAct 因为每步都灌入真实观察,能纠正事实漂移。这就是 ReAct 论文的核心论点——CoT "受困于幻觉,因为它不与外部世界接地"。
场景走查:一次两跳问答的 ReAct 轨迹
问题:「导演了《盗梦空间》的人,下一部上映的电影是什么?」单跳查不到——要先查导演,再用导演查新片。ReAct 的轨迹(示意):
Thought: 要先找出《盗梦空间》的导演是谁
Action: search("盗梦空间 导演")
Observation: 克里斯托弗·诺兰 ← 外部真实结果,喂回
Thought: 现在查诺兰下一部上映的电影
Action: search("诺兰 2026 上映 新片")
Observation: 片名《XXX》,2026-07 上映 ← 又一次接地
Thought: 已拿到答案,可以收尾
Action: finish("《XXX》")
- 第 2 行
Action: search(...):体现"行动"——生成在这里暂停,外部真去搜索。这就是定义里"行动"的含义。 - 第 3 行
Observation:真实结果接地,纠正了模型未接地时的瞎猜。这是 ReAct 区别于 CoT 的关键。 - 第 5 行起:第二跳的 Thought用上了第一跳的 Observation(诺兰)——这就是"每步带着全部历史重新推理"的具体样子。轨迹越长,重新喂回的历史越多。
ReAct 单独使用,未必比"纯 CoT + 自洽采样(CoT-SC)"更强。原论文的头条数字,很多来自 ReAct 与 CoT-SC 互相回退切换的组合策略。而且"强制每步产出一个合法 action"是一种结构约束,反而降低了推理的灵活性——论文里 23% 的错误是"无信息搜索"把 agent 带进了重复的思考/行动死循环。"最适应"不等于"最强",它只是轴右端那个最朴素的落点。
§本章 self-check
先合上教程,把答案写在纸上或编辑器里。写完再点开对照——直接点开等于把这一节再读一遍。
- 用一句话说出「承诺↔适应」轴左右两端各自买到什么、各自付出什么代价。
- ReAct "每一步把累积的全部上下文重新喂回推理"——这件事会让什么量随轨迹长度增长?
- 任务分解的"粒度"旋钮拧得太细,会触发哪个失败模式?拧太粗呢?
- 三大家族里,哪个家族的核心动作是"生成多条候选路径再用评估函数选"?它和"反思"家族在"从失败中学"的时间尺度上有什么不同?
答案(先做完再展开)
- 左端"提前承诺":买到可并行 + 省 token,代价是计划建立在假设的世界状态上、意外无法纠偏。右端"临场适应":买到每步用最新信息纠错,代价是串行 + token/延迟随轨迹线性增长。
- token 消耗与延迟随轨迹线性(偏二次)增长——因为每一步都把之前所有 Thought/Action/Observation 重新编码进 prompt。这正是 ReWOO 的攻击点。
- 太细 → 过度分解:步骤数爆炸,延迟与成本飙升。太粗 → 子任务仍太难,模型一步做不完。粒度本身是个要权衡的设计旋钮,没有万能值。
- "多计划选择"家族(ToT / LATS)。区别:多计划选择和 ReAct 的当场纠错都在一次执行内(step 之间);反思(Reflexion)是跨尝试(episode 之间)——整次失败后把教训写进记忆,下一次整体重试。
把一个任务钉到轴上
任务:「给定一个 GitHub 仓库 URL,自动跑通它的测试套件并报告失败的用例」。在纸上画出图 1.2 的轴,标出这个任务的理想落点,并写下:如果错用了轴的另一端(比如本该适应却提前把计划定死,或反之),具体会在哪一步崩?
提示(卡住再展开)
问自己:跑测试这件事,步骤之间的依赖在执行前能不能完全预知?(克隆→装依赖→跑测试 的大框架可预知,但"装依赖"这步极易因环境千奇百怪而失败,需要看到真实报错再决定怎么修。)这意味着它不是纯粹的一端,而是"大框架可提前承诺、易错步骤需临场适应"——这恰好是第 2 章 Plan-and-Execute"定计划 + 失败时重规划"的折中位。