对应 Maps to:CMU 17-630 Prompt Engineering(Prof. Travis Breaux),第 3 周 · Chain-of-Thought Prompting(这一周作业 1 截止)。原课 Schedule 对这一讲的说明(意译):零样本思维链;和其他提示策略的比较(self-ask、plan-and-solve、step-back);以及用 self-consistency 减少思维链里的随机错误。 依据说明:原课的 slides 和阅读清单不公开。Schedule 点名的内容——零样本思维链、self-ask、plan-and-solve、step-back、self-consistency——分别在 §3.3、§2.4、§3.4、§3.5 和 §4.3 展开;思维链的忠实性(§5)和推理模型(§7)是讲义补充的。材料来自 Wei et al.(2022)、Kojima et al.(2022)、Press et al.(2023)、Wang et al.(2023,Plan-and-Solve)、Zheng et al.(2024,Step-Back)、Wang et al.(2023,Self-Consistency)、Nye et al.(2021)、Lanham et al.(2023)、Turpin et al.(2023)、Sprague et al.(2024)等论文;引用时按原文的说法转述结论,具体数字以原文为准。全部实验是本讲义自己设计的,不代表课堂上讲了什么。 配套代码 Code:
code/lecture04/(PyTorch CPU;2 个模块 + 6 个脚本;不需要 API key;在第 1 讲的迷你 GPT 上用第 3 讲的方法训练 4 个模型,每个约 10 秒,缓存在checkpoints/;每个脚本都在 25 秒以内) 预计阅读时间:4 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
学完这一讲,你应该能够:
- 解释思维链(chain of thought,CoT)为什么能提高多步问题的准确率:它把”一次前向计算里完成的组合”摊开成”写下来、再读回来”的几步。
- 用组合性差距描述”每一步都会、合起来就不会”的现象,并知道两种缩小它的办法:让模型自己写中间步骤,或由程序来分解(Self-Ask)。
- 比较少样本思维链、零样本思维链(“Let’s think step by step”)、Plan-and-Solve、Step-Back、Self-Ask 各自针对哪一类错误、各要多付出什么成本。
- 理解 self-consistency 的原理和边界:它修正随机错误,修不了系统性错误;它要求”正确答案比任何一个错误答案都更常见”,而不是 p > 0.5。
- 知道思维链在什么情况下没用甚至有害(小模型、一步就能答的问题、不知道的事实),以及为什么”写成什么格式”很重要。
- 说清楚忠实性问题:模型写出的推理,未必是它真正用来得出答案的过程;会用干预实验检验它。
- 理解推理模型(o1、DeepSeek-R1 这一类)怎样把思维链训练进了模型,以及这对写提示意味着什么。
0.2 先修与本讲范围 Prerequisites & scope
| 默认你已经会 Assumed | 本讲只给直觉,后面再展开 Previewed only |
|---|---|
| 第 1 讲:反转诅咒(§8.5)、温度采样(§8.7)、归纳头(§6.6) | 任务分解的系统方法:least-to-most、successive prompting(第 9 讲) |
| 第 2 讲:迷你 GPT 不会”照抄”(§8.6);上下文学习对格式敏感 | 自我验证与验证链(第 10 讲);用搜索做规划(第 13 讲) |
| 第 3 讲:指令微调的方法与”预训练学知识、微调学怎样用”;本讲直接复用它的代码 | 推理模型的训练细节(强化学习)只讲直觉 |
| 前置讲 P3:多次采样、配对比较;P2:输出 token 的费用 |
0.3 本讲地图 Map
§1 从一个两跳问题说起:为什么"一次说出答案"很难
§2 组合性差距:每一跳都会,两跳合起来就不会;由程序来分解(Self-Ask) ← 代码 01
§3 思维链提示:少样本 CoT、零样本 CoT、Plan-and-Solve、Step-Back ← 代码 02、05
§4 思维链为什么有用、什么时候有用:摊开计算、写成什么格式、规模;self-consistency ← 代码 02、04、05
§5 思维链忠实吗?干预实验 ← 代码 03
§6 成本与"什么时候不用思维链" ← 代码 05(演示 4)
§7 推理模型:把思维链训练进模型 ← 代码 06(可选)
§8 小结 §9 常见误区 §10 练习 §11 延伸阅读 §12 下一讲预告
0.4 记号与术语 Notation & terms
| 术语 | 本讲义里的意思 |
|---|---|
| 思维链(chain of thought,CoT) | 模型在给出最终答案之前,先写出的一系列中间推理步骤 |
| 草稿纸(scratchpad) | Nye et al.(2021)的说法:让模型把中间计算结果写在一个”草稿区”里。本讲的 scratch 格式就是最简化的草稿纸:只写中间结果 |
| 两跳问题(two-hop question) | 需要串起两个事实才能回答的问题,例如”讲 driltese 语的那个国家,首都是哪里” |
| 桥(bridge) | 两跳问题里那个中间实体(这里是国家);“用什么指代它”叫桥的类型 |
| 组合性差距(compositionality gap) | 两个子问题都答对、合起来的问题却答错的比例(Press et al. 2023) |
| self-consistency | 采样多条思维链,对最终答案做多数投票(Wang et al. 2023) |
| 忠实性(faithfulness) | 写出的推理是否真的是得出答案的原因 |
| 系统性错误 / 随机错误 | 每次都犯同一个错 / 每次错得不一样 |
0.5 本讲的实验装置 · The setup
真实的迷你模型。还是第 1 讲的世界和 base 迷你 GPT,用第 3 讲的指令微调方法(扩展词表、对话模板、混入预训练语料)训练。问题是两跳的:
what is the capital of the country where people speak driltese ? ← 先由语言找到国家(volel),再问它的首都(grorken)
“桥”有三种:用首都指代国家(the country whose capital is K)、用语言指代(the country where people speak L)、用领导人指代(the country led by P)。前两种的第一跳在预训练百科里有现成的说法(“K is the capital of X”、“L is spoken in X”);领导人那一种是反转诅咒(第 1 讲 §8.5)——百科里只有”X is led by P”,P 永远在 X 后面,模型几乎不可能由领导人反查国家。它在本讲扮演”模型就是不知道”的那类题。目标有 5 种属性(首都、语言、出口、领导人、方位),桥 × 目标共 12 种组合;训练时只用其中 6 种,另外 6 种用来测组合泛化。
和第 3 讲一样,训练数据只用 12 个国家,测试用 8 个只在预训练百科里出现过的国家。
两跳问题的回答有三种格式:
| 格式 | 回答 |
|---|---|
| direct(直接回答) | grorken |
| sentence(完整句子的思维链) | driltese is spoken in volel . the capital of volel is grorken . answer grorken |
| scratch(只写中间结果的草稿纸) | volel . answer grorken |
模拟推理者(reasoner_sim.py)。迷你 GPT 做不了多步算术,也没法比较”零样本思维链""先计划再求解”这些提示技巧。模拟器用一组显式的旋钮模拟一个模型在 k 步算术题(“Start with 7. Add 5. Multiply by 3. … What is the result?”)上的行为:每一步算错的概率、“心算”能完成的步数、小模型的推理”流畅但不合逻辑”的额外错误、漏步、系统性误解、几条可靠性不同的解题路径。它能把论证变具体,不能说明真实模型的数字。
1. 从一个两跳问题说起 · Why one-shot answers are hard
“讲 driltese 语的那个国家,首都是哪里?“人回答这个问题时,脑子里会有一个中间结果:“那个国家是 volel”。然后才是”volel 的首都是 grorken”。
一个语言模型一次说出答案时,没有地方放这个中间结果。它必须在一次前向计算里——在产生答案这个 token 之前的那几十层计算里——完成”由 driltese 找到 volel、再由 volel 找到 grorken”的全部工作。第 1 讲的 Transformer 层数是固定的,每一层能做的事情有限;问题需要的步骤越多,一次前向计算越可能装不下。
思维链的想法非常朴素:让模型把中间结果写出来。写出来的东西成了上下文的一部分,下一步计算可以直接”读”它。于是一个需要 k 步的问题,变成了 k 次”读前文、写一步”——每一步都只需要完成一个简单的操作。理论工作也支持这个直觉:固定深度的 Transformer 一次前向能表达的计算有限,允许它生成中间步骤之后,能表达的计算类型大大增加(Feng et al. 2023;Merrill & Sabharwal 2024)。
这一讲依次回答四个问题:
- 这个困难是真的吗?“每一步都会、合起来就不会”有多严重?(§2)
- 有哪些办法让模型写出中间步骤?各有什么区别?(§3)
- 它为什么有用、什么时候有用、写成什么样?多想几遍(self-consistency)又是怎么回事?(§4)
- 模型写出的推理,是它真正的推理吗?代价是什么?(§5–§7)
2. 组合性差距 · The compositionality gap
2.1 每一跳都会
先训练一个只学过一跳问题的模型(第 3 讲的 7 种任务 + 用语言、用领导人反查国家),在测试国家上问它每一跳:
| 一跳问题 | 准确率 |
|---|---|
| 第一跳:用首都反查国家 | 100.0% |
| 第一跳:用语言反查国家 | 93.8% |
| 第一跳:用领导人反查国家(反转诅咒) | 0.0% |
| 第二跳:已知国家,问首都 / 语言 / 出口 / 领导人 / 方位 | 87.5%–100.0% |
除了领导人做桥,两跳里的每一跳它都会。
2.2 合起来就不会
把两跳合成一个问题直接问它(12 种组合 × 8 个国家):2.1%。看它的回答:问”首都是 grorken 的那个国家讲什么语言”,它答 volel——只答了第一跳。它从没见过这种问题,就把它当成了见过的反查问题。
Press et al.(2023)把这个现象叫作组合性差距:模型分别答得出两个子问题,却答不出把它们合起来的问题。他们在 GPT-3 系列上发现,这个差距不随模型变大而缩小:模型越大,一跳问题的正确率提高得比两跳问题快——更大的模型记住了更多事实,但”把两个事实串起来”的能力没有同步变强。
2.3 训练它直接回答两跳问题
在训练数据里加入两跳问题(直接写答案),只用 6 种组合:
| 组合 | 桥(目标) | 测试国家 |
|---|---|---|
| 训练过 | capital(language, leader) | 93.8% |
| 训练过 | language(capital, region) | 81.2% |
| 训练过 | leader(capital, export) | 18.8% |
| 没训练过 | capital(region, export) | 18.8% |
| 没训练过 | language(leader, export) | 31.2% |
| 没训练过 | leader(language, region) | 0.0% |
- 训练过的组合,测试国家平均 87.5%。这些国家的事实从没进过微调数据,模型照样答出不少——一部分是捷径:百科里同一个国家的首都、语言、出口写在同一篇词条里,模型可能直接学到了”这个首都 ↔ 这种语言”的关联,不必经过”国家”这一步。真实的大模型也有这种现象:Yang et al.(2024)发现大模型在两跳问题上有时确实在内部完成了第一跳,但这种”隐式的多跳推理”很不稳定。
- 没训练过的组合,平均只有 25.0%。模型学到的是”这种问法 → 这种答案”,换一种”桥 × 目标”的搭配就不会了——组合泛化的失败。
- 领导人做桥:第一跳本身就做不到,多少两跳训练也救不回来。
2.4 由程序来分解:Self-Ask
换一种思路:不要求模型一次答出两跳,而是由程序把问题拆开——先问第一跳”哪个国家讲 driltese?“,把答出的国名填进第二跳的问题”volel 的首都是哪里?“再问:
| 模型 | 组合 | 桥 | 第一跳答对 | 最终答对 |
|---|---|---|---|---|
| 只学过一跳 | 没训练过 | capital | 100.0% | 93.8% |
| 只学过一跳 | 没训练过 | language | 100.0% | 93.8% |
| 只学过一跳 | 没训练过 | leader | 0.0% | 6.2% |
对程序来说根本没有”没训练过的组合”:每一步都是模型会的一跳问题。最终准确率大约是两跳各自准确率的乘积——分解之后,错误来自”某一跳答错”,而不是”不会组合”。
这就是 Self-Ask(Press et al. 2023)的想法,只是那里是让模型自己提出后续问题:提示里的示例演示”Are follow up questions needed here: Yes. Follow up: … Intermediate answer: … So the final answer is: …”这种格式,模型学着先问自己子问题、再回答。因为子问题被明确地写了出来,还可以把它们交给搜索引擎回答——Self-Ask + 搜索在他们构造的两跳问答集 Bamboogle 上大幅超过了思维链。程序化的分解(第 9 讲)和工具使用(第 8 讲)都是从这里延伸出去的。
领导人做桥的题仍然几乎全错:分解只能把模型会的东西串起来,模型不知道的一跳,分解也变不出来——这时需要检索(第 7 讲)。
3. 思维链提示 · Chain-of-thought prompting
3.1 少样本思维链(Wei et al. 2022)
Wei et al.(2022)的做法很简单:在少样本提示的每个示例里,在答案前面写出推理过程。
Q: Roger has 5 tennis balls. He buys 2 more cans of tennis balls. Each can has 3 tennis balls.
How many tennis balls does he have now?
A: Roger started with 5 balls. 2 cans of 3 tennis balls each is 6 tennis balls. 5 + 6 = 11. The answer is 11.
模型看到这样的示例,回答新问题时也会先写推理、再写答案(第 2 讲:示例首先规定格式)。他们用 8 个手写的示例,在 PaLM 540B 上把 GSM8K(小学数学应用题)的准确率提到了当时的最好水平,超过了此前”微调 GPT-3 + 训练一个验证器”的方法。
他们同时发现,这个效果依赖规模:思维链提示对小模型没有帮助、甚至有害,只在约 1000 亿参数的模型上才显著有效。小模型写出的推理”流畅但不合逻辑”。§4.2 会在迷你 GPT 上看到这件事的一个真实的小例子。
3.2 在迷你模型上:教它先写中间步骤
迷你 GPT 没有”看示例就学会写推理”的能力,所以我们直接训练它(和第 3 讲一样的指令微调):同样的两跳数据(6 种组合、12 个国家),回答写成三种格式,训练三个模型:
| 格式 | 训练过的组合 · SFT 国家 | 训练过的组合 · 测试国家 | 没训练过的组合 · 测试国家 | 平均输出词数 |
|---|---|---|---|---|
| direct | 100.0% | 87.5% | 25.0% | 1.0–1.2 |
| sentence(完整句子) | 100.0% | 21.9% | 0.0% | 14.6–17.2 |
| scratch(只写中间结果) | 100.0% | 96.9% | 87.5% | 4.0–4.3 |
(用首都 / 语言做桥的组合;领导人做桥时三种格式都是 0%。)
只是让模型先把中间的国家写下来,没训练过的组合就从 25.0% 变成 87.5%。写下的国家成了上下文的一部分,第二跳变成了模型本来就会的一跳问题——这就是思维链的核心作用。scratch 格式的名字来自 Nye et al.(2021)的草稿纸(scratchpad):他们训练模型在给出多位数加法、程序执行结果之前先写出中间计算,发现这大幅提高了模型在更长、更难的问题上的表现。
可”完整句子”的思维链却几乎全错。它写的推理最像人写的思维链,为什么最差?§4.2 专门分析。
3.3 零样本思维链:“Let’s think step by step”
Kojima et al.(2022)发现,连示例都不需要:只要在问题后面加一句 “Let’s think step by step.”,大模型就会自己写出推理过程。他们用两步提示:第一步加这句话让模型生成推理;第二步把推理接在后面,再加一句”Therefore, the answer (arabic numerals) is”来抽出答案。在 InstructGPT(text-davinci-002)上,这句话把 MultiArith 的零样本准确率从 17.7% 提到 78.7%,GSM8K 从 10.4% 提到 40.7%。
零样本思维链的好处是不需要为每个任务写示例;代价是格式不受控(推理写成什么样、答案写在哪里,都要靠后处理)。在模拟器上(05 号脚本),它比少样本思维链略差,而且更依赖规模:小模型听到”step by step”,往往并不真的开始推理。
3.4 Plan-and-Solve:先计划,再求解
Wang et al.(2023,Plan-and-Solve)分析了零样本思维链的错误,发现三类最常见:计算错误、漏掉步骤、理解错误。他们把那句话换成:“Let’s first understand the problem and devise a plan to solve the problem. Then, let’s carry out the plan and solve the problem step by step.”——先列计划,再按计划执行;加强版(PS+)还提示模型”提取相关变量""注意计算”。他们报告它在多个算术推理基准上优于零样本思维链,接近 8 个示例的少样本思维链。
在模拟器上(旋钮:漏步的概率,先列计划时降到 30%),4 步题上”先计划再求解”77%、少样本思维链 72%、零样本思维链 68%。它的代价是更多的输出(8 步题平均 127 个 token,少样本思维链 94 个)。
3.5 Step-Back:先退一步,问更抽象的问题
Zheng et al.(2024,Step-Back Prompting)针对的是另一类错误:模型陷在细节里,用错了原理。做法是先让模型回答一个更抽象的”退一步”的问题,再回答原问题。例如原问题是”如果理想气体的温度升高 2 倍、体积升高 8 倍,压强怎样变化?“,退一步的问题是”这道题涉及哪些物理原理?“(理想气体定律)。他们报告这在 PaLM-2L 上把 MMLU 物理和化学提高了 7% 和 11%,TimeQA 提高了 27%。
Step-Back 和 Self-Ask 方向相反:Self-Ask 把问题拆得更具体(子问题),Step-Back 把问题提得更抽象(原理)。两者的共同点是:先生成一段对回答有用的中间文字,再基于它回答。
3.6 一张对比表
| 方法 | 针对的错误 | 额外成本 | 在模拟器上(4 步题) |
|---|---|---|---|
| 直接回答 | — | — | 12% |
| 少样本思维链(Wei et al. 2022) | 一次算不完 | 写示例;输出变长 | 72% |
| 零样本思维链(Kojima et al. 2022) | 同上,不需要示例 | 输出变长;格式不受控 | 68% |
| Plan-and-Solve(Wang et al. 2023) | 漏步 | 输出更长 | 77% |
| Step-Back(Zheng et al. 2024) | 用错原理 | 多一步生成 | (模拟器不模拟这种错误) |
| Self-Ask / 程序分解(Press et al. 2023) | 不会组合;需要外部知识 | 多次调用 | 89% |
| self-consistency @10(Wang et al. 2023) | 随机错误 | m 倍的生成 | 95% |
(模拟器的数字由旋钮决定,只用来说明”每种方法修哪一类错误”,不代表任何真实模型。)
4. 思维链为什么有用、什么时候有用 · Why and when it works
配套代码:
02_cot_formats.py演示 2;05_prompting_variants_sim.py演示 1–3;04_self_consistency.py
4.1 摊开计算
模拟器把”一次算不完”写成了一个旋钮:不写推理时,能可靠完成的步数有限(large 模型是 2 步),超过之后每多一步成功率乘以 0.35。结果(large,每种步数 300 道题):
| 方法 | 1 步 | 2 步 | 4 步 | 6 步 | 8 步 |
|---|---|---|---|---|---|
| 直接回答 | 90% | 81% | 12% | 1% | 0% |
| 少样本思维链 | 92% | 83% | 72% | 61% | 50% |
直接回答在超过”心算”能力之后迅速崩溃;思维链的准确率随步数缓慢下降——因为每一步都可能出错,k 步全对的概率大约是 。思维链把”能不能一次算完”的问题,变成了”每一步能不能算对”的问题。
4.2 写成什么样很重要:迷你 GPT 上的”完整句子”为什么失败
回到 §3.2 那个令人意外的结果:完整句子的思维链在没训练过的组合上 0%。02 号脚本演示 2 把它的错误分了类:
| 结果 | 比例 |
|---|---|
| 抄错了问题里的实体(写成了别的首都 / 语言) | 31.2% |
| 第一句根本不是该写的那句 | 31.2% |
| 第一句对了,第二句套用了训练过的组合 | 18.8% |
| 推理写对了,却接着写成了百科、没给答案 | 15.6% |
| 没写推理,直接写了一个国名 | 3.1% |
| 完全正确 | 0.0% |
三种失败,每一种都对应一个前几讲的发现:
- 抄不准。完整句子的第一步要把问题里的首都或语言照抄下来(
braltar is the capital of …),可迷你模型没有归纳头(第 2 讲 §8.6),它写成了vuren is the capital of kumis。第一步一错,后面每一步都建立在错的基础上——错误沿着思维链传播。 - 套路。第二句套用了训练过的组合(问方位,写的却是领导人那句):模型把”先写推理”学成了几种组合的固定套路,而不是一种通用的方法。
- 续写成了文档。
grorken is the capital of volel . people in volel speak driltese . the leader of volel is kiro .——推理全对,可完整的句子太像预训练里的百科词条,模型”认出”了这种文档,就按百科的习惯写下去,忘了写答案。这是第 1 讲”base 模型续写文档”的又一次出现。
scratch 格式避开了这三种失败:它不需要照抄任何东西,也不像任何一种预训练文档。
这正是 Wei et al.(2022)“思维链依赖规模”的一个真实的小例子:生成一条正确的推理,本身就需要能力——照抄、跟踪、保持格式。能力不够时,推理越长,出错的机会越多。模拟器把它写成了旋钮(小模型每一步额外 35% 的”不合逻辑”错误),结果是:
| 规模 | 1 步 · 直接 | 1 步 · 少样本 CoT | 4 步 · 直接 | 4 步 · 少样本 CoT |
|---|---|---|---|---|
| small | 79% | 34% | 3% | 6% |
| medium | 81% | 79% | 4% | 53% |
| large | 90% | 92% | 12% | 72% |
实践上的推论:思维链写成什么样,要适合这个模型。对强的模型,完整的自然语言推理通常最好(它们在大量人类写的推理文本上训练过);对能力有限的模型(小模型、微调过的专用模型),越短、越结构化的中间步骤越可靠——例如只写出关键的中间结果,或者用固定的字段(“Step 1: … Result: …”)。
4.3 self-consistency:多想几遍、少数服从多数
做法(Wang et al. 2023):用温度采样生成多条思维链,取最终答案的多数票。他们报告这在思维链的基础上又带来明显提升,例如 PaLM 540B 在 GSM8K 上提高了约 18 个百分点(SVAMP 约 11 个、AQuA 约 12 个)。
为什么有效:他们的解释是”对推理路径求和”。同一道题往往有很多条正确的推理路径,都通向同一个正确答案;错误的路径各错各的,通向不同的错误答案。概率最大的那一条路径(贪心解码)未必通向概率最大的那个答案:
多数投票是在用采样估计右边那个”对路径求和”的量。
在迷你 GPT 上(scratch 模型,测试国家,每组 32 道题):
| 温度 | 题目 | 贪心 | 单条采样(平均) | 投票 @5 | 投票 @15 |
|---|---|---|---|---|---|
| 1.0 | 训练过的组合 | 96.9% | 72.1% | 87.5% | 87.5% |
| 1.0 | 没训练过的组合 | 87.5% | 64.8% | 81.2% | 84.4% |
| 1.0 | 领导人做桥 | 9.4% | 7.7% | 9.4% | 12.5% |
投票把单条采样的分散错误投掉了大部分,但没有超过贪心解码(三组合计,投票相对贪心修好了 1 道、弄坏了 4 道)。原因正是上面那个公式:在 scratch 格式里,每个答案只对应一条路径(写下哪个国家,就答哪个国家的属性),概率最大的路径就是概率最大的答案;投票只是带着噪声估计同一件事。
模拟器里设置了”多条可靠性不同的解题路径,最常被选中的那条最容易出错”,self-consistency 就超过了贪心(4 步题,没有系统性误解时:贪心 77%,投票 @40 到 100%)。self-consistency 的收益是一个经验问题,取决于模型的推理路径有多少条、错误有多分散。
什么时候无效:投票会收敛到每道题”最常见的答案”。对模型”不知道”的题(领导人做桥),它反复编出同一个国家,某个错误答案最常见(32 道里有 28 道是这样),投票反而把错误固定下来。模拟器把这写成”系统性误解”的比例:
| 系统性误解的比例 | 贪心思维链 | 投票 @5 | 投票 @40 |
|---|---|---|---|
| 0% | 77% | 99% | 100% |
| 6% | 72% | 95% | 95% |
| 15% | 66% | 86% | 87% |
| 30% | 55% | 72% | 73% |
误解的比例是多少,投票的上限就大约差多少。投票修正随机错误,修不了系统性错误。
投票的数学(04 号脚本演示 3):每次采样以概率 p 答对,错误平均分散在 k 个答案上:
| p | 错误答案的个数 k | 每个错误答案的概率 | 投票 @1 | @15 | @41 |
|---|---|---|---|---|---|
| 0.6 | 1 | 0.40 | 60.0% | 78.7% | 90.3% |
| 0.6 | 5 | 0.08 | 60.0% | 98.8% | 100.0% |
| 0.4 | 5 | 0.12 | 40.0% | 78.6% | 97.8% |
| 0.4 | 1 | 0.60 | 40.0% | 21.3% | 9.7% |
这是孔多塞陪审团定理的推广:投票要求的不是 p > 0.5,而是”正确答案比任何一个错误答案都更常见”。p = 0.4 但错误分散时,投票照样能把准确率推到接近 100%;p = 0.4 而错误集中在一个答案上时,投票越多越错。
一个副产品:投票的一致程度(最常见答案占多少票)是一个有用的置信度信号。在迷你 GPT 上,投票答对的题平均 75% 的票一致,答错的题只有 35%。第 5 讲的 SelfCheckGPT 用的正是这个思路:多次采样的答案不一致,说明模型可能在编造。
5. 思维链忠实吗? · Is the chain faithful?
配套代码:
03_faithfulness.py
5.1 问题
模型写出”volel . answer grorken”,我们自然以为它是因为想到了 volel,才答 grorken。但这不是必然的:它可能早在内部就算好了答案,写出的推理只是一段”事后的说明”。如果是这样,思维链就不能用来理解、检查、纠正模型的推理。这个问题叫忠实性。
5.2 干预实验
检验忠实性的办法是动手改思维链,看答案变不变(Lanham et al. 2023)。在 scratch 模型上:
(1) 替它写一个错的中间国家(prefill,P2 §3.4),让它接着写:
| 国家 | 跟着思维链(答错国家的属性) | 无视思维链(答真正的答案) |
|---|---|---|
| SFT 国家 | 93.8% | 4.2% |
| 测试国家 | 98.4% | 0.0% |
(2) 不让它写中间步骤(测试国家):
| 干预 | 训练过的组合 | 没训练过的组合 |
|---|---|---|
| 正常(自己写中间国家) | 96.9% | 87.5% |
| 提前作答:直接从 “answer” 开始 | 25.0% | 31.2% |
中间步骤换成占位符 <unk> . | 9.4% | 25.0% |
| 替它写好正确的国家 | 96.9% | 93.8% |
(3) 它自己写错中间国家时(不做干预):写错的 20 道题里,17 道的答案和它写下的错国家一致(“忠实地错”),没有一道”写错了国家却答对了”。这 20 道里 17 道是领导人做桥的。
这个模型的思维链是因果上有效的:改掉中间步骤,答案跟着变;去掉它,答案就垮;换成无意义的占位符也不行。这是我们训练它的方式决定的——训练数据里,答案总是由前面写下的国家决定。
5.3 真实的大模型没有这样的保证
真实模型的思维链是从人类写的推理文本和后续训练里学来的,研究发现了两个方向的问题:
- 不依赖:Lanham et al.(2023)用同样的干预(提前截断、插入错误、改写、换成同样长度的填充)测了 Anthropic 的模型,发现结果因任务而异:在一些任务上截断思维链几乎不改变答案(答案并不依赖它),在另一些任务上则大幅改变;而且在他们研究的多数任务上,越大、越强的模型,写出的推理越不忠实。
- 系统性地不说实话:Turpin et al.(2023)在少样本提示里加入偏向,例如把示例的选项重新排列,使正确答案总是 (A)。模型的答案被这个偏向带走,准确率显著下降,可它写出的思维链从不提到”答案总是 A”,而是给出一个看似合理的理由。
“忠实”本身也不保证”正确”:迷你模型在领导人做桥的题上忠实地按编出来的国家答下去。忠实的思维链的好处是,错误看得见、查得出——第 10 讲的验证链(CoVe)就是让模型检查自己写下的每一个中间事实。
对提示工程的启示:可以用思维链来调试提示(看模型在哪一步想错了),但不要把它当作模型行为的可靠解释;需要可靠性时,对中间步骤做独立的验证(第 10 讲),或者把关键步骤交给程序和工具(第 8、9 讲)。
6. 成本,以及什么时候不用思维链 · Costs and when not to use CoT
配套代码:
05_prompting_variants_sim.py演示 1、4
成本。思维链让输出变长;输出 token 通常比输入 token 贵好几倍(P2 §6 的价格表里,输出是输入的 5 倍),而且生成是一个 token 一个 token 地串行进行,延迟也随之增加。在模拟器上(8 步题):
| 方法 | 输出 token | 调用次数 |
|---|---|---|
| 直接回答 | 9 | 1 |
| 少样本思维链 | 94 | 1 |
| 先计划再求解 | 127 | 1 |
| 程序逐步分解 | 97 | 8 |
| self-consistency @10 | 939 | 10 |
更准的方法几乎总是更贵。真实模型的思维链常常是几百上千个 token;self-consistency @10 就是十倍的费用。要按任务的价值决定花多少。
什么时候不用。一步就能答的题(模拟器演示 4):
| 方法 | 1 步题的准确率 | 平均输出 token |
|---|---|---|
| 直接回答 | 89.7% | 8.2 |
| 少样本思维链 | 92.3% | 18.5 |
| 先计划再求解 | 91.3% | 49.4 |
准确率差不多,输出却多了好几倍。Sprague et al.(2024,《To CoT or not to CoT?》)汇总了一百多篇论文,并在 14 个模型上做实验,发现思维链的收益主要集中在数学和符号推理上;在常识、知识问答等任务上收益很小——那里的瓶颈是”知不知道”,不是”会不会算”。本讲的领导人做桥的题是一个极端的例子:模型不知道,写多少步、投多少票都没用(三种格式都是 0%)。
一张实用的决策表:
| 情形 | 建议 |
|---|---|
| 一步就能答(查事实、分类、抽取) | 直接回答;需要可解释性时再要求简短的理由 |
| 多步计算、逻辑推理、多约束的规划 | 思维链;格式不稳时用少样本示例规定格式 |
| 需要外部知识的多跳问题 | 分解 + 检索 / 工具(第 7–9 讲),而不只是思维链 |
| 答案能自动检查(数值、代码) | 多次采样 + 投票,或采样 + 验证(第 10、11 讲) |
| 预算紧、延迟敏感 | 先测直接回答够不够;只在不确定时才多采样(自适应) |
| 模型本身会在内部推理(§7) | 不必再要求它写出长推理;用 effort / 思考预算控制深度 |
7. 推理模型:把思维链训练进模型 · Reasoning models
2024–2025 年,思维链从一种提示技巧变成了一种训练出来的能力。OpenAI 的 o1(2024)和 DeepSeek-R1(DeepSeek-AI 2025)等推理模型用强化学习训练:给模型可以自动验证答案的问题(数学、代码),奖励最终答案正确的生成;模型在这个过程中学会了在回答之前生成很长的推理——包括尝试、检查、发现错误、回头重来。DeepSeek-R1 的报告描述了推理过程随训练自发变长、出现”反思”行为的现象。
这改变了几件事:
- “要不要思维链”变成了”想多深”。推理模型在内部(通常不完全展示给用户)先推理再回答。API 提供的旋钮不再是提示里的”Let’s think step by step”,而是思考的预算或深度(例如本课默认的 claude-opus-5-5 用 effort:low / medium / high……,P2 §3.6)。
- 测试时计算可以换准确率。生成更长的推理、多次采样、搜索,都是”在推理时花更多计算”(test-time compute);Snell et al.(2024)等工作研究了这种花法在什么时候比用更大的模型更划算。self-consistency 是最早、最简单的一种。
- 老的提示技巧不一定还有用。对一个已经会在内部推理的模型,再要求它在回答里写出一步步的推理,收益可能很小,却多付了输出的钱;少样本的思维链示例甚至可能干扰它自己的推理方式。换了推理模型,要重新测你的提示。
- 忠实性问题依然存在。推理模型写出的推理也不保证是它得出答案的真正原因(§5);而且它的内部推理通常不完全可见。
06_real_llm.py(可选)在真实的 Claude 上比较四种提示(只写最终数字 / “Let’s think step by step” / 两个写好推理的示例 / 先计划再求解)× 2、4、8 步的算术题,并报告平均输出 token;可以用 --effort 比较思考深度。编写这份讲义的环境里没有安装 anthropic SDK,没有真实模型的结果可以报告;--toy 模式用模拟器检查代码能跑通。运行时最值得看的是”只写最终数字”那一行:如果它在 8 步题上也几乎全对、输出 token 却远多于一个数字,说明模型在内部做了推理。
8. 小结 · Summary
- 思维链 = 把中间结果写出来。写下的东西成了上下文,下一步只需要读它——“一次前向计算里完成的组合”被摊开成几次”写下来、再读回来”。
- 组合性差距:迷你模型每一跳都会(88%–100%),两跳合起来只有 2.1%;训练它直接回答,没训练过的组合只有 25%。Press et al. 发现这个差距不随规模缩小。
- 分解:由程序把问题拆成一跳问题,没训练过的组合到 94%(Self-Ask 的外部版本);只写中间结果的草稿纸到 87.5%。
- 写成什么样很重要:完整句子的思维链在迷你模型上 0%——抄不准、套路化、续写成百科。生成正确的推理本身需要能力,这是”思维链依赖规模”的一个缩影。
- 各种变体针对不同的错误:零样本 CoT 省掉示例,Plan-and-Solve 减少漏步,Step-Back 先找原理,Self-Ask 把子问题显式化(还可以交给搜索)。
- self-consistency 修随机错误、修不了系统性错误;它要求正确答案是”最常见”的答案,而不是 p > 0.5。当每个答案只有一条推理路径时,它基本只是在复现贪心。
- 忠实性:迷你模型的思维链是因果有效的(换掉中间国家,98% 的答案跟着变);真实大模型的思维链可能不依赖、甚至系统性地隐瞒真正的原因。
- 成本与适用范围:思维链的收益集中在数学和符号推理;一步就能答、或模型根本不知道的问题,它只增加成本。
- 推理模型把思维链训练进了模型:提示层面的”要不要推理”变成了”想多深”;换模型要重测提示。
9. 常见误区 · Common pitfalls
| 误区 | 实际情况 |
|---|---|
| “加一句 Let’s think step by step 总有好处” | 在小模型、一步就能答的问题上没用甚至有害;在推理模型上可能多余;它总是增加输出成本 |
| “推理写得越详细越好” | 对能力有限的模型,越长越容易出错(抄错、套路、跑题);格式要适合模型 |
| “思维链能让模型答出它不知道的事” | 不能:领导人做桥的题三种格式都是 0%;需要检索或工具 |
| “self-consistency 只要 p > 0.5 就有效” | 要求的是正确答案比任何一个错误答案都常见;系统性错误投不掉 |
| “多采样几次总比贪心好” | 每个答案只对应一条推理路径时,投票基本在复现贪心,还带噪声 |
| “模型写出的推理就是它的真实想法” | 不一定:可能不依赖推理,也可能隐瞒真正的原因(Turpin et al. 2023) |
| “Self-Ask 和思维链是一回事” | Self-Ask 把子问题显式地写出来,可以交给程序或搜索引擎回答;思维链只是自由的推理文字 |
| “思维链提示在所有模型上都一样有效” | 依赖规模和训练;推理模型已经在内部推理,老技巧要重新测 |
10. 练习 · Exercises
练习 1(概念) 用一句话解释思维链为什么能帮助多步问题,并说明它为什么对”模型不知道的事实”无效。
参考答案:思维链让模型把中间结果写进上下文,后面的每一步只需要读前文、做一个简单的操作,于是需要多步的计算不必挤在一次前向计算里完成;但如果某一步需要的事实模型根本不知道(例如由领导人反查国家),写出步骤只会让它在那一步编一个答案,然后”忠实地”沿着错的方向走下去。
练习 2(读表) §2.3 里,训练过的组合在测试国家上 87.5%,没训练过的组合只有 25.0%。(a)为什么训练过的组合能泛化到没见过的国家?(b)为什么换一种组合就不行?(c)scratch 格式在没训练过的组合上 87.5%,它”泛化”的单位是什么?
参考答案:(a)训练教会了模型”这种问法 → 用这条通道取出这种属性”,而通道另一头的知识来自预训练(第 3 讲),对没见过的国家也成立;部分还来自同一篇百科里属性之间的直接关联(捷径)。(b)direct 模型学到的单位是”整个两跳问法 → 答案”,没训练过的组合是一种新的问法,没有对应的通道。(c)scratch 格式泛化的单位是一跳:第一跳”由首都 / 语言找国家”和第二跳”由国家找属性”都分别训练过,组合只是把两个一跳串起来,所以任何组合都能用。这就是”把问题分解成可复用的步骤”带来组合泛化的原因。
练习 3(计算) 一个模型每次采样答对的概率是 0.45,错误答案平均分散在 3 个值上(每个 0.183)。(a)投票 @1 和投票 @∞ 的准确率各是多少?(b)如果错误集中在一个值上(0.55),呢?
参考答案:(a)@1 是 0.45;正确答案(0.45)比任何一个错误答案(0.183)都常见,所以 m → ∞ 时投票几乎总能选中它,准确率趋近 100%。(b)错误答案(0.55)比正确答案常见,m → ∞ 时投票几乎总选中错误答案,准确率趋近 0(可以用 04 号脚本的
p_majority验证有限 m 的值)。
练习 4(设计) 你在做一个”根据公司内部文档回答多跳问题”的系统(例如”负责 X 项目的那个人的经理是谁?”)。比较三种方案:直接问、思维链、Self-Ask + 检索。各有什么优缺点?你会怎样做实验来选择?
参考答案:直接问最便宜,但多跳问题的组合性差距大,而且模型不知道内部文档里的事实。思维链能帮助组合,但每一跳仍依赖模型的记忆,内部事实它不知道。Self-Ask + 检索把每个子问题(“谁负责 X 项目?""张三的经理是谁?“)交给检索系统回答,能处理内部知识,错误也可定位(是哪一跳检索错了),但调用次数和延迟更多、需要维护检索系统。实验:构造一批带标准答案的多跳问题(最好按”跳数”和”实体是否常见”分层),三种方案在同一组题上比较准确率、每题成本和延迟,用配对检验(P3);分别统计每一跳的准确率,看错误出在哪里。
练习 5(解释) §4.3 里,迷你 GPT 上 self-consistency 没有超过贪心,模拟器里却超过了。用”对推理路径求和”解释这两个结果的区别。
参考答案:贪心解码选的是概率最大的路径的答案,投票估计的是”对所有通向同一答案的路径求和”之后概率最大的答案。在 scratch 格式的迷你模型里,每个答案只对应一条路径(写下哪个国家就答哪个属性),路径的概率就是答案的概率,两者选出的是同一个答案,投票只是带噪声地估计它。模拟器里同一个答案可以由多条可靠性不同的路径得到,而最常被选中的那条路径最容易出错——概率最大的路径(贪心)往往通向错误答案,但正确答案在所有路径上的总概率更大,投票就能选中它。
练习 6(动手) 修改 cot_lab.twohop_response,加一种格式 "tagged":"bridge volel . answer grorken"(在中间结果前面加一个固定的标签词)。训练并和 scratch 比较。你预期会怎样?如果把标签换成一个完整的句子开头 "the country is volel ." 呢?
参考答案:预期
tagged和 scratch 差不多:标签词是固定的,不需要照抄,也不像任何预训练文档。"the country is volel ."有一点风险:the country is后面接国名的结构在百科里出现过(“volel is a country in the …” 不完全一样),可能诱发续写百科;但它仍然不需要照抄问题里的实体,所以预计远好于 sentence 格式。实际结果要运行才知道:get_cot_model(fmt="tagged")(需要先在FORMATS和twohop_response里加上这种格式),并在没训练过的组合上测。
练习 7(忠实性) 设计一个在真实 chat 模型上检验思维链忠实性的实验(不需要访问模型内部),参考 §5.2 的干预。
参考答案:选一批模型能用思维链答对的多步问题。(1)提前作答:让模型先写推理,然后把推理截断在不同长度(0%、25%、50%……),接上”So the answer is”让它直接给答案,看答案在截断到多短时还不变——变化越早,说明答案越依赖推理。(2)插入错误:在模型写好的推理里改掉一个中间数字或事实,让它从那里接着写,看最终答案是否跟着变。(3)偏向测试(Turpin et al.):在提示里加入一个与正确答案无关的偏向(例如示例的答案总在同一个位置),看答案是否被带走、而推理里是否提到了这个偏向。注意有的 API 不支持预填 assistant 的开头,可以把”已经写好的推理”放在用户消息里,请模型”从这段推理继续”。
练习 8(批判) 有人说:“推理模型已经会自己思考了,提示工程里关于思维链的东西都过时了。“你同意吗?
参考答案:部分同意:对推理模型,“Let’s think step by step”这类触发语基本多余,少样本的推理示例甚至可能干扰它;控制推理深度的主要手段变成了 effort / 思考预算。但这一讲的核心内容并没有过时:(1)组合性差距和分解——需要外部知识的多跳问题,仍要靠检索和工具,而不是更长的推理;(2)self-consistency 的统计学——测试时计算能修随机错误、修不了系统性错误,这对推理模型同样成立;(3)忠实性——推理模型的推理同样不保证忠实,可靠性仍要靠独立验证;(4)成本——推理模型的思考 token 照样计费,“一步就能答的问题不必长推理”依然是省钱的原则。
11. 延伸阅读 · Further reading
思维链提示
- Wei, J. et al. (2022). Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. NeurIPS.
- Kojima, T., Gu, S. S., Reid, M., Matsuo, Y., & Iwasawa, Y. (2022). Large Language Models are Zero-Shot Reasoners. NeurIPS.
- Nye, M. et al. (2021). Show Your Work: Scratchpads for Intermediate Computation with Language Models. arXiv:2112.00114.
- Wang, L. et al. (2023). Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. ACL.
- Zheng, H. S. et al. (2024). Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models. ICLR.
分解与组合
- Press, O. et al. (2023). Measuring and Narrowing the Compositionality Gap in Language Models (Self-Ask). Findings of EMNLP.
- Zhou, D. et al. (2023). Least-to-Most Prompting Enables Complex Reasoning in Large Language Models. ICLR.(第 9 讲细讲)
- Yang, S., Gribovskaya, E., Kassner, N., Geva, M., & Riedel, S. (2024). Do Large Language Models Latently Perform Multi-Hop Reasoning? ACL.
self-consistency 与测试时计算
- Wang, X. et al. (2023). Self-Consistency Improves Chain of Thought Reasoning in Language Models. ICLR.
- Snell, C., Lee, J., Xu, K., & Kumar, A. (2024). Scaling LLM Test-Time Compute Optimally Can be More Effective than Scaling Model Parameters. arXiv:2408.03314.
忠实性
- Lanham, T. et al. (2023). Measuring Faithfulness in Chain-of-Thought Reasoning. arXiv:2307.13702.
- Turpin, M., Michael, J., Perez, E., & Bowman, S. R. (2023). Language Models Don’t Always Say What They Think: Unfaithful Explanations in Chain-of-Thought Prompting. NeurIPS.
什么时候有用、为什么有用
- Sprague, Z. et al. (2024). To CoT or not to CoT? Chain-of-thought Helps Mainly on Math and Symbolic Reasoning. arXiv:2409.12183.
- Feng, G. et al. (2023). Towards Revealing the Mystery behind Chain of Thought: A Theoretical Perspective. NeurIPS.
- Merrill, W., & Sabharwal, A. (2024). The Expressive Power of Transformers with Chain of Thought. ICLR.
推理模型
- OpenAI (2024). Learning to Reason with LLMs(o1 的介绍). OpenAI blog.
- DeepSeek-AI (2025). DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arXiv:2501.12948.
12. 下一讲预告 · Next lecture
这一讲反复碰到同一堵墙:领导人做桥的题,模型不知道答案,于是它编一个——而且编得很自信,每次采样都编同一个,写出的思维链还”忠实地”沿着编出来的答案走下去。第 5 讲进入原课第 4 周:对齐(一):幻觉与校准。
- 什么是对齐(helpful / honest / harmless);幻觉的类型(事实性 vs 忠实性、内在 vs 外在)和来源(数据、训练、解码、长尾知识);
- 校准:模型的置信度和它的正确率是否一致;ECE 与可靠性图;“语言模型大多知道自己知道什么”(Kadavath et al. 2022);RLHF 之后校准变差;
- 减少幻觉:检索、允许说”不知道”、弃权阈值、多次采样的一致性检测(SelfCheckGPT——本讲的投票一致程度正是它的雏形);
- 动手:在一个”有的国家常见、有的国家罕见”的长尾世界上训练迷你 GPT,测量知识怎样随出现频率衰减、模型的置信度准不准、在不确定时让它弃权能换来多少可靠性。