Lecture 4 · 思维链提示 · Chain-of-Thought Prompting

Prompt Engineering · Lecture 04。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 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

学完这一讲,你应该能够:

  1. 解释思维链(chain of thought,CoT)为什么能提高多步问题的准确率:它把”一次前向计算里完成的组合”摊开成”写下来、再读回来”的几步。
  2. 用组合性差距描述”每一步都会、合起来就不会”的现象,并知道两种缩小它的办法:让模型自己写中间步骤,或由程序来分解(Self-Ask)。
  3. 比较少样本思维链、零样本思维链(“Let’s think step by step”)、Plan-and-Solve、Step-Back、Self-Ask 各自针对哪一类错误、各要多付出什么成本。
  4. 理解 self-consistency 的原理和边界:它修正随机错误,修不了系统性错误;它要求”正确答案比任何一个错误答案都更常见”,而不是 p > 0.5。
  5. 知道思维链在什么情况下没用甚至有害(小模型、一步就能答的问题、不知道的事实),以及为什么”写成什么格式”很重要。
  6. 说清楚忠实性问题:模型写出的推理,未必是它真正用来得出答案的过程;会用干预实验检验它。
  7. 理解推理模型(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)。

这一讲依次回答四个问题:

  1. 这个困难是真的吗?“每一步都会、合起来就不会”有多严重?(§2)
  2. 有哪些办法让模型写出中间步骤?各有什么区别?(§3)
  3. 它为什么有用、什么时候有用、写成什么样?多想几遍(self-consistency)又是怎么回事?(§4)
  4. 模型写出的推理,是它真正的推理吗?代价是什么?(§5–§7)

2. 组合性差距 · The compositionality gap

配套代码:01_compositionality_gap.py

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 的首都是哪里?“再问:

模型组合桥第一跳答对最终答对
只学过一跳没训练过capital100.0%93.8%
只学过一跳没训练过language100.0%93.8%
只学过一跳没训练过leader0.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

配套代码:02_cot_formats.py;05_prompting_variants_sim.py

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 国家训练过的组合 · 测试国家没训练过的组合 · 测试国家平均输出词数
direct100.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 步全对的概率大约是 (1−e)k(1-e)^k。思维链把”能不能一次算完”的问题,变成了”每一步能不能算对”的问题。

4.2 写成什么样很重要:迷你 GPT 上的”完整句子”为什么失败

回到 §3.2 那个令人意外的结果:完整句子的思维链在没训练过的组合上 0%。02 号脚本演示 2 把它的错误分了类:

结果比例
抄错了问题里的实体(写成了别的首都 / 语言)31.2%
第一句根本不是该写的那句31.2%
第一句对了,第二句套用了训练过的组合18.8%
推理写对了,却接着写成了百科、没给答案15.6%
没写推理,直接写了一个国名3.1%
完全正确0.0%

三种失败,每一种都对应一个前几讲的发现:

  1. 抄不准。完整句子的第一步要把问题里的首都或语言照抄下来(braltar is the capital of …),可迷你模型没有归纳头(第 2 讲 §8.6),它写成了 vuren is the capital of kumis。第一步一错,后面每一步都建立在错的基础上——错误沿着思维链传播。
  2. 套路。第二句套用了训练过的组合(问方位,写的却是领导人那句):模型把”先写推理”学成了几种组合的固定套路,而不是一种通用的方法。
  3. 续写成了文档。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 步 · 少样本 CoT4 步 · 直接4 步 · 少样本 CoT
small79%34%3%6%
medium81%79%4%53%
large90%92%12%72%

实践上的推论:思维链写成什么样,要适合这个模型。对强的模型,完整的自然语言推理通常最好(它们在大量人类写的推理文本上训练过);对能力有限的模型(小模型、微调过的专用模型),越短、越结构化的中间步骤越可靠——例如只写出关键的中间结果,或者用固定的字段(“Step 1: … Result: …”)。

4.3 self-consistency:多想几遍、少数服从多数

做法(Wang et al. 2023):用温度采样生成多条思维链,取最终答案的多数票。他们报告这在思维链的基础上又带来明显提升,例如 PaLM 540B 在 GSM8K 上提高了约 18 个百分点(SVAMP 约 11 个、AQuA 约 12 个)。

为什么有效:他们的解释是”对推理路径求和”。同一道题往往有很多条正确的推理路径,都通向同一个正确答案;错误的路径各错各的,通向不同的错误答案。概率最大的那一条路径(贪心解码)未必通向概率最大的那个答案:

a^贪心=answer(arg⁡max⁡rP(r∣q))vsa^投票≈arg⁡max⁡a∑r: answer(r)=aP(r∣q)\hat a_{\text{贪心}} = \text{answer}\Big(\arg\max_{r} P(r \mid q)\Big) \qquad \text{vs} \qquad \hat a_{\text{投票}} \approx \arg\max_{a} \sum_{r:\ \text{answer}(r) = a} P(r \mid q)

多数投票是在用采样估计右边那个”对路径求和”的量。

在迷你 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.610.4060.0%78.7%90.3%
0.650.0860.0%98.8%100.0%
0.450.1240.0%78.6%97.8%
0.410.6040.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调用次数
直接回答91
少样本思维链941
先计划再求解1271
程序逐步分解978
self-consistency @1093910

更准的方法几乎总是更贵。真实模型的思维链常常是几百上千个 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 的报告描述了推理过程随训练自发变长、出现”反思”行为的现象。

这改变了几件事:

  1. “要不要思维链”变成了”想多深”。推理模型在内部(通常不完全展示给用户)先推理再回答。API 提供的旋钮不再是提示里的”Let’s think step by step”,而是思考的预算或深度(例如本课默认的 claude-opus-5-5 用 effort:low / medium / high……,P2 §3.6)。
  2. 测试时计算可以换准确率。生成更长的推理、多次采样、搜索,都是”在推理时花更多计算”(test-time compute);Snell et al.(2024)等工作研究了这种花法在什么时候比用更大的模型更划算。self-consistency 是最早、最简单的一种。
  3. 老的提示技巧不一定还有用。对一个已经会在内部推理的模型,再要求它在回答里写出一步步的推理,收益可能很小,却多付了输出的钱;少样本的思维链示例甚至可能干扰它自己的推理方式。换了推理模型,要重新测你的提示。
  4. 忠实性问题依然存在。推理模型写出的推理也不保证是它得出答案的真正原因(§5);而且它的内部推理通常不完全可见。

06_real_llm.py(可选)在真实的 Claude 上比较四种提示(只写最终数字 / “Let’s think step by step” / 两个写好推理的示例 / 先计划再求解)× 2、4、8 步的算术题,并报告平均输出 token;可以用 --effort 比较思考深度。编写这份讲义的环境里没有安装 anthropic SDK,没有真实模型的结果可以报告;--toy 模式用模拟器检查代码能跑通。运行时最值得看的是”只写最终数字”那一行:如果它在 8 步题上也几乎全对、输出 token 却远多于一个数字,说明模型在内部做了推理。


8. 小结 · Summary

  1. 思维链 = 把中间结果写出来。写下的东西成了上下文,下一步只需要读它——“一次前向计算里完成的组合”被摊开成几次”写下来、再读回来”。
  2. 组合性差距:迷你模型每一跳都会(88%–100%),两跳合起来只有 2.1%;训练它直接回答,没训练过的组合只有 25%。Press et al. 发现这个差距不随规模缩小。
  3. 分解:由程序把问题拆成一跳问题,没训练过的组合到 94%(Self-Ask 的外部版本);只写中间结果的草稿纸到 87.5%。
  4. 写成什么样很重要:完整句子的思维链在迷你模型上 0%——抄不准、套路化、续写成百科。生成正确的推理本身需要能力,这是”思维链依赖规模”的一个缩影。
  5. 各种变体针对不同的错误:零样本 CoT 省掉示例,Plan-and-Solve 减少漏步,Step-Back 先找原理,Self-Ask 把子问题显式化(还可以交给搜索)。
  6. self-consistency 修随机错误、修不了系统性错误;它要求正确答案是”最常见”的答案,而不是 p > 0.5。当每个答案只有一条推理路径时,它基本只是在复现贪心。
  7. 忠实性:迷你模型的思维链是因果有效的(换掉中间国家,98% 的答案跟着变);真实大模型的思维链可能不依赖、甚至系统性地隐瞒真正的原因。
  8. 成本与适用范围:思维链的收益集中在数学和符号推理;一步就能答、或模型根本不知道的问题,它只增加成本。
  9. 推理模型把思维链训练进了模型:提示层面的”要不要推理”变成了”想多深”;换模型要重测提示。

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,测量知识怎样随出现频率衰减、模型的置信度准不准、在不确定时让它弃权能换来多少可靠性。
← 返回课程目录