大模型 API 协议差异:OpenAI、Anthropic、Gemini
接入大模型时,最先绑定的通常不是模型本身,而是接口协议。消息怎么组织、工具怎么调用、流式事件长什么样,三家的做法都不一样,坑也大多藏在这里。
三套协议形态各异,不只是字段命名习惯不同。先聊聊它们为什么会长成这样——模型能力的起点、商业竞争的考量、历史包袱的累积——再逐一看具体形态,很多设计选择就不再是”奇怪的差异”,而是”必然的结果”。
一、协议为什么会长成这样
1. OpenAI:从 Chat 到 Responses,上下文膨胀倒逼的协议升级
Chat Completions 的设计前提是”每次请求自包含所有上下文”——客户端把 messages 数组完整传来,模型完整处理。这在早期没问题:用户问一句、模型答一句,messages 数组不过几十条。
但当工具调用、多模态内容、推理摘要、多轮对话全部塞进 messages 之后,问题来了。一次请求的 messages 可能包含几十条工具调用历史、base64 编码的图片、推理摘要文本——信息膨胀严重,每次请求都在重复传输已经发过的内容。而且 Chat Completions 对”接着上一次继续”没有原生支持——模型不记得上一轮用了什么工具、推理到哪一步,全靠客户端把历史原封不动地传回来。
Responses 在一定程度上就是为了解这个结。OpenAI 的 conversation state 文档 把 previous_response_id 作为跨轮传递上下文的方式之一;reasoning models 文档 也建议 reasoning model 优先使用 Responses,并要求在函数调用后把 reasoning item、function call 和 function output 一起带回去。换句话说,Responses 不只是换了一个 endpoint,它也把消息、工具、推理这些东西拆成了更明确的 typed items。代价同样明显:服务端状态、存储策略、上下文继承规则都要理解清楚,客户端也会失去一部分手工拼上下文的可控性。
另一个角度看,OpenAI 同时维护两套聊天协议,本身也是历史包袱。Chat Completions 已经有海量存量应用,不能简单停掉;Responses 承载新能力,又必须往前推。市场领先者经常会遇到这种尴尬:新接口更合理,但老接口更有生态。
2. 模态差异决定了接口形态
三家协议的差异,根源上是因为各家模型的起点不同。
OpenAI 的早期 API 是按能力线长出来的。最早的 OpenAI API 以文本补全为核心;后来 DALL·E 通过独立的 DALL·E API 进入应用;语音转文字则由 Audio API 的 transcriptions、translations 端点承载,文档里也明确说这两个端点历史上由 Whisper 支撑。每种模型的输入输出格式都不同,API 自然按这个边界来设计:聊天的归聊天,图片的归图片,音频的归音频。后来 OpenAI 模型页 开始写“最新模型支持 text/image input 和 vision”,原本清楚的资源边界就变模糊了:聊天接口里有图片、工具、推理,Responses 又试图把这些重新整理成 typed items。
Gemini 走的是另一条路。Google 在 Gemini 1.0 发布文 里就说 Gemini 是从头构建的多模态模型,可以跨文本、代码、音频、图片和视频工作。对应到 API,Gemini API reference 也把 Content 定义成一轮消息的容器,把 Part 定义成承载文本、图片、视频等内容的基本单元。文本是一个 part,图片是一个 part,函数调用也是一个 part。这不是单纯的设计审美差异,而是模型能力和平台目标共同推出来的接口形态。
Claude 的位置介于两者之间。Anthropic 的 模型概览 写得很直接:当前 Claude 模型支持文本和图片输入、文本输出、多语言和视觉能力。工具调用和 thinking 则都通过 Messages API 的 content blocks 表达。也就是说,Claude 的重点更像是“多模态输入、文本/工具输出”的对话代理,而不是为图片、音频、视频分别开一组资源端点。这个定位很适合用 /v1/messages 和 content blocks 承载。模型的输入输出模态,本质决定了它的协议更像一份”资源目录”,还是一条”统一内容流”。
3. 协议是商业竞争的一部分
协议从来不只是技术问题。用自己的协议有几个直接好处:新字段和新能力可以按自己的节奏加;SDK、文档、最佳实践都围绕自己的产品来写;开发者一旦深度接入,切换成本会越来越高。
反过来,使用别人的协议就会被动。OpenAI 加了一个字段,你要不要跟?Anthropic 改了 tool_use 行为,兼容层要不要修?所以各家都有动力推原生协议。不是为了”故意不一样”,而是为了掌握迭代节奏。
但兼容生态明显偏向 OpenAI。OpenAI-compatible 已经是大模型 API 的事实标准之一:很多 SDK 默认支持,很多网关默认暴露,很多新模型提供商也会先做 OpenAI 兼容。Google 不只提供 Gemini 原生 API,也提供 OpenAI 兼容端点,官方示例里直接用 OpenAI SDK、改 base_url 调 Gemini。原因未必是 OpenAI 协议最优,而是生态惯性足够强。
三家都不返回原始思维链,只给摘要——表面上是隐私和安全的考虑,但更深一层的原因是防止模型蒸馏。完整思维链是高价值资产。OpenAI 在 Learning to reason with LLMs 里解释为什么不展示 raw chain-of-thought,理由包括用户体验、competitive advantage,以及保留 chain-of-thought monitoring 的可能性;OpenAI 的 服务条款 也禁止用输出开发与 OpenAI 竞争的模型。所以,把 raw CoT、reasoning.encrypted_content、Anthropic signature、Gemini thoughtSignature 放在同一个框架里看,它们至少都在处理同一个问题:模型需要跨轮延续推理状态,但厂商不愿意把完整推理过程变成可自由使用的明文训练材料。
不过,各家协议都在往”统一内容表示”靠近:OpenAI 的 Responses 把输出拆成 typed items,Anthropic 用 content blocks,Gemini 从一开始就是 parts。长远看,字段名还会不同,但概念差异可能会缩小。真正决定选型的,更多会回到模型能力、价格、延迟、区域和合规这些问题。
4. 协议定位背后的公司哲学
当 OpenAI 兼容格式成为事实标准之一,协议之争就不再只是”谁的字段更好看”。但不争不等于原生协议会消失:原生协议通常是新能力的第一落点,也是最少被兼容层裁剪的入口。
从这个角度重新看三种协议,它们确实有不同气质:
- OpenAI:产品线痕迹很重。Chat、Images、Audio、Videos 各自有资源端点,Responses 再把新一代模型能力收拢起来。
- Anthropic:概念更少。Messages API、content blocks、tools、thinking,主要围绕对话代理和工具使用展开。
- Google:平台痕迹最明显。Gemini Developer API 适合直接开发;Vertex AI 路线则服务于 Google Cloud 的认证、区域、配额和企业治理。Google 自己的 迁移文档 也提醒,两条路线的区域、模型训练和密钥管理并不完全一样。
理解这些,不只是为了选协议,也在提醒自己:兼容层能解决 80% 的接入问题,但最后 20% 的能力差异,往往只在原生协议里最清楚。
有了这些背景,下面逐一看三套协议的具体形态——以 OpenAI 为主线展开,Anthropic 和 Gemini 作为对比,讲清楚每一种协议里”内容放在哪里”。
二、OpenAI 接口协议
从兼容层看,OpenAI 仍然是生态最厚的一套协议。大量 SDK、Agent 框架和代理网关都先支持 OpenAI 格式,再去适配其他厂商。它的核心思路是按资源端点拆能力:聊天、图片、音频、视频各有各的接口。以下内容主要参考 OpenAI 官方文档。
但聊天这件事本身,OpenAI 就给了两个入口,先把这个理清楚。
1. Chat Completions:最广的兼容面
POST /v1/chat/completions 是最经典、兼容面最广的聊天入口,详见 Chat Completions API。核心结构是 messages 数组,靠 role 区分角色。
1.1 非流式
不带 stream 参数时,一次请求返回完整结果。
请求:
{
"model": "gpt-5.5",
"messages": [
{ "role": "system", "content": "用清楚、准确的中文回答。" },
{ "role": "user", "content": "用一句话解释什么是大模型 API。" }
]
}响应的 object 为 chat.completion,内容在 choices[].message 里:
{
"id": "chatcmpl_123",
"object": "chat.completion",
"model": "gpt-5.5",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "大模型 API 是应用调用模型能力的一组 HTTP 接口和对象格式。"
},
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 24, "completion_tokens": 18, "total_tokens": 42 }
}1.2 SSE 流式
加上 "stream": true,服务端通过 SSE(Server-Sent Events)逐段推送。每个事件是一行 data: 加一段 JSON,客户端持续把 delta.content 拼起来,最后遇到 data: [DONE] 结束:
data: {"id":"chatcmpl_123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl_123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"大模型"},"finish_reason":null}]}
data: {"id":"chatcmpl_123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"API"},"finish_reason":null}]}
data: {"id":"chatcmpl_123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]注意几个细节:第一个 chunk 通常只带 delta.role,没有文本内容;最后一个有效 chunk 的 delta 可能为空,只带 finish_reason;[DONE] 不是 JSON,必须单独处理。
1.3 工具调用
Chat Completions 的工具声明放在 tools[] 里,用 JSON Schema 描述参数。
请求:
{
"model": "gpt-5.5",
"messages": [
{ "role": "user", "content": "查询杭州天气,判断是否适合露天活动。" }
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气。",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}]
}模型请求调用工具时,assistant message 里会出现 tool_calls:
{
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\"city\":\"杭州\"}" }
}]
},
"finish_reason": "tool_calls"
}]
}应用执行工具后,把结果作为一条 role: "tool" 消息放回 messages,模型继续生成最终回复:
{
"model": "gpt-5.5",
"messages": [
{ "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": "{\"temp\":22,\"condition\":\"晴\"}" }
]
}流式场景下,tool_calls 的增量可能分多个 chunk 到达——arguments 字段会逐段拼接,不能假定一次收全。
1.4 思考控制
Chat Completions 通过 reasoning_effort 控制推理模型的思考强度。这个字段不要硬编码:API 枚举和具体模型支持范围不是一回事。以当前 gpt-5.5 为例,模型页列出的 reasoning 取值是 none、low、medium、high、xhigh;有些接口说明里还会出现 minimal,但不是每个模型都支持。
它不返回原始思维链。需要让用户看到推理过程时,只能看模型支持的摘要或解释字段,不能假设能拿到完整 chain-of-thought。详见 OpenAI Reasoning 文档。
2. Responses:新项目的推荐入口
POST /v1/responses 是 OpenAI 后来推出的新入口,把一次生成建模成一个 response 对象。和 Chat Completions 最大的不同在于,它把文本、工具调用、推理内容都统一放进 output[] 数组里,结构更规整。
2.1 基本请求
请求:
{
"model": "gpt-5.5",
"instructions": "用清楚、准确的中文回答。",
"input": "用一句话解释什么是大模型 API。"
}响应的 object 为 response,内容在 output[] 里:
{
"id": "resp_123",
"object": "response",
"status": "completed",
"model": "gpt-5.5",
"output": [{
"type": "message",
"role": "assistant",
"content": [{
"type": "output_text",
"text": "大模型 API 是应用调用模型能力的一组 HTTP 接口和对象格式。"
}]
}],
"usage": { "input_tokens": 20, "output_tokens": 18, "total_tokens": 38 }
}2.2 多模态输入和工具
input 不只是字符串,也可以是带 role 和 content[] 的消息数组,多模态内容作为不同类型的 content item:
{
"model": "gpt-5.5",
"input": [{
"role": "user",
"content": [
{ "type": "input_text", "text": "解释这张图的主要内容。" },
{ "type": "input_image", "image_url": "https://example.com/image.png" },
{ "type": "input_file", "file_id": "file_123" }
]
}],
"tools": [
{ "type": "web_search" },
{
"type": "function",
"name": "get_weather",
"description": "获取指定城市的天气。",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
]
}工具调用结果也出现在 output[] 里,类型为 function_call。应用执行完后,下一轮请求在 input 里用 function_call_output item 回填结果,并用 call_id 对上原来的调用:
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\"temp\":22,\"condition\":\"晴\"}"
}2.3 推理控制
Responses 对推理的支持更精细,通过 reasoning 字段控制:
{
"model": "gpt-5.5",
"input": "分析这个接口设计的风险。",
"reasoning": {
"effort": "high",
"summary": "auto"
}
}effort 控制思考强度,具体取值仍然看模型页。当前 gpt-5.5 支持 none、low、medium、high、xhigh。summary 控制是否返回推理摘要。和 Chat Completions 一样,这里控制的是推理强度和摘要,不等于返回原始思维链。
如果需要无状态地延续推理上下文,可以在请求里加 include: ["reasoning.encrypted_content"]。这样返回的 reasoning item 会带加密内容,下一轮把它原样带回去即可。这个机制尤其适合 store: false 或 Zero Data Retention 场景。
2.4 上下文延续
Responses 不会因为你在同一个进程里调用两次就自动记住前文。第二轮只发一句”继续”,模型拿不到上一轮上下文。主动管理上下文有三种常见方式:
- 把历史和上一轮
outputitem 继续放进input。 - 传
previous_response_id,让服务端引用上一轮 response。 - 用 Conversations API 管一条持久会话。
这里有两个容易漏掉的细节:previous_response_id 不会继承上一轮顶层 instructions,稳定的系统/开发者指令要每轮重发;它也不等于免费引用历史,链路里的前文 token 仍然会计入输入。
2.5 流式事件
Responses 的流式输出也是 SSE,但事件更语义化:
event: response.output_text.delta
data: {"type":"response.output_text.delta","response_id":"resp_123","item_id":"msg_1","output_index":0,"content_index":0,"delta":"大模型"}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_123","status":"completed"}}每种事件有明确的 type,不像 Chat Completions 全部是 chat.completion.chunk。这对写解析逻辑的人更友好。
3. 其他能力一览
除聊天外,OpenAI 还为不同能力提供了独立端点。它们都不走 messages 结构:
图片:POST /v1/images/generations 做文生图,返回 data[]。当前 GPT Image 系列,包括 gpt-image-2,主要返回 base64 图片数据;可以用 output_format 控制 png/jpeg/webp。/v1/images/edits 做图像编辑,/v1/images/variations 仍主要是旧 DALL·E 2 时代的变体接口。Responses 也能通过内置 image_generation 工具在对话里生成或编辑图片。
向量化:POST /v1/embeddings,输入文本数组,返回向量列表。dimensions 参数影响索引维度,不能随便换。
音频:/v1/audio/speech(文本转语音,返回音频二进制)、/v1/audio/transcriptions(语音转文字)、/v1/audio/translations(音频翻译,输出英文)。后两个用 multipart 表单上传音频文件。
视频:POST /v1/videos 是异步任务,当前模型包括 sora-2 和 sora-2-pro。先创建 job,再用 GET /v1/videos/{id} 轮询状态,完成后通过 GET /v1/videos/{id}/content 下载 MP4。和普通图像生成不同,视频生成不要按一次请求直接返回文件来设计。详见 Videos API。
实时语音:走 WebSocket(wss://api.openai.com/v1/realtime),建连后通过事件对象通信,和普通 HTTP JSON 请求形态完全不同。
其他:/v1/models 列出模型,/v1/moderations 做内容审核,/v1/files 上传文件,/v1/completions 是老的文本补全接口(新项目一般不优先用它)。
小结:OpenAI 的优势是端点覆盖广、生态成熟。需要留意的点是 Chat Completions 和 Responses 两个聊天入口的差异,以及图片、音频、视频各有独立对象格式。做统一抽象时,别把所有能力都强行塞成一条”聊天消息”。
三、Anthropic 接口协议(Claude)
Anthropic 的 Messages API 是 Claude 生成内容的主入口:/v1/messages。它的核心设计很克制:文本、图片、工具调用、工具结果、thinking 都是 content blocks。
一个同时包含工具声明和推理控制的请求:
{
"model": "claude-sonnet-4-6",
"max_tokens": 16000,
"system": "用简洁的中文回答。",
"thinking": { "type": "adaptive", "display": "summarized" },
"output_config": { "effort": "high" },
"tools": [{
"name": "get_weather",
"description": "获取指定城市的天气。",
"input_schema": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}],
"messages": [{
"role": "user",
"content": [{ "type": "text", "text": "查询杭州天气,判断是否适合户外活动。" }]
}]
}响应里,各种内容都是 content[] 里的 block:
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "需要先查天气再判断……", "signature": "EosnC..." },
{ "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": { "city": "Hangzhou" } }
],
"stop_reason": "tool_use"
}工具调用请求(tool_use)和 thinking 都只是 content[] 里的一种 block,结构很统一。应用执行工具后,把结果作为 tool_result block 放回下一轮 messages 即可。
推理控制方面,新版 Claude 推荐用 thinking: { type: "adaptive" } 让模型自行判断什么时候需要 thinking,再用 output_config.effort 控制整体 token 花费和深度。当前 API effort 常见取值包括 low、medium、high、xhigh、max,具体见 Anthropic Effort 文档。部分旧模型仍支持 thinking: { type: "enabled", budget_tokens: 10000 } 这种固定 token 预算,但在 Opus/Sonnet 4.6 之后已经不是推荐路径。
Claude 的 thinking block 可能返回摘要,也可能只返回空 thinking 加 signature,取决于模型和 display 设置。原始思维链不作为稳定可用的 API 输出。如果跨轮延续推理上下文,尤其是工具调用场景,需要保留 signature,不要自己改写 thinking block。详见 Anthropic Extended Thinking。
流式输出也围绕 block 事件展开:content_block_start → content_block_delta → content_block_stop。工具参数的增量和文本增量可能交替出现,不能只按”文本 delta”处理。
小结:Anthropic 协议设计简洁,content blocks 让工具调用和多模态输入很自然。代价是兼容生态不如 OpenAI 广。接入 Claude 时,很多项目最后还是要写一层从 OpenAI message 到 Anthropic block 的转换。
四、Gemini / Vertex AI 接口协议
Gemini 的协议核心是 generateContent,所有内容围绕 contents[] 和 parts[] 组织,详见 Gemini API 文档。这里最容易混的是入口:同一个 Gemini 模型可以通过 Gemini Developer API 调用,也可以通过 Vertex AI 调用。前者走 generativelanguage.googleapis.com 和 API key,后者走 Google Cloud 的区域端点和 IAM。路径、鉴权、配额体系不同,但主体请求结构都围绕 contents/parts。
1. contents 和 parts
contents[] 是对话轮次,parts[] 是一轮里的具体内容。文本、图片、文件、函数调用全都是 part:
请求:
{
"contents": [{
"role": "user",
"parts": [
{ "text": "生成一张夜间咖啡馆的图片,并用一句话描述风格。" }
]
}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"thinkingConfig": { "thinkingLevel": "medium" }
}
}响应里,各种内容都在 candidates[].content.parts[] 里:
{
"candidates": [{
"content": {
"role": "model",
"parts": [
{ "thought": true, "text": "需要同时给出描述和图片。" },
{ "text": "暖色调夜间咖啡馆,轻微电影感。" },
{ "inlineData": { "mimeType": "image/png", "data": "iVBORw0KGgo..." } }
]
},
"finishReason": "STOP"
}],
"usageMetadata": { "promptTokenCount": 120, "candidatesTokenCount": 52, "totalTokenCount": 1300 }
}2. 工具调用和推理
工具调用走 parts:模型请求工具时返回 functionCall part,里面有 name、args。Gemini 3 系列会给每个 function call 一个 id;手写 REST 或自己维护历史时,回填 functionResponse 必须带上同一个 id,否则模型可能对不上是哪次调用的结果。详见 Gemini Function Calling。
推理控制放在 generationConfig.thinkingConfig。Gemini 3 系列用 thinkingLevel(minimal / low / medium / high),Gemini 2.5 系列常见写法是 thinkingBudget(具体 token 数,0 关闭、-1 动态分配)。详见 Gemini Thinking。如果模型在 parts 里返回了 thoughtSignature,下一轮请求要把它放回原来的 part;尤其是函数调用链路里,丢掉 signature 会破坏模型的跨轮推理上下文。
小结:Gemini 的优势是多模态统一,所有模态都是一种 part,不需要在不同端点间跳转。代价是 Developer API 和 Vertex AI 两个入口容易搞混,OpenAI 兼容层也只是方便迁移,不等于覆盖 Gemini 原生能力。
五、对比与选型
1. 整体设计
| 维度 | OpenAI | Anthropic | Gemini |
|---|---|---|---|
| 核心抽象 | 按资源拆端点 | 按 content blocks 组织 | 按 parts 组织 |
| 主入口 | chat/completions 或 responses | /v1/messages(唯一入口) | generateContent |
| 多模态方式 | 不同能力走不同端点 | 不同内容的 block 类型 | 不同内容的 part 类型 |
| 流式输出 | chat.completion.chunk 或 response event | content block 事件 | streamGenerateContent chunk |
| 上下文管理 | 客户端传历史(Responses 可引用已有 response) | 客户端传 messages 历史 | 客户端传 contents 历史 |
| 生态兼容 | 最强,已成事实标准 | 原生体验好,适配较少 | 多模态统一,但生态最窄 |
2. 工具调用差异
这是写 Agent 和协议转换层时最容易踩坑的地方——三家”模型请求工具”和”应用回填结果”的位置各不相同:
| 协议 | 模型请求工具 | 应用回填结果 |
|---|---|---|
| OpenAI Chat | assistant message 的 tool_calls[] | 下一条 role: "tool" 消息 |
| OpenAI Responses | output[] 里的 function_call item | 下一轮 input 里的 function_call_output item |
| Anthropic | assistant content 里的 tool_use block | user content 里的 tool_result block |
| Gemini | model parts 里的 functionCall | user parts 里的 functionResponse |
这个差异的本质是”工具调用放在哪一层”。OpenAI(Chat Completions)把工具调用作为消息的一个附属字段——assistant message 除了 content 正文,额外挂了一个 tool_calls[],回填时也要专门开一条 role: "tool" 消息。Anthropic 和 Gemini 则把工具调用和文本放在同一层——tool_use 就是一个 block 类型,functionCall 就是一个 part 类型,和 text 类型平级,都在同一个 content[] / parts[] 数组里。
3. 思考控制差异
| 协议 | 控制参数 | 返回值 | 跨轮延续 |
|---|---|---|---|
| OpenAI Chat | reasoning_effort | 推理摘要(部分模型) | 不直接支持 |
| OpenAI Responses | reasoning.effort + reasoning.summary | 推理摘要,可选加密内容 | include: ["reasoning.encrypted_content"] |
| Anthropic | thinking.type + output_config.effort | thinking block 摘要或省略文本 | 保留 signature |
| Gemini | thinkingConfig.thinkingLevel 或 thinkingBudget | thought: true part | 保留 thoughtSignature |
三家都不应该按”能拿到原始思维链”来设计。需要跨轮延续推理上下文时,各自有不同机制:Responses 传加密 reasoning item,Anthropic 保留 thinking block 的 signature,Gemini 保留 thoughtSignature。
4. 选型建议
对比表看完,具体怎么选?分三种情况:
以 OpenAI 协议作为对外接口:如果你在做需要对接多个下游的应用或网关,OpenAI 协议通常最省事。客户端最多,SDK 支持最广,很多兼容服务换 base URL 和模型名就能先跑起来。
直接接入某个模型:如果只用一家,走原生协议更自然。Anthropic 的 content blocks 对工具调用很友好,Gemini 的 parts 对多模态最统一。
多模态优先:Gemini 的 parts 设计让文本、图片、音频、视频共用同一套结构,不需要在不同端点间跳转。OpenAI 也在往这个方向补,尤其是 Responses 里的输入 item 和内置工具,但独立资源端点仍然存在。
5. 协议兼容方案
跨协议接入时,常见的兼容方案分两类:
服务端网关负责对客户端暴露一种协议、对上游转成另一种。AxonHub 同时暴露 OpenAI、Anthropic、Gemini 三种入口,内部用统一中间结构做转换;New API 把各家协议拆成更细的 relay format,适合做模型分发和计费。
应用层库负责代码里统一调用、底层处理差异。LangChain 用 ChatModel 接口统一调用不同 provider,Vercel AI SDK 用 generateText、streamText 等函数屏蔽底层协议细节。
无论用哪种方案,协议转换的核心都是同一件事:把一种协议里”内容放在哪里”映射到另一种。理解这个,很多看起来零散的字段差异就会变得好处理。