API 与错误码
API 兼容性与参数
哪些字段原样透传、流式响应里多出来的那一块、以及为什么自动重试会重复扣费。
参数是透传的
请求体里的 OpenAI 字段(model / messages / stream / max_tokens /
temperature / tools 等)原样转发给上游,我们不改写、不补默认值。
也就是说:这些参数的确切语义以上游模型自己的文档为准。
同一个 temperature 在不同厂商的模型上表现不完全一样,某些模型会忽略它不认识的字段。
我们不在中间做"翻译",因为那会让你调出来的结果和直接对着上游文档预期的不一致。
model 必须是「模型与价格」页上那个完整名字,而且要在你这把密钥的白名单内。
三个端点,别打错
| 端点 | 收什么模型 |
|---|---|
POST /v1/chat/completions |
对话类模型 |
POST /v1/embeddings |
向量模型 |
GET /v1/models |
—— |
拿对话模型去打 /v1/embeddings(或者反过来)会得到
400 model_not_supported_for_endpoint,message 里会说明它是哪一类模型。
这是提前拦下来的,不会白花一次上游调用。
GET /v1/models 默认返回全部;想只要对话模型可以带一个非标准的查询参数
?modality=chat。不带它的行为不会变。
流式响应里会多出一块
传 "stream": true 时,网关会强制打开 usage 上报
(相当于替你加上 stream_options.include_usage=true,你没传也会加)。
所以流的末尾会多一个这样的块:
data: {"choices":[],"usage":{"prompt_tokens":..,"completion_tokens":..,"total_tokens":..}}
data: [DONE]
它的 choices 是空数组。如果你的解析代码假设每个块都有 choices[0],
这里会抛异常 —— 按 OpenAI 官方 SDK 写的代码没有这个问题,
自己手写 SSE 解析的要留意。
加这一块是为了拿到末尾 usage 用来计费。断流时拿不到它, 但已经产生的 token 照常计费。
/v1/embeddings 不支持流式(它一次返回完整向量)。
上下文超限是按输入判的
输入本身就超过该模型声明的上下文长度时,返回
400 context_length_exceeded,转发前就拦下。
判断只看输入,不把 max_tokens 算进去 —— 那是在猜你会生成多少,
猜错了会拒掉本来能跑通的请求。所以"输入 + max_tokens 超了"这种情况不会在这里被拦,
它由上游按自己的规则处理。
⚠️ 自动重试会重复扣费
网关不做跨请求去重。这与 OpenAI 官方对该端点的行为一致 ——
它同样不支持 Idempotency-Key。
后果很实在:你的 SDK 因为网络超时自动重发同一个逻辑调用时, 网关会把它当成一次全新请求,产生第二次真实扣费。 第一次可能其实已经在上游跑完了,只是响应没回到你手上。
所以:
- 检查你用的 SDK 的默认重试次数(官方
openaiSDK 默认会重试),按场景调低或关掉; - 需要重试时,在你自己这一侧做去重(比如按业务 id 记一下这一笔发过没有);
- 每个响应里的
request_id是排查这类重复扣费的唯一线索,记下来。
错误结构
统一是 OpenAI 兼容的形状:
{ "error": { "message": "…", "type": "…", "param": null, "code": "…" } }
参数错误(400)的 code 直接透传上游的原值 —— 那种情况通常是请求体本身写错了,
上游给出的说明比我们转述得准。其余错误码及各自的下一步见「错误码与限流」。