什么是 thinking block
开启后,Claude 的 content 数组里会多一类 block:
{
"content": [
{
"type": "thinking",
"thinking": "让我梳理一下条件... 已知 A,B,C... 假设 X 则...",
"signature": "ErUBC..."
},
{
"type": "text",
"text": "最终答案是 42。"
}
]
}
应用层面通常只把 text block 显示给用户,thinking 当做"幕后草稿"——类似 o1 的 reasoning tokens,但 Claude 把原文给你,不是加密的。
开启 Thinking
const msg = await client.messages.create({ model: "claude-opus-4-7", max_tokens: 16000, thinking: { type: "enabled", budget_tokens: 10000, // thinking 最多花这么多 }, messages: [ { role: "user", content: "证明 √2 是无理数,再证明 √n(n 非完全平方数)也无理。" }, ], }); for (const block of msg.content) { if (block.type === "thinking") { console.log("[thinking]", block.thinking.slice(0, 100), "..."); } else if (block.type === "text") { console.log("[answer]", block.text); } }
支持矩阵
| 模型 | Extended Thinking | 典型 budget |
|---|---|---|
| Opus 4.x | ✅ 原生最佳 | 5000–30000 |
| Sonnet 4.x | ✅ 支持 | 2000–10000 |
| Haiku 4.x | ⚠️ 部分版本 | 不推荐 |
budget_tokens 规则
- 最小值:1024 tokens
- 必须 < max_tokens:因为 max_tokens 覆盖 thinking + output 全部
- 给太小:thinking 被截断,质量反而差
- 给太大:成本线性涨,并不一定更好——数学/代码题 10000 常够用
// ❌ 错误:budget > max_tokens max_tokens: 5000, thinking: { budget_tokens: 8000 }, // 400 Error // ✅ 正确:max_tokens 覆盖 thinking + text max_tokens: 16000, thinking: { budget_tokens: 10000 }, // 留 6000 给 text 输出
什么时候该开
经验清单:
Thinking 的成本
Thinking tokens 按 output 单价计费(不是 input)。也就是说开启 10000 budget:
Sonnet 4.x:10000 × $15/M = $0.15 (只是 thinking 那部分) Opus 4.x: 10000 × $75/M = $0.75
所以 Opus + Thinking 的组合,单次调用很容易 $1 以上——只在真需要高可靠推理时上。
Thinking + 流式响应
流式里 thinking block 会先出:
event: content_block_start type=thinking event: content_block_delta thinking_delta: "让我先..." event: content_block_delta thinking_delta: "考虑三种情况..." ... event: content_block_stop event: content_block_start type=text event: content_block_delta text_delta: "答案是..." ...
UI 建议:thinking 期间显示 "🧠 正在推理..." 指示,不要直接把草稿怼给用户看(会把他们搞晕)。推理完成后再把 text block 显示在聊天气泡。
Thinking + Tool Use
Agent 在决定调工具前可以先 thinking,然后直接出 tool_use block。回塞 tool_result 后的第二次调用,模型可以再来一次 thinking+tool 循环。
第 1 次: [thinking] "用户要订机票,我需要先查日期和目的地机场" [tool_use] search_flights(date="2026-05-10", dest="PEK") 第 2 次(你回塞 tool_result): [thinking] "有 3 个航班选项,按价格和时段筛,CA1234 最优" [text] "推荐 CA1234,..."
Thinking 上下文的保留
重要细节:把 assistant response 作为多轮历史回塞时,保留 thinking block—— Claude 需要它作为推理连续性参考。Signature 字段用于完整性验证,不能改。
// ✅ 正确:保留整个 content 数组,包括 thinking messages.push({ role: "assistant", content: resp.content }); // ❌ 错误:只取 text block messages.push({ role: "assistant", content: resp.content.filter((b) => b.type === "text"), });
Thinking 不能和这些一起
- temperature != 1——thinking 固定 temperature=1,你设别的被忽略
- top_p / top_k 不允许——开 thinking 时设了会 400
- stop_sequences 不允许——同上
- 续写 assistant(
"{"开头)不允许——thinking 模式不支持续写
何时 thinking 没帮助
不是所有任务都受益:
- 信息检索型问题(知识已在 context 里) —— thinking 往往无用
- 开放式创作(写诗、故事) —— 过度推理反而模板化
- 指令遵循型(格式化输出) —— 直接写更快更稳
测试方法:同样 prompt 各跑 20 次 thinking on/off,用 LLM-as-judge 打分。差 < 5% → 关掉,省钱。
实战:SQL 生成
const resp = await client.messages.create({ model: "claude-opus-4-7", max_tokens: 6000, thinking: { type: "enabled", budget_tokens: 4000 }, system: "你是 PostgreSQL 专家。", messages: [{ role: "user", content: `Schema: users(id, country, signup_at) orders(id, user_id, amount, created_at, status) 问题:过去 30 天里,哪些国家的 VIP 用户(月消费 > 10000)增长最快?用窗口函数,避免相关子查询。`, }], });
带 thinking 的 Claude 会先思考"我得定义 VIP → 连接 users/orders → 按国家分月分组 → 同比/环比 → 窗口函数 ORDER BY"——产出更可执行的 SQL。
实战:LeetCode hard
thinking: { type: "enabled", budget_tokens: 15000 },
// "给定 m×n 网格,权值可正可负,求从左上到右下的所有路径中
// 路径和为 0 的路径数,mod 1e9+7"
//
// thinking 里 Claude 会:
// 1. 分析:权值有负,不能简单 DP
// 2. 考虑 meet in the middle
// 3. 评估复杂度 2^(m+n) / 2,45 太大?
// 4. 改用从中点对角线切,哈希合并
// 5. 最后给代码
Thinking 监控
usage 里会多一个字段:
{
"usage": {
"input_tokens": 120,
"cache_read_input_tokens": 0,
"output_tokens": 500,
"thinking_tokens": 3842 // ← 新增
}
}
生产监控应该追踪 thinking_tokens / output_tokens 比例,识别"thinking 但没啥产出"的 case(通常任务选错了)。
本章小结
- Thinking = 模型先写草稿再写答案,content 里多一个 thinking block
budget_tokens ≥ 1024且< max_tokens- 数学/代码/规划显著受益;聊天/分类/翻译不开
- 成本按 output 单价计,Opus+Thinking 单次容易 $1+
- 和 temperature / top_p / stop_sequences / 续写不兼容
- 多轮时保留 thinking block在历史里不能删