Skip to content

模型协议主流标准对比

本篇为 1-模型服务 系列的一篇协议规范笔记。配套部署/运行笔记见 docker安装ollama并使用本地模型 / Ollama-介绍

写完 Spring AI、LangChain、Dify 这些框架之后回头看,无论哪一家框架,最终都只做了一件事:把内部表示转成一段 HTTP 请求,扔给上游大模型,再把响应转回对象。这意味着——所谓"用框架封装"和"直接调用协议",差别只在谁来写那段 HTTP。

而今天市面上能拿到的上游协议几乎都"长得像 OpenAI"。Spring AI 默认拼 /v1/chat/completions,LangChain 的 ChatOpenAI 默认打 /v1/chat/completions,阿里云百炼、DeepSeek、SiliconFlow 也都把 /v1/chat/completions 当成事实标准。这套接口最早由 OpenAI 在 2020 年随 GPT-3 推出,2023 年起成为事实行业标准。

但"长得像"不等于"完全一样"。本文就以五条主流协议为对象,逐个拆端点、鉴权、入参、出参、流式事件、工具调用,最后给一张五协议横向对照表——读完你应该能在任意一个 SDK 报错的时候,自己打开 curl 验证协议层到底发生了什么。

本文涉及的五条协议:

编号协议厂商 / 形态
1OpenAI Chat Completions APIOpenAI / 业界事实标准原型
2OpenAI Responses APIOpenAI / 2025 起逐步替代 Chat Completions 的 stateful 接口
3Anthropic Messages APIAnthropic / Claude 系列
4Google Gemini APIGoogle / Gemini 系列
5OpenAI Compatible API兼容端点(Ollama / vLLM / DeepSeek / 阿里云百炼 / SiliconFlow 等)

1. OpenAI Chat Completions API

行业事实标准的原型。多数智能体框架的默认底层协议。

1.1 端点与鉴权

text
POST https://api.openai.com/v1/chat/completions
Authorization: Bearer $OPENAI_API_KEY
Content-Type: application/json

可选 header:OpenAI-OrganizationOpenAI-Project(多组织/项目区分计费)。Azure 镜像端点为 https://{resource}.openai.azure.com/openai/deployments/{deployment}/chat/completions,鉴权换为 api-key header。

1.2 最小请求

json
{
  "model": "gpt-5",
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user",   "content": "你是谁?"}
  ]
}

1.3 最小响应(非流式)

json
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1752400000,
  "model": "gpt-5-2026-01-15",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "我是 OpenAI 训练的 AI 助手 ..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 24,
    "completion_tokens": 18,
    "total_tokens": 42
  }
}

1.4 关键参数

字段必填类型范围 / 默认含义
modelstring模型 ID,例 gpt-5 / gpt-4o / o4-mini
messagesarray对话历史,元素为 {role, content},role ∈ {system, user, assistant, tool},tool 角色承载 tool_call_id 回传结果
temperaturefloat0–2,默认 1采样温度
top_pfloat0–1,默认 1核采样
max_tokens / max_completion_tokensint默认不限单次输出上限(新模型端点偏向 max_completion_tokens)
nint默认 1同 prompt 生成几条候选
streambool默认 falsetrue 时返回 SSE 流
stopstring | array命中即停止生成的字符串
presence_penaltyfloat-2–2,默认 0鼓励 / 抑制新话题
frequency_penaltyfloat-2–2,默认 0抑制 / 鼓励重复用词
seedint复现性种子(并非 100% 保证)
toolsarray函数定义,见 1.6
tool_choicestring | object默认 auto"none" / "auto" / "required" / {"type": "function", "function": {"name": "..."}}
parallel_tool_callsbool默认 true允许单轮多次调用
response_formatobject{type: "json_schema", json_schema: {...}} 等结构化输出
logprobs / top_logprobsbool / int返回对数概率
logit_biasobject-100–100按 token 偏置
reasoning_effortstringlow/medium/high推理模型(gpt-5 / o 系列)控制思考深度
service_tierstringauto/default/flex/priority服务层级

1.5 流式响应(SSE)

object 字段变为 "chat.completion.chunk",id 在所有 chunk 中保持一致。choices[].delta 按出现顺序承载:

json
{"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1752400000,"model":"gpt-5-2026-01-15",
 "choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
{"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1752400000,"model":"gpt-5-2026-01-15",
 "choices":[{"index":0,"delta":{"content":"我"},"finish_reason":null}]}
{"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1752400000,"model":"gpt-5-2026-01-15",
 "choices":[{"index":0,"delta":{"content":"是"},"finish_reason":null}]}
{"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1752400000,"model":"gpt-5-2026-01-15",
 "choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_xxx","type":"function",
   "function":{"name":"get_weather","arguments":"{\"city\":\"Hangzhou\"}"}}]},"finish_reason":null}]}
{"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1752400000,"model":"gpt-5-2026-01-15",
 "choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}

finish_reason 在最后一个 chunk 出现,且通常伴随 usage 字段(部分实现仅在最后一个 chunk 给)。

1.6 工具调用

请求侧:

json
{
  "model": "gpt-5",
  "messages": [{"role": "user", "content": "杭州天气怎么样?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "获取指定城市的实时天气",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }
  }],
  "tool_choice": "auto"
}

响应侧 choices[].message.tool_calls:

json
{
  "id": "call_abc",
  "type": "function",
  "function": {"name": "get_weather", "arguments": "{\"city\":\"Hangzhou\"}"}
}

调用方执行工具后,把结果以 {"role":"tool","tool_call_id":"call_abc","content":"晴 25℃"} 回传 messages

1.7 finish_reason 取值

  • stop — 自然结束或命中 stop 序列
  • length — 命中 max_tokens / max_completion_tokens 上限
  • tool_calls — 模型调用了工具,等待工具结果
  • function_call — 旧 functions 端点保留值,新代码统一收敛到 tool_calls
  • content_filter — 内容被安全过滤器截断

参考来源:OpenAI Chat Completions API Reference / Function Calling Guide


2. OpenAI Responses API

2025 年起 OpenAI 推的 stateful 协议,是 Chat Completions 的继任者。核心差异:内置 state(previous_response_id / conversation)+ 内置工具 + 推理模型原语

2.1 端点与鉴权

text
POST https://api.openai.com/v1/responses
Authorization: Bearer $OPENAI_API_KEY
Content-Type: application/json

非流式直接返回完整 Response 对象;流式返回 SSE 事件序列(见 2.5)。Azure 镜像为 https://{resource}.openai.azure.com/openai/v1/responses

2.2 最小请求

json
{
  "model": "gpt-5",
  "input": "你好",
  "instructions": "You are a helpful assistant."
}

注意 input 而非 messages——input 既能传字符串(单轮),也能传数组(多轮 / 多模态 items)。

2.3 关键请求字段

字段类型说明
inputstring | array文本或多模态 items
instructionsstring替代 messages 中的 system 角色
modelstring必填
previous_response_idstring传入上一次响应的 id,服务端自动恢复上下文(省去客户端管理 history)
conversationobject多轮会话级 state({id} 引用已有会话)
toolsarray既支持自定义 function,也支持内置工具
tool_choicestring | object同 Chat Completions
parallel_tool_callsbool同 Chat Completions
truncationstringauto / disabled —— 超长上下文截断策略
storebool是否把响应存到 OpenAI 服务端,供 previous_response_id 复用
reasoningobject{effort: "low"|"medium"|"high", summary: "auto"|"concise"|"detailed"}
textobject{format: {type: "json_schema", ...}} 结构化输出
temperature / top_p / max_output_tokens / metadata同 Chat Completions,max_tokensmax_output_tokens 替代

2.4 最小响应

json
{
  "id": "resp_abc123",
  "object": "response",
  "created_at": 1752400000,
  "model": "gpt-5-2026-01-15",
  "status": "completed",
  "output": [
    {"type": "reasoning", "id": "rs_xxx", "summary": [{"type":"summary_text","text":"用户问天气..."}]},
    {"type": "message", "id": "msg_xxx", "role": "assistant",
     "content": [{"type": "output_text", "text": "杭州目前晴 25℃。", "annotations": []}],
     "status": "completed"}
  ],
  "usage": {"input_tokens": 24, "output_tokens": 18, "total_tokens": 42}
}

output 是混合 items 数组,type 可为 message / function_call / web_search_call / file_search_call / image_generation_call / code_interpreter_call / computer_call / mcp_call / reasoning 等。

2.5 流式事件

SSE 事件枚举(摘取主事件):

text
response.created           — 响应已创建
response.in_progress       — 处理中(伴随中间状态)
response.output_item.added — 新增一项 output(可能是 message / function_call / reasoning 等)
response.content_part.added — message 内新增一段(text / summary_text)
response.output_text.delta — 文本增量
response.function_call_arguments.delta — 工具调用参数增量
response.reasoning_summary_text.delta   — 推理摘要增量
response.completed         — 响应结束,伴随完整 output 与 usage
response.error             — 顶层错误事件

每条事件的 data 字段是 Response 对象的"增量切片",客户端按事件类型重组即可得到完整 Response

2.6 内置工具(Responses 独有)

json
{
  "model": "gpt-5",
  "input": "杭州和上海今天天气差异?",
  "tools": [
    {"type": "web_search"},
    {"type": "file_search", "vector_store_ids": ["vs_xxx"]},
    {"type": "code_interpreter", "container": {"type": "auto"}}
  ]
}
  • web_search — 模型自带联网搜索,返回 web_search_call item
  • file_search — OpenAI 托管向量库检索
  • code_interpreter — 沙箱执行 Python
  • image_generation — 调用 gpt-image-1 出图
  • computer_use — 操控远程浏览器(Computer-Use 模型)
  • mcp — 连接远程 MCP server(通过 server_label + server_url)

Chat Completions 里没有这些内置工具——客户端要自己接 RAG / 联网 / 代码执行。Responses 把它们标准化成同一种 tools 声明方式,统一走 output items 回流,极大降低 Agent 编排代码量。

2.7 与 Chat Completions 何时该选哪个

  • 新项目 / Agent:Responses(内置工具 + state 显著降低客户端复杂度)
  • 已有大量 Chat Completions 代码:继续用 Chat Completions,OpenAI 没有 deprecation 公告
  • 明确不想要 state 持久化:Chat Completions(Responses 默认 store: true)
  • 老 SDK / 老模型不支持 Responses:Chat Completions

参考来源:OpenAI Responses API Reference / Streaming events


3. Anthropic Messages API

Anthropic Claude 系列官方协议。与 OpenAI 的最大差别:system 不在 messages 里、必须 max_tokens、messages 角色只允许 user / assistant

3.1 端点与鉴权

text
POST https://api.anthropic.com/v1/messages
x-api-key: $ANTHROPIC_API_KEY
anthropic-version: 2023-06-01
Content-Type: application/json

anthropic-version 必填,目前推荐 2023-06-01(锁定日期型版本字符串,API 用 date-based versioning 而非 semver)。

3.2 最小请求

json
{
  "model": "claude-opus-4-5",
  "max_tokens": 1024,
  "system": "You are a helpful assistant.",
  "messages": [
    {"role": "user", "content": "你是谁?"}
  ]
}

3.3 最小响应(非流式)

json
{
  "id": "msg_abc123",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-4-5-20260115",
  "content": [
    {"type": "text", "text": "我是 Anthropic 训练的 AI 助手 ..."}
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 24,
    "output_tokens": 18,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0
  }
}

3.4 关键请求字段

字段必填类型说明
modelstring模型 ID
messagesarray仅允许 user / assistant 角色
max_tokensint单次输出上限,必填(OpenAI 默认不限)
systemstringsystem 提示,作为顶层字段而非消息角色
toolsarray函数定义,见 3.6
tool_choiceobject{type: "auto" | "any" | "tool", name: "..."}
temperaturefloat0–1,默认 1
top_pfloat0–1
stop_sequencesarray自定义停止序列
streambool默认 false
thinkingobject扩展思考 {type: "enabled", budget_tokens: N}
metadataobjectuser_id 等可追踪字段

3.5 流式事件(SSE,8 个核心类型)

text
message_start        — 响应开始,data.message 含 id/type/role/model/usage{input_tokens, output_tokens}
content_block_start  — 一段内容块开始,data.content_block.type ∈ text/tool_use/thinking/server_tool_use/web_search_tool_result/fallback
content_block_delta  — 内容块增量,data.delta.type ∈ text_delta(text)/input_json_delta(partial_json)/thinking_delta(thinking)/signature_delta/signature/citations_delta(citation)
content_block_stop    — 一段内容块结束
message_delta        — 顶层 delta(stop_reason/stop_sequence),data.usage 是**累计**值
message_stop         — 响应结束,无 payload
ping                 — 心跳,无 payload
error                — 错误,data.error.type ∈ api_error / overloaded_error / rate_limit_error / ...

流式结束时,message_delta.usage.output_tokens 是本轮累计值(官方文档明文警告),客户端要做差值计算。

3.6 工具调用

请求侧:

json
{
  "model": "claude-opus-4-5",
  "max_tokens": 1024,
  "tools": [{
    "name": "get_weather",
    "description": "获取指定城市的实时天气",
    "input_schema": {
      "type": "object",
      "properties": {"city": {"type": "string"}},
      "required": ["city"]
    }
  }],
  "messages": [{"role": "user", "content": "杭州天气怎么样?"}]
}

响应侧 content[].type == "tool_use":

json
{"type": "tool_use", "id": "toolu_abc", "name": "get_weather",
 "input": {"city": "Hangzhou"}}

调用方执行后,结果以 user 角色回传:

json
{"role": "user", "content": [
  {"type": "tool_result", "tool_use_id": "toolu_abc", "content": "晴 25℃"}
]}

3.7 stop_reason 取值

  • end_turn — 自然结束
  • max_tokens — 命中 max_tokens 上限
  • stop_sequence — 命中自定义 stop 序列
  • tool_use — 模型调用了工具,等待工具结果
  • pause_turn — 长对话暂停(用于 server-side 工具如 web_search)

注意与 OpenAI 的 finish_reason 命名风格不同:tool_use 对应 OpenAI 的 tool_calls

3.8 thinking 字段(扩展思考)

json
{
  "model": "claude-opus-4-5",
  "max_tokens": 4096,
  "thinking": {"type": "enabled", "budget_tokens": 2048},
  "messages": [{"role": "user", "content": "证明哥德巴赫猜想"}]
}

启用后响应 content 数组中可能出现 {"type":"thinking", "thinking":"..."}{"type":"text", "text":"..."} 两种块,流式里以 thinking_delta 增量推送。

参考来源:Anthropic Messages API / Messages Streaming / Extended Thinking


4. Google Gemini API

Google Gemini 系列官方协议,Google AI Studio 直接可用。最大差异:messages 变成 contents[].parts[]、工具调用不嵌 tool_calls 而是 functionCall part、safetySettings 是 Gemini 独有。

4.1 端点与鉴权

text
POST https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key=$GEMINI_API_KEY
POST https://generativelanguage.googleapis.com/v1beta/models/{model}:streamGenerateContent?alt=sse&key=$GEMINI_API_KEY
Content-Type: application/json

三种鉴权等价:

  1. ?key=$GEMINI_API_KEY(查询参数,文档示例主流)
  2. x-goog-api-key: $GEMINI_API_KEY(header,SDK 内部用)
  3. Authorization: Bearer <OAuth access token>,scope 为 https://www.googleapis.com/auth/generative-language

2026 年起 Google 推荐迁移到 Interactions API(POST /v1beta/interactions),但 :generateContent / :streamGenerateContent 仍完整文档化且受支持。

4.2 最小请求

json
{
  "contents": [
    {"role": "user", "parts": [{"text": "你是谁?"}]}
  ]
}

4.3 最小响应(非流式)

json
{
  "candidates": [
    {
      "content": {"role": "model", "parts": [{"text": "我是 Google 训练的大模型 ..."}]},
      "finishReason": "STOP",
      "index": 0,
      "safetyRatings": [
        {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE"}
      ]
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 24,
    "candidatesTokenCount": 18,
    "totalTokenCount": 42
  },
  "modelVersion": "gemini-2.5-flash"
}

4.4 关键请求字段

字段类型说明
contentsarray对话历史,每项 {role: "user"|"model", parts: [...]}
parts[]arraytext / inline_data(mime_type, data) / file_data(file_uri, mime_type) / function_call(name, args) / function_response(name, response)
systemInstructionobject顶层字段,{parts: [{text: "..."}]}
toolsarray[{functionDeclarations: [{name, description, parametersJsonSchema}]}]
toolConfigobject{functionCallingConfig: {mode: "NONE"|"AUTO"|"ANY", allowedFunctionNames: [...]}}
generationConfigobject温度、token 上限、JSON schema 等,见 4.5
safetySettingsarray[{category: "HARM_CATEGORY_*", threshold: "BLOCK_NONE"|...}]
cachedContentstring引用已缓存上下文(用于 context caching)

4.5 generationConfig 子字段

字段类型说明
temperaturefloat0–2
topPfloat0–1
topKint核采样的 K 值
maxOutputTokensint单次输出上限
responseMimeTypestring"text/plain" / "application/json"
responseSchemaobjectJSON schema,要求 responseMimeType="application/json" 才生效
seedint复现性
presencePenalty / frequencyPenaltyfloat重复惩罚
responseLogprobs / logprobsbool / int对数概率
stopSequencesarray自定义停止序列
thinkingConfigobject{thinkingBudget: N, includeThoughts: bool} 控制推理深度

4.6 工具调用

请求侧:

json
{
  "contents": [{"role": "user", "parts": [{"text": "杭州天气怎么样?"}]}],
  "tools": [{
    "functionDeclarations": [{
      "name": "get_weather",
      "description": "获取指定城市的实时天气",
      "parametersJsonSchema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }]
  }],
  "toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}
}

响应侧:candidates[0].content.parts 包含 functionCall part:

json
{"functionCall": {"name": "get_weather", "args": {"city": "Hangzhou"}}}

调用方执行后,把结果作为 user 角色、functionResponse part 回传:

json
{"role": "user", "parts": [{
  "functionResponse": {"name": "get_weather", "response": {"weather": "晴 25℃"}}
}]}

4.7 finishReason 取值

  • STOP — 自然结束
  • MAX_TOKENS — 命中 maxOutputTokens
  • SAFETY — 安全拦截,响应内容会被清空
  • RECITATION — 命中引用/版权拦截
  • OTHER — 其他异常
  • BLOCKLIST / PROHIBITED_CONTENT / SPII — 细分类别的安全拦截

安全相关类别会同时出现在 safetyRatings[] 中,客户端可以细分原因。

4.8 流式响应

不传 ?alt=sse 时,流式响应是 NDJSON(每行一个完整的 generateContent 响应对象)。传 ?alt=sse 才是 SSE 协议。两种模式下每行的 candidates[0].content.parts[0].text 都是累计的增量,客户端按 usageMetadata 增量或文本长度差值自行处理。

4.9 多模态传图

json
{"contents": [{"role": "user", "parts": [
  {"text": "图里有什么?"},
  {"inline_data": {"mime_type": "image/jpeg", "data": "<base64>"}}
]}]}

或用 file_data 传 File API URI:

json
{"file_data": {"mime_type": "image/png", "file_uri": "https://generativelanguage.googleapis.com/..."}}

参考来源:Google Gemini API Reference / Gemini Text Generation Guide / Function Calling


5. OpenAI Compatible API

不是一条协议,而是"行业事实标准"的扩散名——所有选择暴露 /v1/chat/completions 兼容端点的服务。

5.1 形态

text
POST {base_url}/v1/chat/completions
Authorization: Bearer <api_key>
Content-Type: application/json

base_url 替换成对应厂商:

实现base_url默认模型示例
Ollamahttp://localhost:11434/v1llama3.2 / qwen2.5 / gpt-oss
vLLMhttp://localhost:8000/v1启动时指定
DeepSeekhttps://api.deepseek.com/v1deepseek-chat / deepseek-reasoner
阿里云百炼(dashscope)https://dashscope.aliyuncs.com/compatible-mode/v1qwen-plus / qwen-max
SiliconFlowhttps://api.siliconflow.cn/v1Qwen/Qwen2.5-72B-Instruct
Togetherhttps://api.together.xyz/v1meta-llama/Llama-3-70b-chat-hf
Groqhttps://api.groq.com/openai/v1llama-3.1-70b-versatile

5.2 字段支持度分级

L0 几乎都支持(事实标准最小集):

model / messages / temperature / top_p / stream / max_tokens / n / stop

L1 多数兼容端点支持,但有差异:

  • tools / tool_choice — 大部分支持,但 JSON schema 严格度、strict 字段、流式 tool_calls 增量命名有差异
  • response_format — 部分仅支持 {type: "json_object"},json_schema 严格模式仅 OpenAI 官方与 vLLM(guided JSON)支持
  • seed — Ollama / vLLM 支持,部分云厂商忽略
  • frequency_penalty / presence_penalty — Ollama 与部分国产模型不支持

L2 仅原生 OpenAI 支持或特定实现:

  • parallel_tool_calls — 仅 OpenAI 原生
  • logprobs / top_logprobs / logit_bias — 仅 OpenAI 原生 + vLLM 兼容端点
  • reasoning_effort — 仅 OpenAI 原生(o / gpt-5 系列)
  • service_tier / prompt_cache_key / safety_identifier — 仅 OpenAI 原生
  • metadata / store / previous_response_id — OpenAI Responses 独有

5.3 典型实现的差异点

  • Ollamausage 字段返回全 0(免费本地不计费);finish_reason 总是 stop;tools 完整支持;支持 format 参数做 JSON 模式;支持 keep_alive 控制模型常驻
  • vLLM — 支持 guided_json / guided_choice / guided_regex(覆盖 response_format);usage 返回完整 token 数;tool_choice 支持完整;logprobs 支持
  • DeepSeekdeepseek-reasoner 推理模型会泄漏 reasoning_content 字段(类似 Responses 的 output[].reasoning)
  • 阿里云百炼 dashscope/compatible-mode/v1 完整兼容 Chat Completions;max_tokens 字段命名为 max_tokens(不是 max_completion_tokens);tools 支持完整
  • SiliconFlow — 字段映射完整,主要提供开源模型托管

5.4 为什么 OpenAI Compatible 成为事实标准

  1. 历史起点早:2020 年 OpenAI 开放 GPT-3 API 时就确立了 /v1/chat/completions 的形状,当时没有更优的竞品规范
  2. 生态先发优势:LangChain、LlamaIndex、Dify、Spring AI 等主流框架默认对接这个形状
  3. 本地推理框架跟跑:Ollama、vLLM、llama.cpp、LM Studio、Jan 都主动暴露兼容端点,因为这等于免费接入整个生态
  4. 国产模型兼容:DeepSeek、阿里云百炼、SiliconFlow、智谱、月之暗面、字节豆包等均提供 compatible-mode,原因是"客户已经在用 OpenAI SDK 写代码了,改 endpoint 改 model 名就行"
  5. 协议本身简洁:HTTP + JSON + SSE,任何语言都能 5 行代码起一个客户端,无 SDK 也能用 curl

副作用:任何框架报告"功能不支持"时,先看它是不是仅当 OpenAI 官方 API 在用——切到 compatible 端点(尤其是本地 Ollama)经常踩到 usage=nullfinish_reason=stop 退化等坑。

参考来源:Ollama OpenAI Compatibility / vLLM OpenAI Server / DeepSeek API Docs / 阿里云百炼 OpenAI 兼容


6. 五协议横向对照表

维度OpenAI Chat CompletionsOpenAI ResponsesAnthropic MessagesGoogle GeminiOpenAI Compatible
端点POST /v1/chat/completionsPOST /v1/responsesPOST /v1/messagesPOST /v1beta/models/{m}:generateContent / :streamGenerateContent?alt=ssePOST {base_url}/v1/chat/completions
鉴权Authorization: BearerAuthorization: Bearerx-api-key + anthropic-version?key=x-goog-api-key 或 OAuthAuthorization: Bearer
对话字段messages[]input (string/array)messages[]contents[].parts[]messages[]
system 位置messages[].role=systeminstructions 顶层system 顶层systemInstruction.parts[] 顶层messages[].role=system
messages 角色system/user/assistant/toolinput items 多态user/assistant 唯一两种user/model(contents)system/user/assistant/tool
max_tokens可选(max_tokensmax_completion_tokens)max_output_tokens(可选)必填generationConfig.maxOutputTokens(可选)可选
单次多候选choices[] 数组(由 n 控制)单个 output 数组(多 item)单条 messagecandidates[] 数组(由 candidateCount 控制)choices[] 数组(同 Chat)
工具声明tools[].functiontools[].function 或内置 typetools[].{name,description,input_schema}tools[].functionDeclarations[]tools[].function
工具返回choices[].message.tool_calls[]output[].type=function_callcontent[].type=tool_useparts[].functionCallchoices[].message.tool_calls[]
工具结果回传messages[].role=tool,tool_call_id同 input 多 itemmessages[].content[].type=tool_resultparts[].functionResponsemessages[].role=tool
tool_choice"auto"/"none"/"required"{type:function,name}同 Chat{type:auto/any/tool,name}toolConfig.functionCallingConfig.mode ∈ {NONE,AUTO,ANY}"auto"/"none"/"required"
结构化输出response_format.json_schematext.format.json_schema无原生 JSON mode(走 prompt + tools)responseMimeType + responseSchema取决于实现
流式协议SSE,object=chat.completion.chunk,delta.{role,content,tool_calls}SSE 事件枚举(response.output_text.delta 等)SSE,8 类事件(message_start / content_block_delta / message_delta / ...)NDJSON 或 SSE(?alt=sse),每行累计 parts同 Chat Completions
结束原因字段choices[].finish_reason隐式在 output items + response.completedstop_reasoncandidates[].finishReasonchoices[].finish_reason
结束原因取值stop/length/tool_calls/function_call/content_filter隐式 status=completed / incomplete(子原因 max_output_tokens)end_turn/max_tokens/stop_sequence/tool_use/pause_turnSTOP/MAX_TOKENS/SAFETY/RECITATION/OTHER/BLOCKLIST/SPII同 Chat Completions
usage 字段usage.{prompt_tokens,completion_tokens,total_tokens}usage.{input_tokens,output_tokens,total_tokens}usage.{input_tokens,output_tokens,cache_creation_input_tokens,cache_read_input_tokens}usageMetadata.{promptTokenCount,candidatesTokenCount,totalTokenCount,thoughtsTokenCount,cachedContentTokenCount}同 Chat,部分实现返回 0 / null
状态延续客户端维护 history服务端 previous_response_id / conversation客户端维护 history(client 用 prompt caching 优化)客户端维护 history(client 用 context caching 优化)客户端维护 history
推理/思考reasoning_effort + 隐藏 reasoningreasoning 原语 + output[].reasoningthinking block + thinking_deltathinkingConfig.thinkingBudget + 隐藏 reasoning取决于实现
多模态输入messages[].content[] 多 part(text/image_url/input_audio)input items 多模态content[].type ∈ text/image/documentparts[].{text,inline_data,file_data}messages[].content[](取决于实现)
典型 base_urlhttps://api.openai.com/v1https://api.openai.com/v1https://api.anthropic.comhttps://generativelanguage.googleapis.com/v1beta见 5.1

7. 实战选型建议

如果你是在写一个"小到能塞进一个脚本"的智能体:

  • 默认走 OpenAI Compatible 端点——任何 client = OpenAI(base_url=..., api_key=...) 起手,Ollama / DeepSeek / 阿里云百炼切换就是改 base_url 和 model 名
  • 工具调用场景确认目标实现的 tool_choice / parallel_tool_calls 支持度
  • 流式体验必须自己拼 SSE / NDJSON(stream=True 时 SDK 帮你拼)

如果你在做生产级 Agent / 多工具调用 / 联网搜索:

  • OpenAI 系:Responses API(内置 web_search / file_search / code_interpreter / mcp,状态延续省客户端代码)
  • Anthropic 系:Claude 系列直接走 Messages,Extended Thinking 用 thinking
  • 多模态重的场景(Gemini 系列原生强):走 Gemini 原生 API,responseSchema 是结构化输出最干净的写法

如果你的应用要"模型可换":

  • 抽象一个内部表示层(消息 list + 工具 list + 流式 delta),在每家协议层做适配
  • 至少要处理四类差异:system 位置、工具调用命名、finish_reason/stop_reason 命名风格、usage 字段子字段
  • 不要假设所有兼容端点都支持 parallel_tool_calls / response_format.json_schema / reasoning_effort

8. 一句话总结

  • OpenAI Chat Completions 是事实标准的"原型",多数 SDK 与兼容端点的默认形态
  • OpenAI Responses 是 Chat 的 stateful 继任,内置工具 + 服务端 state,新项目首选
  • Anthropic Messagessystem / max_tokens / tool_use 都拆到顶层或独立字段,流式用 8 类事件而非单一 delta
  • Google Gemini 把 messages 拆成 contents[].parts[],工具调用以 part 形式存在,多了 safetySettingsfinishReason 大类
  • OpenAI Compatible 是行业扩散名,选 Ollama / vLLM / DeepSeek / 阿里云百炼 / SiliconFlow 之前,先确认它的 usage / finish_reason / tools 实际支持度——兼容性 ≠ 等价

掌握这五条协议的差异,以后看任何一个框架的报错,都能在 SDK 之下自己拉一段 curl 验证协议层到底发生了什么——这才是"会用 LLM API"和"被 SDK 哄着用"的差别。