配置模型客户端时,除了地址、密钥和模型名,有时还会遇到这样一项:
protocol: openai-chat它会和 model 一起发给服务端吗?如果地址已经填好了,为什么还要选协议?
这里的 protocol 用于让客户端选择一套请求与响应的处理方式。openai-chat 表示按 OpenAI Chat Completions 的格式与服务端交互。客户端先读这个配置,再决定发出什么请求、怎样读回结果。
protocol 和 openai-chat 是这里讨论的客户端配置约定,具体字段名和可选值要看所用工具;它们不是所有 SDK 共有的配置项。下文用接口报文解释这个开关,资料核对于 2026-11-04。
配置里写的,不一定都在请求体里
假设用户只说了一句“你好”。客户端要把它送给模型服务,配置中的几项信息会在不同位置起作用:
| 配置 | 客户端用它做什么 |
|---|---|
base_url | 确定 API 基础地址,再按调用入口拼接路径 |
protocol | 选择请求组装、响应解析等适配逻辑 |
| API Key | 按目标接口要求构造认证信息 |
model | 指定要调用的模型,通常写入请求体 |
比如选择 Chat Completions 后,客户端会构造 messages,调用对应端点;不会因为本地配置写了 protocol: openai-chat,就在 JSON 中自动添加同名字段。OpenAI 的 Chat Completions 接口定义展示了实际接受的请求字段。
配置文件负责告诉客户端怎样工作,HTTP 请求则是客户端工作后的结果。 要判断某一项有没有发出去,应当看最终的 URL、请求头和 body。
选中 openai-chat,一句“你好”怎样往返?
设基础地址为 https://llm.example.com/v1。这是虚构地址;以下是普通非流式文本请求的教学报文,省略认证头与部分响应字段,没有调用在线模型。
客户端在基础地址后追加 /chat/completions,请求会呈现为:
POST https://llm.example.com/v1/chat/completions
Content-Type: application/json{
"model": "example-model",
"messages": [
{"role": "user", "content": "你好"}
],
"stream": false
}假设服务端返回下面的简化响应:
{
"choices": [
{
"message": {"role": "assistant", "content": "你好,有什么可以帮你?"},
"finish_reason": "stop"
}
]
}客户端从 choices[0].message.content 读出文字,界面才会显示“你好,有什么可以帮你?”。选协议时,选中的既有发请求的规则,也有读响应的规则。
这条取值路径有前提:它处理的是普通非流式文本响应。流式 Chat Completions 通常逐块读取 choices[0].delta;工具调用还需要处理 tool_calls,此时 message.content 可以为空。不能把“取一段文字”当成完整的协议实现。OpenAI 请求、响应及流式示例
换成 Anthropic,哪些地方会跟着变?
同一句“你好”,换用 Anthropic Messages 接口时,调用端点变为 /v1/messages,响应以 content 内容块组织。请求中仍然有 messages,所以差异不能概括成“有没有 messages”。下面对比的是常见文本交互形状:Claude Messages 接口定义。
| 对照位置 | OpenAI Chat Completions | Anthropic Messages |
|---|---|---|
| 官方完整端点 | https://api.openai.com/v1/chat/completions | https://api.anthropic.com/v1/messages |
| 用户消息 | messages 中的 user 消息 | messages 中的 user 消息 |
| 系统提示的常见写法 | messages 中的 system/developer 消息,依模型支持情况选择 | 顶层 system 字段 |
| 普通文本响应 | choices[0].message.content | content 中 type: text 块的 text |
Anthropic 的简化响应可以长这样:
{
"role": "assistant",
"content": [
{"type": "text", "text": "你好,有什么可以帮你?"}
],
"stop_reason": "end_turn"
}如果客户端仍按 Chat Completions 解析,就找不到 choices。即使 HTTP 请求成功了,界面也可能没有文字或直接报解析错误。反过来,只换响应解析也不够:请求字段、认证与版本头、工具调用及流式事件,都需要由对应适配逻辑处理。
另外,协议名描述的是接口格式。第三方模型服务也可以提供这些兼容接口;选择 OpenAI 格式,并不等于请求一定发往 OpenAI,也不等于底层一定运行 OpenAI 的模型。
为什么换协议还要去掉地址里的 /v3?
这就需要把协议格式和服务商路由分开看了。以火山方舟 Coding Plan 为例,官方为两种兼容接口给出了不同的基础地址:
| 兼容接口 | Base URL |
|---|---|
| OpenAI | https://ark.cn-beijing.volces.com/api/coding/v3 |
| Anthropic | https://ark.cn-beijing.volces.com/api/coding |
这里“不带 /v3”是方舟的地址约定。换另一家服务,不能照着删路径,应该查它为目标协议提供的 Base URL。方舟 Coding Plan 接入文档
基础地址也不一定是最终请求地址。客户端可能继续追加 /chat/completions 或 /v1/messages;有些工具则要求填写完整端点。应当连同工具的拼接规则一起核对,避免把路径重复写两次。
因此,切换时要让三件事对齐:客户端选中的协议、服务商提供的协议入口,以及客户端最终拼出的 URL。 只改开关,可能把新的请求格式发到旧的路由;只改地址,又可能继续用旧格式收发。
连不上时,先看实际发出了什么
遇到问题,我会先看脱敏后的最终请求和原始响应,再判断故障落在哪一层:
- 返回 404:先核对最终路径,有没有重复的
/v1、误留的/v3,或把完整端点当成基础地址。 - 返回参数校验错误:对照目标接口检查 body,确认客户端实际组装的格式与入口相符。
- 返回成功却显示空白:检查原始响应是
choices还是content,以及客户端是否把流式内容当成普通 JSON 读取。
这些是排查线索,状态码本身不足以确定原因。修正后,仍用同一句“你好”验证完整往返:路径正确、请求体被接受、返回文字被正确显示。
以后再看到 protocol: openai-chat,就可以沿着这条链去理解:客户端选择 Chat Completions 适配逻辑,按对应格式构造请求,再按同一接口规则解释响应。 更完整的跨厂商工具往返,可以继续看调用不同厂商的 LLM,究竟要适配什么?。