Extended Thinking 实战指南:Opus 4.7 时代该怎么用思考预算
大多数关于 Extended Thinking 的中文资料还在教
thinking: {type: "enabled", budget_tokens: 10000}——这套写法在 Opus 4.7 上直接报错。本文按 2026-05 的实际 API 行为给出 4.7 / 4.6 / Sonnet 4.6 三个模型的正确用法,附 effort 选型表、interleaved thinking 在 tool loop 里的完整闭环、以及最容易踩的两个 prompt caching 坑。
一、半年里 thinking 接口换了一次写法
如果你的代码库里还有这样的调用:
response = client.messages.create(
model="claude-opus-4-7", # 这一行
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000}, # 这一行
messages=[...]
)
response = client.messages.create(
model="claude-opus-4-7", # 这一行
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000}, # 这一行
messages=[...]
)
把 model 改成 Opus 4.7 之后,整个请求会失败。原因是 Anthropic 在 4.6/4.7 这一代把 thinking 接口从"显式预算"切到了"adaptive + effort"——4.7 已经不再接受老写法。
变更摘要:
| 模型 | 老写法(type: enabled + budget_tokens) |
新写法(type: adaptive + effort) |
|---|---|---|
| Opus 4.7 | ❌ 不再接受 | ✅ 唯一支持的方式 |
| Opus 4.6 | ⚠️ 仍可用但已 deprecated | ✅ 推荐 |
| Sonnet 4.6 | ⚠️ 仍可用但已 deprecated | ✅ 推荐 |
| Sonnet 4.6 + tool 间思考 | 需要 interleaved-thinking-2025-05-14 beta header |
adaptive 模式自动启用 |
这意味着如果你打算把 Opus 4.7 接进现有 agent 链路,第一步就是把 thinking 配置改成 adaptive——而不是简单地换模型 ID。
二、adaptive thinking 是什么
老写法的设计是:你告诉模型"最多花 10000 token 思考"。模型可能用满,也可能只用一部分。问题在于:
- 简单问题被强制思考浪费 token
- 复杂问题如果设小了又思考不够

adaptive thinking 把这个判断权交给模型,由 effort 参数控制激进程度:
| effort | 行为 | 适用场景 |
|---|---|---|
low |
简单问题模型常常完全跳过思考 | 低成本、低延迟的轻量调用 |
medium |
平衡——只在判断有必要时思考 | 一般生产任务 |
high(默认) |
几乎总会先思考 | 生产环境的推理任务 |
max(仅 Opus 4.6/4.7) |
最大思考强度 | AIME 级数学、长链路 agent、最难的 bug |
Anthropic 的内部评测显示:在大量任务上 adaptive 的 token 利用率优于固定 budget——因为它不会在简单题上浪费推理,也不会在难题上提前收手。
三、完整调用代码(Python)
环境准备:
pip install anthropic
pip install anthropic
3.1 Opus 4.7 调用(唯一支持 adaptive)
import anthropic
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com"
)
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[
{"role": "user", "content": "证明:模 4 余 3 的素数有无穷多个。"}
]
)
for block in response.content:
if block.type == "thinking":
print(f"[思考] {block.thinking[:200]}...")
elif block.type == "text":
print(f"[答案] {block.text}")
import anthropic
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com"
)
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[
{"role": "user", "content": "证明:模 4 余 3 的素数有无穷多个。"}
]
)
for block in response.content:
if block.type == "thinking":
print(f"[思考] {block.thinking[:200]}...")
elif block.type == "text":
print(f"[答案] {block.text}")
返回的 content 是按顺序排列的 block 数组:先一个 thinking block(包含模型的推理过程摘要),再一个 text block(最终答案)。
3.2 在 Sonnet 4.6 上同样的写法
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "medium"}, # Sonnet 不支持 max
messages=[{"role": "user", "content": "..."}]
)
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "medium"}, # Sonnet 不支持 max
messages=[{"role": "user", "content": "..."}]
)
注意:Sonnet 4.6 上 effort: max 不被接受——max 是 Opus 系列独占的。日常生产用 medium,关键推理才上 high。
3.3 Opus 4.6 上的两种写法都能用,但应该用 adaptive
# ✅ 推荐
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[...]
)
# ⚠️ 仍可工作但已 deprecated,建议尽快迁移
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
messages=[...]
)
# ✅ 推荐
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
messages=[...]
)
# ⚠️ 仍可工作但已 deprecated,建议尽快迁移
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
messages=[...]
)
四、Node.js / TypeScript 版本
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "sk-你的ClaudeAPI密钥",
baseURL: "https://gw.claudeapi.com",
});
const response = await client.messages.create({
model: "claude-opus-4-7",
max_tokens: 16000,
thinking: { type: "adaptive" },
output_config: { effort: "high" },
messages: [{ role: "user", content: "你的复杂推理任务" }],
});
for (const block of response.content) {
if (block.type === "thinking") {
console.log("[思考]", block.thinking);
} else if (block.type === "text") {
console.log("[答案]", block.text);
}
}
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "sk-你的ClaudeAPI密钥",
baseURL: "https://gw.claudeapi.com",
});
const response = await client.messages.create({
model: "claude-opus-4-7",
max_tokens: 16000,
thinking: { type: "adaptive" },
output_config: { effort: "high" },
messages: [{ role: "user", content: "你的复杂推理任务" }],
});
for (const block of response.content) {
if (block.type === "thinking") {
console.log("[思考]", block.thinking);
} else if (block.type === "text") {
console.log("[答案]", block.text);
}
}
五、interleaved thinking:tool 循环里的关键变化
Extended Thinking 在 agent 场景下真正强大的地方,是允许模型在每次调用 tool 后再思考一轮——也就是 interleaved thinking。
老写法在 Sonnet 4.6 上要手动加 beta header:
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "interleaved-thinking-2025-05-14"}
)
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "interleaved-thinking-2025-05-14"}
)
Opus 4.7 和 4.6 的 adaptive 模式下,interleaved thinking 默认就开,不需要任何 beta header。这是迁移到 4.7 的一个隐藏收益——agent 链路里不再需要管 thinking 旗子。
完整 tool-use 循环(关键点:上一轮的 thinking block 必须原样回填):
weather_tool = {
"name": "get_weather",
"description": "获取指定城市的实时天气",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
# 第一轮:模型先思考再决定调 tool
response_1 = client.messages.create(
model="claude-opus-4-7",
max_tokens=8000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
tools=[weather_tool],
messages=[
{"role": "user", "content": "巴黎现在适合穿什么?给出具体建议。"}
]
)
# 第二轮:把 thinking block + tool_use block 原样回填,加 tool_result
thinking_block = next(b for b in response_1.content if b.type == "thinking")
tool_use_block = next(b for b in response_1.content if b.type == "tool_use")
response_2 = client.messages.create(
model="claude-opus-4-7",
max_tokens=8000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
tools=[weather_tool],
messages=[
{"role": "user", "content": "巴黎现在适合穿什么?给出具体建议。"},
{
"role": "assistant",
"content": [thinking_block, tool_use_block] # ← 关键
},
{
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_use_block.id,
"content": "巴黎 22°C,晴,微风。"
}]
}
]
)
weather_tool = {
"name": "get_weather",
"description": "获取指定城市的实时天气",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
# 第一轮:模型先思考再决定调 tool
response_1 = client.messages.create(
model="claude-opus-4-7",
max_tokens=8000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
tools=[weather_tool],
messages=[
{"role": "user", "content": "巴黎现在适合穿什么?给出具体建议。"}
]
)
# 第二轮:把 thinking block + tool_use block 原样回填,加 tool_result
thinking_block = next(b for b in response_1.content if b.type == "thinking")
tool_use_block = next(b for b in response_1.content if b.type == "tool_use")
response_2 = client.messages.create(
model="claude-opus-4-7",
max_tokens=8000,
thinking={"type": "adaptive"},
output_config={"effort": "high"},
tools=[weather_tool],
messages=[
{"role": "user", "content": "巴黎现在适合穿什么?给出具体建议。"},
{
"role": "assistant",
"content": [thinking_block, tool_use_block] # ← 关键
},
{
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_use_block.id,
"content": "巴黎 22°C,晴,微风。"
}]
}
]
)
没回填 thinking block 的后果:模型会"失忆",把刚才的推理过程丢掉,第二轮决策质量明显下降。这是接 agent 链路时最常踩的坑。
六、effort 选型:到底用哪一档
按业务任务类型选,不要默认 high:
| 任务 | 推荐 effort | 模型 | 备注 |
|---|---|---|---|
| 简单分类、信息抽取 | low 或不开 thinking |
Haiku 4.5 / Sonnet 4.6 | 开 thinking 反而加成本与延迟 |
| 常规问答、文档生成 | medium |
Sonnet 4.6 | 性价比甜点 |
| 代码 review、PR 分析 | medium 或 high |
Sonnet 4.6 / Opus 4.6 | 多步推理但不至于 max |
| 复杂算法、架构设计 | high |
Opus 4.7 | 需要长链条思考 |
| AIME 级数学、最难的 debug | max |
Opus 4.7 / 4.6 | 极限场景,单次成本明显上升 |
一个有用的经验法则:开 thinking 之前先用普通模式跑一遍,如果普通模式答得不错,就不开;如果普通模式有明显问题(漏了约束、逻辑跳步、答非所问),再上 thinking。盲目默认 high 是 Uber 月人均 $2000 账单的成因之一。
七、容易踩的坑
坑 1:thinking 与 prompt caching 的隐藏耦合
prompt caching 的 cache key 包含 thinking 配置。这意味着:
# 第一次:建缓存
client.messages.create(
...,
thinking={"type": "adaptive"},
output_config={"effort": "medium"},
system=[{"type": "text", "text": LONG_SYSTEM, "cache_control": {"type": "ephemeral"}}],
...
)
# 第二次:把 effort 改成 high → 缓存失效,重新计费
client.messages.create(
...,
thinking={"type": "adaptive"},
output_config={"effort": "high"}, # 改了
system=[{"type": "text", "text": LONG_SYSTEM, "cache_control": {"type": "ephemeral"}}],
...
)
# 第一次:建缓存
client.messages.create(
...,
thinking={"type": "adaptive"},
output_config={"effort": "medium"},
system=[{"type": "text", "text": LONG_SYSTEM, "cache_control": {"type": "ephemeral"}}],
...
)
# 第二次:把 effort 改成 high → 缓存失效,重新计费
client.messages.create(
...,
thinking={"type": "adaptive"},
output_config={"effort": "high"}, # 改了
system=[{"type": "text", "text": LONG_SYSTEM, "cache_control": {"type": "ephemeral"}}],
...
)
实战建议:同一条工作流内 effort 固定,不要在 A/B 测试时改 effort 又指望 cache 命中。
坑 2:thinking block 不会跨轮保留
模型每次返回 thinking block,但在下一轮请求时这些 block 默认不在上下文里——除非你像第五节那样手动回填。多轮对话场景里如果忽略这点,模型会反复"重新思考一遍"已经想过的事,token 浪费严重。
坑 3:thinking 计费是全过程,不是可见摘要
你拿到的 block.thinking 是模型自己生成的思考摘要——但计费按完整内部思考过程,可能是摘要的 3-5 倍。一个看起来 200 字的 thinking block,背后可能消耗了 5000 token。月底账单和你看屏幕估算的不一样,原因常常在这里。
坑 4:thinking 与几个采样参数互斥
开启 thinking 时不能用:
temperature≠ 1 或top_ktop_p< 0.95- forced tool use(
tool_choice指定具体工具名) - response prefill(用 assistant 消息预填模型回复)
如果原代码里有这些参数,迁移到 thinking 时要先拿掉。
八、对照 checklist:从老代码迁移到 adaptive
代码层:
- [ ] 把
thinking: {"type": "enabled", "budget_tokens": N}改成thinking: {"type": "adaptive"} - [ ] 加上
output_config: {"effort": "..."},按上表选档 - [ ] 移除
interleaved-thinking-2025-05-14beta header(adaptive 自动开) - [ ] 检查
temperature、top_k、tool_choice、prefill 是否与 thinking 冲突
工程层:
- [ ] 多轮对话的 thinking block 回填逻辑
- [ ] prompt caching 的 effort 一致性
- [ ] 账单告警:把 thinking token 与可见输出 token 分开监控
测试层:
- [ ] 同一个 prompt 在 effort: low / medium / high 三档下跑一遍,记录质量与 token 消耗
- [ ] agent 链路:tool_result 回填后第二轮 thinking 是否仍然合理
九、小结
做对一件事就够了:默认用 adaptive,按任务类型选 effort,不要一上来就 high。
claudeapi.com 提供 Claude Opus 4.7、Opus 4.6、Sonnet 4.6、Haiku 4.5 完整能力,兼容 Anthropic SDK 格式,仅需替换 base_url 即可平滑接入现有项目。控制台支持按 API Key 维度查看 thinking token 与普通 token 的分项消耗,定位"思考太狠"问题更直接。
立即体验:claudeapi.com · 完整模型与定价见 console.claudeapi.com。



