我们已针对 Claude 系列模型升级了与 OpenAI 兼容的接口,进行了更深层次的优化。您现在可以更精确和方便地控制思维和缓存。在多轮对话中,交错思维变得更加用户友好,允许无缝集成而无需额外参数。它还支持启用 Anthropic 提供的测试功能。
1. 模型思维(扩展思维)
1.1 交错思维的优势
当未启用交错思维时,模型仅在助手轮次开始时进行一次思维;后续响应在接收到工具结果后直接生成,而不会产生新的思维块:
User → [Thinking] → Tool Call → Tool Result → Response
当启用交错思维时,模型在每次接收到工具结果时插入一个新的思维块,形成推理链:
User → [Thinking] → Tool Call → Tool Result → [Thinking] → Response
↑ 交错思维
这使得模型能够:
- 基于工具结果进行二次推理,而不仅仅是简单地连接输出。
- 在多个工具调用之间进行推理链,每个决策基于对前一步的分析。
参考: Anthropic 交错思维
1.2 启用思维
您可以通过四种方式启用思维,选择其中任何一种:
| 方法 | 示例 | 描述 |
|---|---|---|
reasoning_effort |
"reasoning_effort": "low" |
OpenAI 标准参数,放置在请求体的顶层 |
reasoning.effort |
"reasoning": {"effort": "low"} |
等同于前一种方法,放置在推理对象内 |
reasoning.max_tokens |
"reasoning": {"max_tokens": 1024} |
精确控制思维的最大令牌数 |
模型名称加 -think |
"model": "claude-sonnet-4-5-think" |
最简单的方法,无需额外参数 |
优先级(当使用多种方法时):reasoning_effort>reasoning.max_tokens>reasoning.effort>-think后缀
努力的可能值: minimal / low / medium / high / xhigh
1.3 思维返回
响应消息将包含两个新字段:
reasoning_content:思维内容(字符串),便于显示。reasoning_details:关于思维的完整结构化信息,在多轮对话中需要按原样返回;内部结构可能因提供者而异。
非流式示例(省略不相关字段):
{
"choices": [{
"message": {
"role": "assistant",
"content": "你好!今天我能帮你什么?",
"reasoning_content": "用户只是打招呼...",
"reasoning_details": {
"type": "thinking",
"thinking": "用户只是打招呼...",
"signature": "Er8CCkYI..."
}
}
}]
}
在流式响应中,思维内容将通过 delta.reasoning_content 和 delta.reasoning_details 分块发送。有关完整的流式连接逻辑,请参阅下面的完整示例。
1.4 在多轮对话中保留思维 (交错思维是内置的,无需额外参数)
要使模型在多轮对话中继续其推理能力,只需将之前返回的 reasoning_details 按原样 放入下一轮的助手消息中:
messages = [
{"role": "user", "content": "波士顿的天气怎么样?"},
{
"role": "assistant",
"content": response.choices[0].message.content,
"tool_calls": response.choices[0].message.tool_calls,
"reasoning_details": response.choices[0].message.reasoning_details,
},
{
"role": "tool",
"tool_call_id": "toolu_xxx",
"content": '{"temperature": 45, "condition": "rainy"}',
}
]
AIHubMix 将在检测到请求中的历史思维信息时自动启用交错思维,使模型在接收到工具调用结果后继续进行深度推理,而无需额外参数。
1.5 完整示例
以下两个示例演示了完整的多轮工具调用 + 交错思维过程:用户询问 → 模型思考并调用工具 → 注入工具结果(保留 reasoning_details) → 模型交错思维给出最终响应。
非流式 · 交错思维
import os
import json
from openai import OpenAI
client = OpenAI(
base_url="https://aihubmix.com/v1",
api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)
# ── 工具定义 ───────────────────────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取某个地点的当前天气",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "城市名称"}},
"required": ["location"]
}
}
}]
# ── 模拟工具执行 ───────────────────────────────────────
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sunny", "humidity": "45%", "wind": "5 mph S"},
}
def execute_tool(name: str, args: dict) -> str:
if name == "get_weather":
key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "clear"}))
return "{}"
# ── 多轮对话循环 ─────────────────────────────
messages = [
{"role": "user", "content": "波士顿的天气怎么样?然后推荐穿什么。"}
]
turn = 0
while True:
turn += 1
print(f"\n── 第 {turn} 轮 ──")
response = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
msg = response.choices[0].message
# 打印思维过程
if msg.reasoning_content:
label = "交错思维" if turn > 1 else "思维"
print(f"[{label}] {msg.reasoning_content}")
# 打印响应内容
if msg.content:
print(f"[响应] {msg.content}")
# 打印工具调用
if msg.tool_calls:
for tc in msg.tool_calls:
print(f"[工具调用: {tc.function.name}] {tc.function.arguments}")
# 构建助手消息,保留 reasoning_details(关键!)
assistant_msg = {"role": "assistant", "content": msg.content}
if msg.tool_calls:
assistant_msg["tool_calls"] = msg.tool_calls
if msg.reasoning_details:
assistant_msg["reasoning_details"] = msg.reasoning_details # 不修改地传回
messages.append(assistant_msg)
# 没有工具调用意味着对话结束
if not msg.tool_calls:
break
# 执行工具并将结果附加到消息中
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
result = execute_tool(tc.function.name, args)
print(f"[工具结果: {tc.function.name}] {result}")
messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
流式 · 交错思维
import os
import sys
import json
from openai import OpenAI
client = OpenAI(
base_url="https://aihubmix.com/v1",
api_key=os.environ.get("AIHUBMIX_API_KEY", "sk-***"),
)
# ── 工具定义与模拟执行 ─────────────────────────
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取某个地点的当前天气",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "城市名称"}},
"required": ["location"]
}
}
}]
WEATHER_DB = {
"boston": {"temperature": "45°F (7°C)", "condition": "rainy", "humidity": "85%", "wind": "15 mph NE"},
"tokyo": {"temperature": "72°F (22°C)", "condition": "sunny", "humidity": "45%", "wind": "5 mph S"},
}
def execute_tool(name: str, args: dict) -> str:
if name == "get_weather":
key = next((k for k in WEATHER_DB if k in args.get("location", "").lower()), None)
return json.dumps(WEATHER_DB.get(key, {"temperature": "65°F", "condition": "clear"}))
return "{}"
# ── 流式响应收集器 ────────────────────────────────
def stream_and_collect(turn: int, **kwargs):
"""流式响应,实时打印思维/内容,累积 reasoning_details/tool_calls。"""
rd = {} # 累积的 reasoning_details
content = "" # 累积的响应文本
tc_map = {} # 累积的 tool_calls(按索引)
cur = "none" # 当前输出部分:none / thinking / content
stream = client.chat.completions.create(stream=True, **kwargs)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
# ── 处理思维 ──
rd_delta = getattr(delta, "reasoning_details", None)
if rd_delta and isinstance(rd_delta, dict):
for k, v in rd_delta.items():
if k == "type":
rd[k] = v
elif isinstance(v, str):
rd[k] = rd.get(k, "") + v
elif v is not None:
rd[k] = v
# 实时打印思维块
thinking_chunk = rd_delta.get("thinking", "")
if thinking_chunk:
if cur != "thinking":
cur = "thinking"
label = "交错思维" if turn > 1 else "思维"
sys.stdout.write(f"\n[{label}] ")
sys.stdout.write(thinking_chunk)
sys.stdout.flush()
# ── 处理内容 ──
if delta.content:
if cur != "content":
if cur == "thinking":
sys.stdout.write("\n")
cur = "content"
sys.stdout.write("\n[响应] ")
sys.stdout.write(delta.content)
sys.stdout.flush()
content += delta.content
# ── 处理工具调用 ──
for tc in delta.tool_calls or []:
i = tc.index
if i not in tc_map:
tc_map[i] = {"id": "", "type": "function",
"function": {"name": "", "arguments": ""}}
if tc.id:
tc_map[i]["id"] = tc.id
if tc.function:
tc_map[i]["function"]["name"] += tc.function.name or ""
tc_map[i]["function"]["arguments"] += tc.function.arguments or ""
# 结束当前输出部分
if cur in ("thinking", "content"):
sys.stdout.write("\n")
tool_calls = [tc_map[i] for i in sorted(tc_map)] if tc_map else None
return {
"content": content or None,
"reasoning_details": rd or None,
"tool_calls": tool_calls,
}
# ── 多轮对话循环 ─────────────────────────────
messages = [
{"role": "user", "content": "波士顿的天气怎么样?然后推荐穿什么。"}
]
turn = 0
while True:
turn += 1
print(f"\n── 第 {turn} 轮 ──")
result = stream_and_collect(
turn,
model="claude-sonnet-4-5",
messages=messages,
tools=tools,
extra_body={"reasoning": {"max_tokens": 2000}},
)
# 打印工具调用
if result["tool_calls"]:
for tc in result["tool_calls"]:
print(f"[工具调用: {tc['function']['name']}] {tc['function']['arguments']}")
# 构建助手消息,保留 reasoning_details(关键!)
assistant_msg = {"role": "assistant", "content": result["content"]}
if result["tool_calls"]:
assistant_msg["tool_calls"] = result["tool_calls"]
if result["reasoning_details"]:
assistant_msg["reasoning_details"] = result["reasoning_details"] # 不修改地传回
messages.append(assistant_msg)
# 没有工具调用意味着对话结束
if not result["tool_calls"]:
break
# 执行工具并将结果附加到消息中
for tc in result["tool_calls"]:
args = json.loads(tc["function"]["arguments"])
tool_result = execute_tool(tc["function"]["name"], args)
print(f"[工具结果: {tc['function']['name']}] {tool_result}")
messages.append({"role": "tool", "tool_call_id": tc["id"], "content": tool_result})
1.6 思维强度映射规则
努力模式:
- Opus 4.6 / Sonnet 4.6 及以上:映射到 Anthropic 的原生 自适应思维 努力级别。
- 其他模型:使用
budget_tokens的公式计算:
budget_tokens = max(min(max_tokens × effort_ratio, 128000), 1024)
| 努力 | 努力比例 |
|---|---|
| xhigh | 0.95 |
| high | 0.80 |
| medium | 0.50 |
| low | 0.20 |
| minimal | 0.10 |
自适应思维努力映射:
| 传入努力 | Opus 4.6 | Sonnet 4.6 |
|---|---|---|
| xhigh | max | high |
| high | high | high |
| medium | medium | medium |
| low | low | low |
| minimal | low | low |
max_tokens 模式: 直接分配为 Anthropic 的 budget_tokens。
-think 后缀: Opus/Sonnet 4.6+ 使用自适应思维(努力=中等);其他模型设置 budget_tokens = min(10240, max_tokens - 1),默认 max_tokens 为 4096。
2. 提示缓存
您可以在通过聊天接口向 Claude 模型发出请求时使用提示缓存。通过在消息中设置 cache_control 断点,可以缓存大块文本(如角色卡、RAG 数据、书籍章节等)以供重用,从而使后续请求直接命中缓存并显著降低成本。
Claude 官方文档: 提示缓存
2.1 缓存成本
| 操作 | 价格乘数(相对于原始输入价格) |
|---|---|
| 缓存写入(5分钟 TTL) | 1.25x |
| 缓存写入(1小时 TTL) | 2x |
| 缓存读取 | 0.1x |
2.2 支持的模型和最小缓存长度
| 模型 | 最小缓存令牌数 |
|---|---|
| Claude Opus 4.8 | 1024 |
| Claude Opus 4.7 | 2048 |
| Claude Opus 4.6 / Opus 4.5 | 4096 |
| Claude Sonnet 4.6 / Sonnet 4.5 / Opus 4.1 / Opus 4 / Sonnet 4 / Sonnet 3.7(已弃用) | 1024 |
| Claude Haiku 4.5 | 4096 |
| Claude Haiku 3.5(已弃用) / Haiku 3 | 2048 |
断点数量限制: 每个请求最多 4 个 cache_control 断点。2.3 缓存 TTL
| TTL | 语法 | 适用场景 |
|---|---|---|
| 5分钟(默认) | "cache_control": {"type": "ephemeral"} |
短会话,常规请求 |
| 1小时 | "cache_control": {"type": "ephemeral", "ttl": "1h"} |
长会话,避免重复缓存写入 |
1小时 TTL 的写入成本较高,但通过减少长会话中的重复写入可以节省总费用。所有来自 Claude 4.5 及以上版本的模型(包括 Anthropic、Amazon Bedrock、Google Vertex AI)都支持 1小时 TTL。
2.4 使用
您可以在 system、user(包括图像)和 tools 中使用 cache_control 字段设置缓存断点。以下示例仅显示关键结构,省略大块文本。
系统消息缓存(默认 5分钟 TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "您是一个 AI 助手"},
{
"type": "text",
"text": "(长上下文)",
"cache_control": {"type": "ephemeral"}
}
]
},
{
"role": "user",
"content": [{"type": "text", "text": "你好"}]
}
]
}
用户消息缓存(1小时 TTL):
{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [{"type": "text", "text": "您是一个 AI 助手"}]
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "(长上下文)",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
},
{"type": "text", "text": "你好"}
]
}
]
}
图像消息缓存:
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"detail": "auto", "url": "data:image/jpeg;base64,/9j/4AAQ..."},
"cache_control": {"type": "ephemeral"}
},
{"type": "text", "text": "这是什么?"}
]
}
工具定义缓存:
cache_control 放置在工具对象的顶层(与 type 和 function 并列):
{
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取某个地点的当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
},
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
}
2.5 查看缓存状态
响应的 usage 将返回 claude_cache_tokens_details,记录详细的缓存信息:
第一次请求(创建缓存):
{
"usage": {
"prompt_tokens": 22,
"completion_tokens": 890,
"total_tokens": 912,
"claude_cache_tokens_details": {
"cache_creation_input_tokens": 6266,
"cache_read_input_tokens": 0,
"cache_write_5_minutes_input_tokens": 6266,
"cache_write_1_hour_input_tokens": 0
}
}
}
后续请求(缓存命中):
{
"usage": {
"prompt_tokens": 22,
"completion_tokens": 810,
"total_tokens": 832,
"prompt_tokens_details": {
"cached_tokens": 6266
},
"claude_cache_tokens_details": {
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 6266,
"cache_write_5_minutes_input_tokens": 0,
"cache_write_1小时_input_tokens": 0
}
}
}
| 字段 | 含义 |
|---|---|
cache_creation_input_tokens |
在此请求中写入缓存的令牌数 |
cache_read_input_tokens |
在此请求中从缓存读取的令牌数 |
cache_write_5_minutes_input_tokens |
写入 5分钟 TTL 缓存的令牌数 |
cache_write_1_hour_input_tokens |
写入 1小时 TTL 缓存的令牌数 |
prompt_tokens_details.cached_tokens |
缓存命中时的令牌数,兼容 OpenAI 格式 |
3. 请求头用于 anthropic-beta
您可以通过 HTTP 头 anthropic-beta 启用 Claude 模型的测试功能,AIHubMix 将把其传递给 Anthropic API。
用法
在请求头中添加 anthropic-beta,值为相应的测试功能标识符:
curl "https://aihubmix.com/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AIHUBMIX_API_KEY" \
-H "anthropic-beta: context-1m-2025-08-07" \
-d '{
"model": "claude-opus-4-5",
"messages": [
{
"role": "system",
"content": [
{"type": "text", "text": "您是一个 AI 助手"},
{
"type": "text",
"text": "(长上下文)",
"cache_control": {"type": "ephemeral"}
}
]
},
{"role": "user", "content": [{"type": "text", "text": "你好"}]}
]
}'
有关具体可用的测试标识符,请参阅 Anthropic API 文档。
最后更新:2026-06-01