Skip to content

02.5 思维链与 Extended Thinking

让模型"想清楚再说",以及它什么时候会想太多。

读完你能做什么:判断何时该开思考、选对 effort 级别,并抑制过度思考带来的副作用。


一、思维链的本质

思维链(Chain of Thought)不是让模型"更聪明",而是给它更多的计算步骤

回到第一性原理:模型每生成一个 token,就是一次前向传播。如果你要求它直接输出答案,它只有很少的 token 用于"计算";如果允许它先写推理过程,那些推理 token 本身就是计算的载体。

text
问:一个班 30 人,60% 是女生,女生中 1/3 参加了合唱团,合唱团女生有几人?

❌ 直接回答(少量计算步骤)
   "6 人"  ← 可能对,可能错,取决于这个模式在训练数据中有多常见

✅ 显式推理(充分的计算步骤)
   女生人数 = 30 × 60% = 18
   参加合唱团的女生 = 18 × 1/3 = 6
   答案:6 人

推论:任何需要多步计算或多步逻辑的任务,都该开思考。任何一步就能得到答案的任务,开思考只是浪费时间。


二、三种思考机制

2.1 提示词层面的 CoT(所有场景可用)

text
在 <thinking> 标签内先分析,然后在 <answer> 标签内给出最终答案。

或者更结构化:

text
<instructions>
按以下步骤处理,每一步的结果都写出来:
1. 列出所有已知条件
2. 识别需要求解的目标
3. 找出连接已知与目标的推理链
4. 逐步计算
5. 用另一种方法验算
6. 给出最终答案
</instructions>

这种方式最可控 —— 你可以精确指定思考的结构。

2.2 [Extended Thinking] (扩展思考)(网页/客户端)

输入框旁的开关。开启后模型在给出回复前进行一段独立的推理过程。

2.3 Effort Level(Claude Code)

bash
claude --effort low       # 快
claude --effort medium
claude --effort high      # 深度推理
claude --effort xhigh
claude --effort max

会话中:

text
> /effort

可用级别取决于模型。 这是"同一个模型,不同投入"的旋钮,性价比常常优于换更贵的模型。

2.4 交错思考(Interleaved Thinking)

工具调用之间穿插推理。适合 Agent 场景 —— 它读到工具返回的结果后,先想一想,再决定下一步调什么工具。

在 Claude Code 中,这通常是自动的。在 API 中通过 beta 特性开启:

bash
claude --betas interleaved-thinking

三、什么时候开,什么时候关

场景建议理由
数学计算、单位换算✅ 开需要中间步骤
多约束的方案设计✅ 开需要枚举与权衡
疑难 bug 的根因分析✅ 开需要建立因果链
代码逻辑正确性推导✅ 开需要模拟执行
大规模重构的影响分析✅ 开需要追踪依赖
格式转换(JSON → YAML)❌ 关机械操作,思考无收益
翻译❌ 关直接映射
简单事实问答❌ 关纯延迟
代码补全❌ 关模式匹配
创意写作⚠️ 慎用过度分析会让文字机械化
需要严格遵守输出格式⚠️ 慎用长思考后可能"忘记"格式约束,需要在末尾重申

四、过度思考(Overthinking)

这是开启思考后最常见的副作用。

4.1 症状

症状表现
穷举无关分支简单任务被分析出 8 种可能性,每种都展开
过度防御性编码要求写个工具函数,它给你加上重试、熔断、日志、指标
决策瘫痪反复权衡,最后说"取决于你的具体需求"
格式漂移思考太长,末尾忘了输出格式要求
自我怀疑循环得出答案后又推翻,来回好几轮

4.2 抑制手段

手段 1:给出范围约束

text
<constraints>
- 这是一个简单任务。不要考虑并发、分布式或超大规模场景。
- 输入规模:最多 1000 条记录,单机内存足够
- 只需要处理正常路径 + 空输入,其他边界情况不用管
</constraints>

手段 2:限制思考深度

text
在 <thinking> 中最多分析 3 个候选方案,不要穷举。
选出一个后直接给实现,不要再回头质疑。

手段 3:明确"够好就行"

text
这是一个原型,不是生产代码。优先可读性和实现速度,
不要加错误处理、日志、配置化。能跑通就行。

手段 4:末尾重申格式

长思考后模型的注意力已经被推理内容占据,格式要求容易衰减。解法:把格式要求放在最后重复一遍

text
{……长提示词……}

<output_format>
{格式规范}
</output_format>

再次确认:无论思考多长,最终输出必须严格符合上面的 output_format,
不要添加任何额外的解释段落。

手段 5:降低 effort

bash
claude --effort low

对于机械性任务,低 effort 反而结果更好 —— 因为它不会想着去"优化"你没要求优化的东西。


五、思考的正确使用姿势

5.1 给思考一个明确的检查清单

不要只说"仔细想想",要给它想什么:

text
<instructions>
在 <thinking> 中,逐项确认以下问题,每项都要给出明确答案:

1. 这段代码的输入可能是 None 吗?如果是,会发生什么?
2. 有没有资源需要释放?释放路径在异常时也会执行吗?
3. 有共享状态吗?多线程调用会怎样?
4. 有 IO 操作吗?失败了会怎样?
5. 时间复杂度是多少?在 100 万条数据下可接受吗?

然后在 <answer> 中给出结论。
</instructions>

效果:把"自由发挥的思考"变成"结构化的检查",既避免遗漏,又避免发散。

5.2 让思考成为可验证的中间产物

text
在 <thinking> 中,把你的推理写成可验证的形式:
- 每个数值计算写出算式
- 每个关于代码行为的断言,标注你依据的是哪一行代码
- 每个假设显式写成「假设:xxx」

这样我可以逐条检查你的推理链,而不是只能接受或拒绝最终结论。

这一招把思考过程从"黑盒解释"变成"可审计的证据链",是高风险决策场景的必备手段。


六、思考不能解决的问题

必须清楚思考的边界,否则会产生虚假的安全感。

思考改善思考不能改善
多步推理的准确性训练数据里就没有的知识
逻辑一致性你没提供的上下文
数值计算需要实际执行才能知道的结果
遗漏的边界情况对外部系统当前状态的判断
方案的完整性时效性信息

关键:一个基于错误前提的严密推理,仍然会得到错误结论。而且思考过程会让错误结论看起来更可信 —— 这是思考带来的最大风险。

对策:对涉及外部事实的任务,先用工具验证前提,再开始推理。

text
<instructions>
不要凭印象回答。按顺序执行:
1. 先运行 `npm ls <package>` 确认实际安装的版本
2. 再查阅该版本的文档确认 API 签名
3. 最后才开始设计方案

如果第 1、2 步无法完成,直接告诉我缺什么,不要继续推理。
</instructions>

七、Extended Thinking 与工具调用的配合

在 Agent 场景中,最优模式是:

text
思考 → 调工具 → 读结果 → 再思考 → 再调工具 → ... → 结论

而不是:

text
一次性想完所有步骤 → 一口气调 10 个工具 → 结论

理由:第一种模式中,每次思考都基于最新的真实信息;第二种模式中,第 10 个工具调用是基于第 0 步的假设决定的,中间任何一个意外都会让后续全部偏航。

在提示词中强化这一点:

text
<instructions>
每次只执行一个步骤,看到结果后再决定下一步。
不要预先规划超过两步的动作序列 —— 前一步的结果可能改变后续判断。
</instructions>

例外:互不依赖的操作应该并行执行以节省时间。

text
如果多个操作之间没有依赖关系(比如同时读三个不相关的文件),
在同一批次里并行执行,不要串行。

延伸阅读

基于 VitePress 构建 · 内容采用原作者授权