惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
Netflix TechBlog - Medium
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
V
V2EX
IT之家
IT之家
J
Java Code Geeks
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
GbyAI
GbyAI
D
Docker
S
Secure Thoughts
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
云风的 BLOG
云风的 BLOG
博客园_首页
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Security Archives - TechRepublic
Security Archives - TechRepublic
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
N
News | PayPal Newsroom
S
Security @ Cisco Blogs
I
InfoQ
Last Week in AI
Last Week in AI
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
W
WeLiveSecurity
T
Troy Hunt's Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Attack and Defense Labs
Attack and Defense Labs
美团技术团队
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Scott Helme
Scott Helme
T
Tor Project blog
Know Your Adversary
Know Your Adversary
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
Recorded Future
Recorded Future
C
Cyber Attacks, Cyber Crime and Cyber Security
AI
AI
G
Google Developers Blog

博客园 - 冯叶青

GitHub Actions 自动部署流程 Git分支自动合并脚本:基于时间戳的冲突解决方案 Next.js lingui.js 多语言自动提取翻译键 - ats-node React实现短信验证码输入组件 Next.js 中优雅地使用 Lottie 动画 Next.js 路由参数更新最佳实践:从 replaceState 到 nextReplaceState Jenkins构建时SWR模块导入报错解决方案 解决 Jenkins 环境下 Lingui 构建报错 "btoa is not defined" git 提交 实现大图自动压缩功能 React lingui.js 多语言自动提取翻译键 - ast node html2canvas 解决截图空白问题 react 实现前端发版监测 JS根据文件名获取文件类型 JS获取本机IP地址 适用于react、vue菜单格式化工具函数 git 内容提交 实现大图拦截功能 JS实现视频截图 next.js 利用中间件(middleware.ts)实现PC与移动路由无缝切换 Android生成签名文件及对apk进行签名 JS-SDK 配置,实现微信分享功能
OpenAI vs Anthropic API 对比:响应体、请求体、消息格式与工具调用
冯叶青 · 2026-05-10 · via 博客园 - 冯叶青

在开发 AI 应用时,我们经常需要对接不同的大模型 API。其中 OpenAI 的 Chat Completions API 和 Anthropic 的 Messages API 是目前最流行的两种。虽然它们功能相似,但 请求/响应格式、消息角色、工具调用流程 存在显著差异。本文将从实际开发角度,为你详细对比两者,并提供可直接使用的代码示例。


一、响应体格式区别

OpenAI 响应结构

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "gpt-4",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "回复内容"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": { ... }
}

Anthropic 响应结构

{
  "id": "msg_xxx",
  "type": "message",
  "role": "assistant",
  "content": [
    { "type": "text", "text": "回复内容" }
  ],
  "model": "claude-3-sonnet-...",
  "stop_reason": "end_turn",
  "usage": { ... }
}
特性 OpenAI Anthropic
消息位置 choices[0].message 顶层 role + content
content 类型 字符串(或数组) 数组(纯文本也需数组形式)
结束原因字段 finish_reason stop_reason
判断依据 存在 "choices" → OpenAI 存在 "type": "message" → Anthropic

二、请求体格式区别

OpenAI 请求示例

{
  "model": "gpt-4",
  "messages": [
    { "role": "system", "content": "你是一个助手" },
    { "role": "user", "content": "你好" }
  ],
  "temperature": 0.7,
  "max_tokens": 1000
}

Anthropic 请求示例

{
  "model": "claude-3-sonnet-20240229",
  "system": "你是一个助手",
  "messages": [
    { "role": "user", "content": "你好" }
  ],
  "temperature": 0.7,
  "max_tokens": 1000   // 必填!
}
特性 OpenAI Anthropic
系统提示 messages 中,role: "system" 顶层 system 字段
消息角色 system, user, assistant, tool user, assistant
max_tokens 可选,有默认值 必填,无默认值
content 类型 字符串(可扩展为数组) 必须是数组(如 [{"type":"text","text":"..."}]
角色顺序约束 无强制交替 严格交替,且第一条必须是 user
特有参数 presence_penalty, frequency_penalty top_k
停止词字段 stop stop_sequences

三、消息角色与格式注意事项

✅ OpenAI 支持的角色

  • system:设定助手行为(可出现在任意位置,但通常放在开头)
  • user:用户输入
  • assistant:模型回复
  • tool:工具调用结果

常见错误写法

  • ❌ 使用非规范角色名(如 function_call
  • ❌ 缺少 rolecontent 字段
  • ❌ 连续两个 user 或两个 assistant(虽不强制,但影响逻辑)

✅ Anthropic 支持的角色

  • userassistant 仅限这两种。系统指令放在顶层的 system 字段。

严格约束

  • 消息不是以 user 开头 → 报错
  • 没有严格交替 → 报错
  • content 是字符串而非数组(某些模型会失败)
  • ❌ 最后一条 assistant 消息的内容以空白字符结尾 → 特殊失败场景
  • ❌ 使用旧版 \n\nHuman: 格式 → 不兼容 Messages API

四、工具调用(函数调用)完整示例

4.1 OpenAI 格式

第一次请求:定义工具,模型返回 tool_calls

{
  "model": "gpt-4o",
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    { "role": "user", "content": "北京天气怎么样?" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "获取指定城市的天气",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string", "description": "城市名称" }
          },
          "required": ["city"]
        }
      }
    }
  ],
  "tool_choice": "auto"
}

模型返回(简化):

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\":\"北京\"}"
        }
      }]
    }
  }]
}

第二次请求:回传工具执行结果

{
  "model": "gpt-4o",
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    { "role": "user", "content": "北京天气怎么样?" },
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [{ "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"北京\"}" } }]
    },
    {
      "role": "tool",
      "tool_call_id": "call_abc123",
      "content": "{\"temperature\": \"22°C\", \"condition\": \"晴\"}"
    }
  ],
  "tools": [ /* 同第一次定义 */ ]
}

关键点:工具结果使用 role: "tool",通过 tool_call_id 关联。


4.2 Anthropic 格式

第一次请求:定义工具,模型返回 tool_use

{
  "model": "claude-3-sonnet-20240229",
  "system": "You are a helpful assistant.",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "北京天气怎么样?" }
      ]
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取指定城市的天气",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": { "type": "string", "description": "城市名称" }
        },
        "required": ["city"]
      }
    }
  ],
  "tool_choice": { "type": "auto" },
  "max_tokens": 1024
}

模型返回:

{
  "id": "msg_xyz789",
  "type": "message",
  "role": "assistant",
  "content": [
    { "type": "text", "text": "好的,我来查询北京的天气。" },
    {
      "type": "tool_use",
      "id": "toolu_01AbC",
      "name": "get_weather",
      "input": { "city": "北京" }
    }
  ],
  "stop_reason": "tool_use"
}

第二次请求:回传工具执行结果

{
  "model": "claude-3-sonnet-20240229",
  "system": "You are a helpful assistant.",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "北京天气怎么样?" }
      ]
    },
    {
      "role": "assistant",
      "content": [
        { "type": "text", "text": "好的,我来查询北京的天气。" },
        {
          "type": "tool_use",
          "id": "toolu_01AbC",
          "name": "get_weather",
          "input": { "city": "北京" }
        }
      ]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01AbC",
          "content": "{\"temperature\": \"22°C\", \"condition\": \"晴\"}"
        }
      ]
    }
  ],
  "tools": [ /* 同第一次定义 */ ],
  "max_tokens": 1024
}

关键点

  • 工具结果放在 user 消息中,类型为 tool_result
  • 必须保留之前的 assistant 完整 content
  • 消息仍然严格交替 user/assistant(工具结果本质上是一条新的 user 消息)。

五、总结与建议

对比维度 OpenAI Anthropic
设计哲学 messages 是统一的时序容器 分离系统指令与对话历史
角色丰富度 更灵活(4种角色) 简洁(仅2种核心角色)
严格程度 宽容,不强制交替 严格,强制交替且首消息为 user
工具调用 独立 tool 角色 + tool_calls 字段 tool_use / tool_result 块嵌入 content
易错点 角色名拼错、缺少字段 内容不是数组、未交替、尾随空格