主流模型 API 格式
本章速查 OpenAI Chat Completions 与 Anthropic Messages 两大 API 的请求格式、参数与核心差异,以及工具调用闭环、流式响应、提示缓存、扩展思考等实战要点。现有国内外模型厂商基本都兼容这两种请求格式。
OpenAI (Chat Completions API)
请求地址: POST https://api.openai.com/v1/chat/completions
认证方式: Authorization: Bearer YOUR_API_KEY
Headers: content-type: application/json (必填)
{
// ========== 必填参数 ==========
"model": "gpt-4o",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "What is the weather like today?" }
],
// ========== 常用可选参数 ==========
"max_tokens": 1024,
"temperature": 0.7, // 0~2,默认 1
"top_p": 0.9, // 0~1,核采样
"n": 1,
"stream": false,
"stop": ["\n", "Human:"],
// ========== 多样性控制 ==========
"presence_penalty": 0, // -2.0~2.0,存在惩罚
"frequency_penalty": 0, // -2.0~2.0,频率惩罚
"logit_bias": {},
// ========== 工具/函数调用 ==========
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City and state" }
},
"required": ["location"]
}
}
}],
"tool_choice": "auto", // "auto" | "none" | "required" | 指定工具名
// ========== 元数据 ==========
"user": "user-12345" // 用户标识,勿包含 PII
}Anthropic (Messages API)
- URL:
POST https://api.anthropic.com/v1/messages - Headers:
x-api-key: YOUR_API_KEY(必填)anthropic-version: 2023-06-01(必填,日期版本)content-type: application/json(必填)
{
"model": "claude-sonnet-5-20251001",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "What is the weather like today?" }
],
"system": "You are a helpful assistant with a cheerful tone.",
"temperature": 0.7, // 0~1
"top_p": 0.9,
"top_k": 40,
"stop_sequences": ["\n\nHuman:", "\n\nAssistant:"],
"stream": false,
"tools": [{
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City and state" }
},
"required": ["location"]
}
}],
"tool_choice": { "type": "auto" },
"metadata": { "user_id": "user-12345" }
}必填字段
model(string): 模型名称,如"claude-sonnet-5-20251001"max_tokens(integer): 最大生成 token 数,不同模型有各自上限messages(array): 对话历史。每项含role("user"|"assistant")和content(字符串或内容块数组)
可选字段
| 字段 | 类型 | 说明 |
|---|---|---|
system |
string/array | 系统提示词,独立于 messages,设定角色与行为 |
temperature |
number | 0~1,控制随机性 |
top_p |
number | 核采样参数 |
top_k |
number | 只从概率最高的 K 个 token 中采样 |
stop_sequences |
string[] | 停止序列 |
stream |
boolean | 流式响应(SSE) |
tools |
array | 工具定义列表 |
tool_choice |
object | 工具选择策略 |
metadata.user_id |
string | 滥用检测标识,勿放 PII |
OpenAI vs Anthropic 核心差异
两者最大的不同在于设计哲学:OpenAI 的 Chat Completions API 定位是通用行业标准;Anthropic 的 Messages API 则是为充分发挥 Claude 模型原生能力而设计。
| 特性 | OpenAI | Anthropic |
|---|---|---|
| API 端点 | POST /v1/chat/completions |
POST /v1/messages |
| 认证方式 | Authorization: Bearer |
x-api-key |
| API 版本 | 模型名区分(如 gpt-4o) |
anthropic-version 头 |
| 系统提示 | role: "system" 消息 |
独立的 system 参数 |
| 角色 (Roles) | system, user, assistant, tool |
user, assistant |
| 工具定义 | tools + function 关键字 |
tools,字段更扁平 |
| 扩展思考 | 不支持 | 支持 (thinking 参数) |
| 提示缓存 | 不支持(2025 年部分支持) | 支持 (cache_control 参数) |
| 采样参数 | temperature: 0top_p: 0presence_penalty/frequency_penalty |
temperature: 0top_p: 0top_k: 正整数 |
| 状态管理 | 无状态 | 无状态 |
stop_reason / finish_reason 对照
Agent Loop 的控制流由这个字段驱动(详见 05-Agent-Loop与工具调用):
| 场景 | OpenAI finish_reason |
Anthropic stop_reason |
|---|---|---|
| 正常回答完毕 | stop |
end_turn |
| 达到 max_tokens 被截断 | length |
max_tokens |
| 模型请求调用工具 | tool_calls |
tool_use |
| 命中停止序列 | stop(含 stop 字段) |
stop_sequence |
工具调用完整闭环
工具调用不是一次请求,而是两次以上请求组成的闭环:模型返回"我要调工具" → 你执行 → 把结果塞回 messages 再次请求。
Anthropic 流程
① 请求:messages + tools
② 响应:stop_reason == "tool_use"
content: [
{ "type": "text", "text": "我来查一下天气" },
{ "type": "tool_use", "id": "toolu_01A...", "name": "get_weather",
"input": { "location": "Beijing" } }
]
③ 执行工具,将结果以 user 消息追加:
{ "role": "user", "content": [
{ "type": "tool_result", "tool_use_id": "toolu_01A...",
"content": "晴,32°C", "is_error": false }
]}
④ 再次请求 → 模型基于工具结果生成最终回答(stop_reason == "end_turn")OpenAI 流程
① 请求:messages + tools
② 响应:finish_reason == "tool_calls"
message.tool_calls: [
{ "id": "call_abc", "type": "function",
"function": { "name": "get_weather",
"arguments": "{\"location\": \"Beijing\"}" } } // ⚠️ JSON 字符串
]
③ 执行工具,以 role: "tool" 消息追加:
{ "role": "tool", "tool_call_id": "call_abc", "content": "晴,32°C" }
④ 再次请求 → 最终回答两者关键差异
| 差异点 | OpenAI | Anthropic |
|---|---|---|
| 工具参数格式 | arguments 是 JSON 字符串,需 json.loads() 解析 |
input 是已解析的对象 |
| 结果回传角色 | 独立的 role: "tool" 消息 |
role: "user" 中的 tool_result 内容块 |
| 结果与调用的对应 | tool_call_id |
tool_use_id |
| 错误上报 | 无专用字段,写入 content | is_error: true |
🚨 陷阱:模型可能在一次响应中发起多个并行工具调用。必须为每一个
tool_use/tool_call都返回对应 id 的结果,缺一个都会导致 API 报错。Anthropic 还要求tool_result块位于下一条 user 消息 content 的最前面。
流式响应 (Streaming / SSE)
设置 "stream": true 后,响应以 Server-Sent Events 逐块推送,用于降低首字延迟(TTFT)。
OpenAI
每个事件是一行 data: {...},增量在 choices[0].delta 中,结束标志是 data: [DONE]:
data: {"choices":[{"delta":{"role":"assistant","content":""}}]}
data: {"choices":[{"delta":{"content":"你好"}}]}
data: {"choices":[{"delta":{},"finish_reason":"stop"}]}
data: [DONE]Anthropic
事件有显式类型,结构化程度更高:
event: message_start → 消息元数据(model、usage.input_tokens)
event: content_block_start → 一个内容块开始(text / tool_use / thinking)
event: content_block_delta → 增量内容:
text_delta → 文本增量
input_json_delta → 工具参数的 JSON 片段(partial_json)
event: content_block_stop → 内容块结束
event: message_delta → stop_reason、usage.output_tokens
event: message_stop → 消息结束🚨 陷阱:流式模式下工具调用参数以
input_json_delta的partial_json碎片形式到达,必须累积拼接到content_block_stop后才能解析,中途的碎片不是合法 JSON。SDK(如client.messages.stream())已封装了这个累积逻辑,优先使用 SDK。
提示缓存 (Prompt Caching)
Anthropic 通过 cache_control 显式标记缓存断点,命中缓存的前缀部分按大幅折扣计费:
{
"system": [
{ "type": "text", "text": "<几万 token 的长文档/工具定义>",
"cache_control": { "type": "ephemeral" } }
]
}- 前缀匹配:缓存按
tools → system → messages的顺序对前缀生效,断点之前的任何改动都会导致缓存失效 - 计费:缓存写入约为正常输入价格的 1.25 倍,缓存读取约为 0.1 倍——多轮 Agent 对话下收益巨大
- TTL:默认约 5 分钟(每次命中会刷新),有更长 TTL 的选项
- 最小长度:过短的前缀(约 1024 token 以下)不会被缓存
💡 Agent 场景最佳实践:把稳定不变的部分(系统提示、工具定义、参考文档)放在最前面并打上缓存断点;把每轮变化的对话历史放在后面。Agent Loop 每轮都携带全量历史,缓存能把成本降一个数量级。
扩展思考 (Extended Thinking)
Claude 支持在正式回答前输出内部推理链:
{
"model": "claude-sonnet-5-20251001",
"max_tokens": 16000,
"thinking": { "type": "enabled", "budget_tokens": 8000 },
"messages": [...]
}- 响应 content 中会出现
thinking类型的内容块,之后才是text/tool_use budget_tokens是思考的 token 预算上限,计入max_tokens- 多轮工具调用时,需要把上一轮的
thinking块原样传回(不可篡改),供模型延续推理
常见陷阱
- 🚨 OpenAI 的
arguments是 JSON 字符串:直接当对象用会报错,必须先解析;且模型偶尔会生成不合法 JSON,要有解析失败的兜底 - 🚨
max_tokens截断工具调用:stop_reason == "max_tokens"时tool_use的 input 可能是残缺 JSON,不能执行,应提高 max_tokens 重试 - 🚨 温度范围不同:OpenAI 是 0
2,Anthropic 是 01。跨厂商迁移时直接搬temperature: 1.5会报参数错误 - 🚨 Anthropic 的 messages 必须以
user开头,且 system 提示不能放在 messages 里(有独立的system参数) - 🚨 两个 API 都是无状态的:服务端不保存对话历史,每次请求都要携带全量 messages——这正是 Agent 需要上下文工程的原因
- 💡 用
usage字段做成本监控:每个响应都带 input/output token 计数,Agent Loop 中累计它,配合预算上限防止失控