Claude 原生 Messages API 详解:与 OpenAI 格式的字段差异及迁移实战
·
Claude 原生 Messages API 详解:与 OpenAI 格式的字段差异及迁移实战
调用 Claude 有两套常见姿势:一套是走 OpenAI 兼容的 /v1/chat/completions,另一套是 Anthropic 自家的 /v1/messages(Messages API)。前者上手快,但部分原生能力(更细的 stop_reason、content blocks 等)只有原生格式表达得完整。这篇把两套格式的差异逐项过一遍,并演示迁移要改哪些地方。
1. 准备:一个能访问的入口
无论哪套格式,都需要一个调用地址(Base URL)和 API Key。这类入口有几种来源:官方接口、自建网关(如开源的 OneAPI),或第三方统一接入服务(如 OneAPI、聚合服务 等,按需自行实测)。不少网关两套格式都支持。下文统一用环境变量占位。
2. 关键差异对照
| 维度 | 原生 Messages API | OpenAI 兼容格式 |
|---|---|---|
| 端点 | /v1/messages |
/v1/chat/completions |
| 认证头 | x-api-key + anthropic-version |
Authorization: Bearer |
| system 提示 | 顶层 system 参数 |
messages 里 role: system |
max_tokens |
必填 | 选填 |
| 回复正文 | content 数组(content block) |
choices[0].message.content |
| 结束原因 | stop_reason(end_turn/max_tokens/tool_use) |
finish_reason(stop/length/tool_calls) |
最容易踩的是两条:原生接口 max_tokens 不传直接报 400;messages 里塞 role: system 会被原生接口拒绝。
3. 原生调用示例
import os, requests
url = os.getenv("BASE_URL", "YOUR_BASE_URL") + "/v1/messages"
headers = {
"x-api-key": os.getenv("API_KEY"),
"anthropic-version": "2023-06-01",
"content-type": "application/json",
}
payload = {
"model": "claude-sonnet-4-6",
"max_tokens": 1024, # 原生接口必填
"system": "你是一名严谨的代码审查助手",
"messages": [
{"role": "user", "content": "这段循环有没有越界风险:for(i=0;i<=n;i++) a[i]=0;"}
],
}
resp = requests.post(url, headers=headers, json=payload, timeout=60)
data = resp.json()
print(data["content"][0]["text"]) # 注意是 content 数组
print("stop_reason:", data["stop_reason"])
注意响应解析:原生格式的回复在 content[0]["text"],不是 choices[0].message.content。
4. 从 OpenAI 格式迁移:一个适配函数
迁移的核心就是两件事——把 system 消息抽到顶层、补上 max_tokens:
def openai_to_anthropic(messages, max_tokens=1024):
system = "\n".join(
m["content"] for m in messages if m["role"] == "system"
)
rest = [m for m in messages if m["role"] != "system"]
body = {"messages": rest, "max_tokens": max_tokens}
if system:
body["system"] = system
return body
把原有 OpenAI 风格的 messages 喂进去,返回值合并上 model 字段即可直接 POST 到 /v1/messages。
5. 怎么选
- 已有大量 OpenAI SDK 代码、只想换模型:继续用兼容格式,成本最低;
- 需要精确区分
tool_use、max_tokens等结束状态,或要用 content block 处理多段输出:用原生格式; - 两套混用也可以,用上面的适配函数收敛差异,解析层各写一份即可。
6. 排错速查
- 400 且提示 max_tokens:原生接口忘了传
max_tokens; - system 相关报错:检查是否把 system 塞进了 messages 数组;
- 401:确认用的是
x-api-key而不是Authorization头(原生格式); - KeyError: choices:拿原生响应按 OpenAI 结构解析了,改读
content数组。
两套格式本质只是「信封」不同,理解差异之后,迁移就是十几行适配代码的事。
更多推荐

所有评论(0)