OpenAI APIClaude APIGemini APIAPI 格式工具调用流式输出多模型

OpenAI、Claude 和 Gemini API 格式有什么区别?

对比 OpenAI Responses 与 Chat Completions、Claude Messages、Gemini GenerateContent 的认证、消息、系统指令、流式输出、工具调用、多模态和结构化输出格式。

OpenAI、Claude 和 Gemini API 格式有什么区别?

OpenAI、Claude 和 Gemini 三种原生 API 协议对比

OpenAI、Claude 和 Gemini 都能完成聊天、图片理解、工具调用和 JSON 输出,但它们的原生 API 不是换个模型名就能互相调用

最常见的错误是:

  • 把 OpenAI 的 messages 原样发给 Claude;
  • 把 Claude 的 system 放进 Gemini 的 contents
  • 只替换 Base URL,却没有转换认证 Header;
  • 把三家的工具调用都当作 tool_calls
  • 流式响应只按 data: ... 文本拼接;
  • 假设正文永远位于同一个 content 字段。

如果你正在写多模型客户端、API 网关或 Agent,真正需要统一的是应用内部数据模型,而不是假设上游协议天然相同。

先看结论:三家核心格式对照

项目OpenAI ResponsesClaude MessagesGemini GenerateContent
典型路径POST /v1/responsesPOST /v1/messagesPOST /v1beta/models/{model}:generateContent
模型位置请求体 model请求体 modelURL 路径 {model}
认证Authorization: Bearer ...x-api-key: ...x-goog-api-key: ...
版本 Header通常不需要固定日期 Headeranthropic-version版本通常体现在 URL,如 v1beta
输入入口inputmessagescontents
系统指令instructions顶层 systemsystemInstruction
内容单元input/output items 与 content partscontent blocksparts
输出正文output 中的 output_text,SDK 常提供聚合属性content[] 中的 text blockcandidates[].content.parts[] 中的 text
最大输出max_output_tokensmax_tokensgenerationConfig.maxOutputTokens
工具定义tools 中的 function tooltools + input_schematools[].functionDeclarations
工具调用function call itemtool_use blockfunctionCall part
工具结果function call output itemtool_result blockfunctionResponse part

OpenAI 自己还存在两套常见文本协议:较新的 Responses API 和仍广泛使用的 Chat Completions API。因此“OpenAI 格式”本身也不是单一格式。

消息结构为什么不能直接复制

input、messages、contents 和内容块的结构差异

OpenAI Responses:input 是字符串或输入项

最简单的请求:

curl https://api.openai.com/v1/responses \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_MODEL_ID",
    "instructions": "Answer concisely.",
    "input": "Explain API adapters in one sentence.",
    "max_output_tokens": 300
  }'

复杂对话可把 input 写成 item 数组。响应的 output 也可能包含消息、工具调用、推理相关项目等,不应硬编码读取:

response.output[0].content[0].text

OpenAI 官方明确提醒,output 往往不止一个 item。官方 SDK 提供的 output_text 聚合属性更适合简单取正文;自己写协议层时则应遍历类型。

OpenAI Chat Completions:messages + choices

旧客户端和大量 OpenAI 兼容网关仍使用:

{
  "model": "YOUR_MODEL_ID",
  "messages": [
    { "role": "developer", "content": "Answer concisely." },
    { "role": "user", "content": "Explain API adapters." }
  ],
  "max_completion_tokens": 300
}

正文通常在:

choices[0].message.content

这和 Responses API 的 inputinstructionsoutput 不是同一结构。某个服务宣称“OpenAI 兼容”时,还要继续确认它兼容的是 Chat Completions、Responses,还是二者。

Claude Messages:messages 中只有 user 与 assistant 对话角色

基础请求:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "YOUR_MODEL_ID",
    "system": "Answer concisely.",
    "max_tokens": 300,
    "messages": [
      { "role": "user", "content": "Explain API adapters." }
    ]
  }'

Claude 的 content 可以是字符串,也可以是 block 数组。响应正文不是一个固定字符串,而是:

{
  "content": [
    { "type": "text", "text": "..." }
  ],
  "stop_reason": "end_turn",
  "usage": {}
}

工具调用、思考、引用等能力也通过不同 block 类型表达。解析器必须按 type 分支。

Gemini:contents → parts

Gemini REST 请求把模型放在 URL 中:

curl "https://generativelanguage.googleapis.com/v1beta/models/YOUR_MODEL_ID:generateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemInstruction": {
      "parts": [{ "text": "Answer concisely." }]
    },
    "contents": [{
      "role": "user",
      "parts": [{ "text": "Explain API adapters." }]
    }],
    "generationConfig": {
      "maxOutputTokens": 300
    }
  }'

常见正文路径为:

candidates[0].content.parts[].text

parts 还可能包含 functionCallfunctionResponse、图片或其他模态,因此同样不能只假设第一个 part 一定是文本。

Google 当前文档还提供新的 Interactions API,并建议用它访问最新功能和模型。本文聚焦仍有明确官方参考且广泛使用的 generateContent 原生格式;选择接口时应以目标模型当前文档为准。

Role 和系统指令有什么不同

OpenAI

Responses API 使用顶层 instructions,并可在输入 item 中使用角色。Chat Completions 常见 developersystemuserassistant 等角色;具体优先级和模型支持应看当前官方文档。

Claude

传统 Messages 请求把主要系统提示放在顶层 system,对话消息通常在 userassistant 之间交替。不要简单塞入一条 { "role": "system" } 并假设原生 Claude Messages 会按 OpenAI 方式处理。

Gemini

系统指令使用 systemInstruction,对话历史放入 contents。模型回复角色通常表示为 model,不是 OpenAI/Claude 常用的 assistant

适配时可建立内部角色:

instruction
user
assistant

再映射为各 Provider 的顶层指令、消息角色与内容结构。

工具调用的字段差异

三家 API 的 function call、tool use 与结果回传差异

三家流程都可抽象成:

定义工具
→ 模型请求调用
→ 应用执行函数
→ 把结果连同调用标识发回
→ 模型生成最终回答

但线上格式并不相同。

OpenAI Responses

工具定义通常带:

{
  "type": "function",
  "name": "get_weather",
  "description": "Get current weather",
  "parameters": {
    "type": "object",
    "properties": {
      "city": { "type": "string" }
    },
    "required": ["city"]
  }
}

模型产生 function call item,应用执行后用对应 call_id 发送 function call output。不要把 Chat Completions 的 tool_call_id 或 Claude 的 tool_use_id 原样套过来。

OpenAI Chat Completions

模型返回 message.tool_calls[];工具结果作为 role: "tool" 的消息回传,并使用 tool_call_id 关联。

Claude Messages

工具定义使用 namedescriptioninput_schema。Claude 返回:

{
  "type": "tool_use",
  "id": "toolu_...",
  "name": "get_weather",
  "input": { "city": "Shenzhen" }
}

应用把结果放进后续用户消息的 tool_result block,并通过 tool_use_id 关联。

Gemini GenerateContent

函数声明放入 tools[].functionDeclarations。模型在 part 中返回 functionCall,应用通过 functionResponse part 回传结果。

因此,跨模型 Tool Runner 至少需要统一:

type ToolCall = {
  provider: 'openai' | 'claude' | 'gemini';
  id?: string;
  name: string;
  arguments: unknown;
};

同时保留 Provider 原始 ID 和原始 payload,避免多轮调用时丢失关联信息。

图片和多模态输入怎么表示

Provider常见内容表示
OpenAI Responsesinput_textinput_image 等 content item
OpenAI Chat Completionsmessage content 中的 text / image content parts
Claudetextimagedocument 等 content block,source 描述 URL 或 Base64
Geminiparts 中使用 textinlineDatafileData

不要只改图片字段名。还应转换:

  • MIME type;
  • URL、Base64 或文件引用方式;
  • 单次请求的文件数量与尺寸限制;
  • 图片在消息中的顺序;
  • PDF、音频和视频支持范围;
  • Provider 的文件上传与缓存机制。

客户端内部可以统一为:

type ContentPart =
  | { type: 'text'; text: string }
  | { type: 'image_url'; url: string; mimeType?: string }
  | { type: 'image_base64'; data: string; mimeType: string };

适配层再决定目标 API 是否支持,以及应该变成哪种原生 part/block。

流式响应不是同一种 SSE

OpenAI Responses

Responses API 会发送带明确类型的语义事件,例如文本增量与完成事件。解析器应根据 type 处理,而不是把所有 data 直接拼成字符串。

OpenAI Chat Completions

常见流式正文位于:

choices[0].delta.content

工具参数也可能分多个 delta 到达,需要按调用索引或 ID 累积。

Claude

Claude 流式事件包括:

message_start
content_block_start
content_block_delta
content_block_stop
message_delta
message_stop

文本通常由 text_delta 累积;工具输入可能以部分 JSON delta 形式到达。

Gemini

Gemini 提供 streamGenerateContent。每个流式 chunk 仍围绕 candidatescontentparts 组织。不能套用 OpenAI 的 choices[].delta 解析器。

建议内部统一事件:

type NormalizedEvent =
  | { type: 'text_delta'; text: string }
  | { type: 'tool_delta'; callId?: string; data: string }
  | { type: 'usage'; input: number; output: number }
  | { type: 'done'; reason?: string }
  | { type: 'error'; error: unknown };

但同时保存未知原生事件,避免 Provider 新增类型后被静默丢弃。

结构化输出也不是复制同一个 schema 字段

三家都支持受约束的 JSON 输出,但入口不同:

  • OpenAI:Responses 或 Chat Completions 中配置文本/响应格式与 JSON Schema;
  • Claude:通过 output_config.format 等当前官方能力声明结构;
  • Gemini:通过 generationConfig.responseMimeTyperesponseJsonSchema / responseSchema 等字段声明。

支持 JSON Schema 不代表完整支持所有关键字。生产代码应:

  1. 使用各 Provider 官方支持的 Schema 子集;
  2. 在客户端再次解析和校验;
  3. 处理拒答、截断、工具调用和空响应;
  4. 保存原始响应便于排错;
  5. 不把“JSON mode”误认为一定符合业务 Schema。

关于 Schema 设计,后续可参考专门的结构化输出文章;如果当前接口返回成功但正文为空,可先读 AI API 返回空内容排查

认证和错误响应也要转换

认证 Header

OpenAI: Authorization: Bearer YOUR_API_KEY
Claude: x-api-key: YOUR_API_KEY
        anthropic-version: 2023-06-01
Gemini: x-goog-api-key: YOUR_API_KEY

不要在浏览器前端直接放这些 Key。安全保存方式可参考 API Key 安全指南

错误格式

即使三家都返回 HTTP 4004014295xx,错误 JSON 的嵌套结构、错误类型、请求 ID Header 和重试信息仍不同。

适配器可统一业务错误:

type ProviderError = {
  provider: string;
  status: number;
  code?: string;
  type?: string;
  message: string;
  requestId?: string;
  retryable: boolean;
  raw: unknown;
};

但不要抹掉原始状态码和 payload。详细状态码处理可参考 AI API 错误排查指南

如何设计真正可靠的多模型适配层

应用内部统一格式与三家原生协议适配架构

1. 定义内部 Canonical Model

至少统一:

  • system instruction;
  • messages 与多模态 parts;
  • generation options;
  • tool definitions;
  • structured output;
  • text、tool call、usage、finish reason 与 errors。

2. 每个 Provider 独立编码和解析

Canonical request
├─ OpenAI Responses adapter
├─ OpenAI Chat Completions adapter
├─ Claude Messages adapter
└─ Gemini GenerateContent adapter

不要构造一个包含所有 Provider 字段的巨大 JSON,再期望上游忽略陌生字段。

3. 做能力协商,而不是静默降级

例如目标模型不支持图片、并行工具调用或某个 Schema 关键字时,应明确报错或由策略层决定降级,不能悄悄删除输入。

4. 保留原生响应

统一对象方便业务使用,原生对象方便调试、审计和支持新特性。二者都要保留。

5. 分协议测试

至少测试:

纯文本
多轮消息
系统指令
图片输入
单工具调用
并行工具调用
工具结果回传
流式文本
流式工具参数
结构化输出
截断与拒答
429 和 5xx

“基础聊天成功”不能证明 Agent、流式和工具调用兼容。

使用 Nbility 时如何选格式

Nbility 提供多种协议入口,典型路径包括:

OpenAI Chat Completions: https://api.nbility.ai/v1/chat/completions
OpenAI Responses:        https://api.nbility.ai/v1/responses
Claude Messages:         https://api.nbility.ai/v1/messages

开始前在 Nbility 模型广场确认:

  • 精确 Model ID;
  • 该模型支持的协议;
  • 工具调用、图片和结构化输出能力;
  • 客户端最终请求的 Endpoint;
  • Token 权限和额度。

如果现有 SDK 只支持 OpenAI 格式,优先选择平台明确支持的 OpenAI 兼容入口;如果应用依赖 Claude 原生 content blocks,则使用 Messages 入口。不要根据模型品牌猜协议。

遇到兼容问题时,可通过 Nbility 工单提交脱敏后的请求路径、Model ID、状态码和响应类型,不要附带真实 API Key 或完整敏感 Prompt。

FAQ

OpenAI SDK 能直接调用 Claude 或 Gemini 原生 API 吗?

不能直接调用原生格式。只有目标服务额外提供 OpenAI 兼容层时,才可以按它声明的兼容范围使用。

只改 Base URL 和 model 可以吗?

只有 Provider 明确实现了当前客户端所用协议时才可能。认证、路径、工具、流式和响应结构必须同时兼容。

Claude 的 system 能放进 messages 吗?

基础 Messages API 通常使用顶层 system。不要照搬 OpenAI 的 system-role 消息;以当前 Claude 文档和所用功能为准。

Gemini 的 assistant role 是什么?

Gemini contents 中模型回复通常使用 model 角色,而不是 assistant

三家的 JSON Schema 完全兼容吗?

不完全兼容。入口字段和支持的 Schema 子集可能不同,输出仍需在应用端校验。

为什么普通聊天成功,工具调用却失败?

因为兼容层可能只转换文本消息,没有完整转换工具定义、调用 ID、结果回传和流式参数。

总结

OpenAI、Claude 和 Gemini API 的核心区别不只是字段名:

  1. Endpoint、认证方式和模型位置不同;
  2. inputmessagescontents 的语义不同;
  3. 系统指令、角色和多模态内容结构不同;
  4. 工具调用 ID 与结果回传协议不同;
  5. 流式事件必须分别解析;
  6. 结构化输出和 Schema 支持范围不同;
  7. 多模型系统应使用内部统一模型加独立 Provider Adapter。

先确认客户端实际发送的协议,再选择对应 Endpoint 和 Model ID,能避免大多数“换了模型却 400/404、正文为空或工具不工作”的问题。

参考资料

相关文章

结构化输出与 JSON Schema:如何让模型稳定返回 JSON
Structured OutputJSON SchemaOpenAI API

结构化输出与 JSON Schema:如何让模型稳定返回 JSON

模型返回的 JSON 经常少字段、类型错误或夹带 Markdown?本文解释 JSON Mode 与结构化输出的区别,并给出 OpenAI、Claude、Gemini 配置、Schema 设计、校验与重试方案。

用 Nbility 跑通你的 Agent 工作流

获取 API Key,统一接入 OpenAI 兼容模型和开发工具。

管理 API Key