openai兼容接口规范

接入与开发

把 OpenAI 兼容接口的字段规范与协议约定逐项拆开,讲清哪些字段必须对齐、哪些可以缺省、缺了会怎样。

你可能遇到过这种情况:同一段代码换一家中转站就报参数错,或者明明传了字段模型却当没看见。问题多半不在代码,而在各家对 OpenAI 兼容接口的实现口径不一致。这篇把请求与响应里那些字段约定、必填与选填边界、常见偏离写法讲清楚,给你一份能对照排查的清单。

同一段代码换成另一家中转站就报参数错,或者明明传了字段对方却当没看见——这种情况多半不是你的代码写错了,而是各家对 OpenAI 兼容接口的实现口径不一样。所谓「兼容」,往往只保证主干结构能对上,细枝末节的字段支持程度、默认值、返回结构差异不小。

这篇不讲概念,直接给一份能对照排查的字段清单:先判断你面对的是哪种程度的兼容,再逐项确认哪些字段是地基、哪些可以缺省、缺了会怎样,最后给一套十分钟就能跑完的自查流程。全程不写死任何数字,需要具体价格或模型资料时到站内页面核对。

「兼容」到底承诺了什么

兼容通常只保证三件事:请求路径对得上、鉴权头格式一致、消息体主干结构能解析。它不承诺所有字段都被支持,也不承诺语义完全一样。接入前先搞清楚自己面对的是哪种程度,比事后一个个试错省事得多。

兼容程度表现判断方式不适用场景
只认核心字段多余的字段被忽略,不报错也不生效传一个差异明显的取值,看输出有无变化需要精细控制采样行为时
核心加部分扩展常用扩展能认,冷门字段直接丢逐字段做差异测试依赖某家私有字段时
字段全认但语义有偏差字段名一样,实际含义或上限不同比对文档与实测边界需要严格复现某家行为时
  • 拿一份最小请求先跑通,确认路径与鉴权没问题,排除网络因素;
  • 在最小请求上每次只加一个字段,观察返回是否被静默忽略;
  • 对关键字段传两个差异明显的取值,看输出是否有可观察变化;
  • 把每轮结果记成一张小表,接入时直接对照,别靠记忆。

请求体骨架:哪些字段是地基

请求体里有三项几乎是所有实现的公共地基:模型标识、消息数组、是否流式。这三项缺任何一项,大概率直接报错而不是被忽略。消息数组内部的角色与内容结构也要固定,角色名拼错往往不会报错,而是被当成无效项丢掉,表现就是模型「答非所问」。

采样类字段属于可传可不传。不传时由服务端默认值决定,而不同实现的默认值可能不一样——这意味着同一段代码在两家中转站上跑,输出风格可能不同,别急着怀疑模型,先怀疑默认值。

模型标识
告诉服务端用哪个模型,多数实现必填,写错通常直接报错而不是回退默认
消息数组
对话主干的载体,结构固定,角色名必须用约定写法
是否流式
决定返回是整包还是一行行推送,影响你的解析分支
  1. 把基线请求写成常量把最小可用的请求体固化下来,排查任何问题时先换回基线,确认基线还能跑通
  2. 逐字段加法在基线上每次只加一个字段,记录是否报错、是否生效
  3. 差异取值验证对同一个字段传两个差异明显的值,看输出是否真的变化,变化才算被支持

必填与选填的边界怎么划

划边界只有一个判断标准:服务端能不能自己补。能补的是选填,补不了的是必填。模型标识和消息内容服务端补不了,所以通常必填;上限类、惩罚类、随机性类字段都能靠默认值补上,所以可省略。

字段类别是否必填缺省后果验证方式
模型标识通常必填直接报错去掉后看报错信息
消息内容通常必填请求无效去掉后看报错信息
随机性类选填用服务端默认值传两个极端值比输出
上限类选填用服务端默认值传小值看是否被截断
惩罚类选填用服务端默认值传大值看是否重复变少

最容易踩的坑是把「我传了没报错」当成「被支持了」。静默忽略是兼容层最常见的做法——不报错,也不生效。判断它到底有没有生效,只能靠可观察的输出差异,不能靠有没有报错。

不报错不等于被支持,能观察到变化才算数。

响应结构:解析前先确认这几点

解析响应时,最常见的错误是直接取顶层字段当正文。回复文本通常藏在候选数组的第一项里,少一层取值就会拿到空值或者结构体。动手写解析前,先把原始返回打印一遍,看清层级再写代码。

用量统计块是实现差异最大的部分。有的实现字段齐全,有的缺项,有的干脆不返回。代码里必须做空值兜底,否则一条缺字段的响应就能让整条链路挂掉。结束原因字段决定你是正常结束还是被截断,长回答场景必须读它。

  • 先打印原始返回,确认层级再写取值逻辑;
  • 候选数组取第一项,不要直接取顶层;
  • 用量块每个字段都做空值判断,别假设一定存在;
  • 结束原因读到「被截断」时要判断是否该继续追问;
  • 把这三类信息写进日志,方便后续复盘慢与贵。

流式模式下的协议约定

流式返回是若干条数据行拼接而成的,每条以固定前缀开头,最后有一条终止标记。增量内容藏在候选对象的差异字段里,不是每一条都带完整文本,拼接逻辑写错就会出现重复或丢字。

  1. 确认首条有内容看第一条推送是否带有效内容,如果首条就是空心跳,说明推送格式和你预期不同
  2. 确认终止标记到达读到终止标记才算正常结束,没读到就是中途断连,要触发超时与重试判断
  3. 确认拼接结果把增量拼成完整文本后和一次性请求的结果对比,看是否有重复或截断

心跳与空行必须跳过,不能当成内容塞进结果里。中途断连要有超时与重试判断,否则用户会看到一段永远不结束的回答。流式的问题排查顺序固定:先看首条有没有内容,再看终止标记到没到,最后看拼接结果对不对。

各家实现偏离的常见处,一份对照清单

跨实现时最容易出问题的地方集中在命名风格、错误结构、取值范围这三块。字段命名的大小写与下划线风格不统一,错误返回可能有两种结构风格,同一字段在不同实现里的取值范围也可能不同。别假设上限一致。

偏离点典型表现应对做法
命名风格大小写、下划线不一致跨实现时留一层字段名映射
错误结构两种错误风格并存两套错误解析都写上
取值范围上限或合法区间不同在适配层做钳制,不假设一致
返回层级用量块字段缺项每个字段做空值兜底

建议做法是把「我方发出」和「对方返回」两层各自归一化,中间加一层薄适配器。适配器只做字段映射、范围钳制和空值兜底,不掺业务逻辑,这样换一家中转站时只需要改适配器,不用动主流程。

下一步动手前先去站内核对目标中转站的口径和当时的数字,再决定适配层怎么写。

十分钟自查:你的接入层够不够稳

下面这套自查按顺序跑,每步都有明确的通过标准。跑完之后,你对自己的接入层能扛到什么程度就有数了。任何一步没过,先解决它再往下走。

  1. 最小请求验证连通与鉴权只带模型标识、最小消息内容、是否流式三项,能返回就说明路径和鉴权没问题,剩下的报错都是字段层面的
  2. 逐字段加法验证支持度在最小请求上每次加一个字段,观察是否报错、输出是否有可观察变化,变化的才算真被支持
  3. 构造截断与报错各一次用很小的上限值制造一次被截断,再故意传一个非法参数制造一次报错,确认两个解析分支都能走通
  4. 把用量与结束原因写进日志用量块和结束原因落到日志里,后续算成本和查原因时不用重新发请求复现
  • 连通与鉴权过了,再谈字段问题,别混在一起排查;
  • 字段支持度靠输出差异判断,不靠有没有报错;
  • 截断和报错两个分支必须都走通过,否则上线必踩;
  • 用量与结束原因进日志,是后续复盘的前提。
接入层的稳,不是一次调通,而是换一家也能在十分钟内调通。

常见问题

兼容接口能保证和原厂行为完全一样吗?

不能。兼容通常只对齐主干结构和字段名,语义细节、默认值、错误结构都可能有差异。稳妥做法是把兼容层当成一个独立实现来对待,关键字段自己验证一遍,别直接照搬原厂文档里的期望。

为什么我传的字段没报错,但看起来没生效?

大概率是被静默忽略了。兼容层对不认识的字段常常直接丢掉而不是报错。验证方法很简单:给这个字段传两个差异明显的取值,看输出有没有可观察的变化;没变化基本就是没被采纳。

响应里的用量统计对不上怎么办?

先把用量块当成可选字段处理,缺失时用自己的估算兜底,别让业务逻辑依赖它。同时把它记进日志,跑一段时间再对比口径差异。哪家怎么算,可以到 /tools/token-price-calculatorToken 单价换算 这类工具页对照着看自己的账。

流式和非流式要写两套解析吗?

解析入口可以共用,但拼接逻辑必须分开。流式要处理分片、跳过心跳、判断终止标记;非流式一次拿全量。把两者收敛到同一个返回对象上,业务层就不用关心底层是哪种模式。

换一家中转站要改多少代码?

如果一开始就把字段归一化做在适配层里,通常只改配置不改业务代码。省事的做法是把模型标识、接口地址、超时都抽成配置项,切换时只动这几个值。具体路径和参数写法可以先到 /sites中转站目录 里挑几家对比着看。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。