主题
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
如果多个操作之间没有依赖关系(比如同时读三个不相关的文件),
在同一批次里并行执行,不要串行。