怎么用标准 OpenAI 格式调用各家大模型

模型与算力

给做多模型接入的开发者讲清:怎么用一套标准 OpenAI 兼容格式调用各家大模型,从端点、鉴权、参数差异到返回体解析和迁移排查。

你可能已经写过一版基于标准 OpenAI 格式的调用代码,换模型时以为只改个 base_url 和模型名就行,结果报 404、字段对不上、流式断掉、多模态传不进去。这篇不评价哪家模型好,只讲接入层的活:端点怎么拼、鉴权放哪、哪些参数各家不认、返回体哪些字段会缺、以及怎么按顺序排查。

你可能已经写过一版按标准 OpenAI 格式发请求的代码,换模型时以为只改 base_url 和模型名就行,结果要么 404,要么参数被忽略,要么流式断在半路,多模态干脆传不进去。这篇不评价哪家模型好,只讲接入层的活:端点怎么拼、鉴权放哪、哪些参数各家不认、返回体哪些字段会缺,以及出问题时按什么顺序排查。

先明确一个预期:所谓「OpenAI 兼容」,兼容的是调用接口的形状,不是模型能力。形状对了,代码能跑通;能力层面的差异,比如上下文长度、是否支持工具调用、图片怎么传,仍然要一家一家试。所以下面所有的判断标准都围绕一个目标:把你的业务代码和厂商差异隔离开。

先搞清「OpenAI 兼容」到底兼容了哪一层

多数厂商说的兼容,实际只覆盖三层:HTTP 路径形状、请求体里的字段名、返回体的结构。模型怎么推理、支不支持某个能力,完全不在兼容范围内。所以别把「兼容」理解成「可以随便换」,它只保证你的调用代码不用大改,不保证行为一致。

兼容层次通常能对上常见对不上的地方
HTTP 路径资源路径和动作命名版本段前缀、结尾斜杠、大小写
请求体字段消息数组、角色、输出长度上限采样参数、停止词、工具调用相关字段
返回体结构选项数组、消息内容、结束原因用量统计、流式增量字段、错误体结构
模型能力不保证上下文长度、多模态形式、并发上限
  • 先确认兼容是官方声明还是社区适配层,官方声明的路径和字段通常更稳定,适配层可能随时跟着上游改
  • 不适用的情况:厂商只做「类 OpenAI」命名但路径不同,或者只给自家 SDK 不开放原始 HTTP,这时候硬套标准格式会一直报错
  • 如果对方文档里明确写了「兼容 OpenAI SDK」,通常意味着可以直接用官方 SDK 改 base_url,但仍要单独验证流式和工具调用

端点拼接与鉴权:多数 404 和 401 出在这一步

base_url 和后面那段路径怎么拼,各家规则不一样。有的 base_url 已经包含版本段,你再加一次就变重复;有的需要在 base_url 后面补完整资源路径;有的对结尾斜杠敏感。鉴权也一样,请求头的字段名、是否支持自定义头、密钥前缀格式,都以对方文档为准,不要靠猜。

  1. 先用最简请求打连通性只带鉴权和一条最短的用户消息,不带任何可选参数。返回正常说明端点和鉴权没问题,返回 404 先查路径拼接,返回 401 先查请求头字段名和密钥是否被截断。
  2. 再逐步加参数连通之后一次只加一类参数,加完立刻看返回。这样出问题时能定位到具体是哪类参数不被支持。
  3. 把 base_url 和路径拼接收敛到一处不要让每个调用点自己拼字符串,统一走一个函数,里面按厂商标识决定要不要补版本段、要不要去掉多余斜杠。以后加厂商只改这一个地方。
base_url
服务地址前缀,有的已含版本段,有的不含,决定你后面要不要再补
请求头字段名
放密钥的那个头的名字,各家写法不同,写错就是 401
自定义头
部分厂商支持用额外头指定路由或分组,不支持时加了可能被忽略或报错

有一种情况容易误判:请求其实发出去了,但网关层把请求拦下返回了一个和厂商无关的错误页。这时候看到的状态码和错误体格式都和文档对不上,排查顺序是先确认你访问的域名解析和网络可达,再去看厂商文档。

请求体参数:哪些是通吃的,哪些各家不认

消息结构、角色字段、最大输出长度这类通常各家都认,迁移时基本不用动。差异最集中的是采样类参数、停止词和工具调用相关字段。麻烦的是有些厂商遇到不认识的参数不报错,直接静默忽略,你会以为调参生效了,其实什么都没变,这种比报错更难查。

参数类别通用程度处理建议
消息数组与角色高,基本都认可以共用同一套构造逻辑
最大输出长度高,但字段名偶有差异接入前对一遍字段名
采样类参数中,取值范围和是否支持不同按厂商白名单过滤后再发
停止词中,形式可能不同单独验证,别和其他参数混着测
工具调用字段低,支持程度差异大先跑通再决定是否上排期
  • 给每个接入的模型维护一份参数白名单,请求前先过滤,只发对方支持的字段
  • 对静默忽略要有应对:改一个参数后,用同一个输入对比两次返回的差异,确认它真的起作用了
  • 不要用一套参数广播给所有厂商,尤其是采样类参数,一家合适的取值换到另一家可能落在合法范围外
  • 不适用的情况:如果你只调一家的模型,不需要做这层抽象,直接照文档写反而更省事

如果确实需要跨多家做同一件事,把参数按「业务意图」和「厂商实现」拆开。业务代码只表达意图,比如要更稳还是要更发散,由适配层翻译成各家认的字段和取值。这样以后加一家,只需要在适配层加一个翻译分支。

流式返回与用量字段:别写完就不管

流式模式下,结束标记长什么样、增量文本放在返回体的哪一层、中途出错是断开连接还是发一个错误块,各家实现有差别。如果你的代码只按一种写法解析,换个厂商就可能读到空内容或者提前结束。用量统计字段也不是每家都给,缺了就得自己按输入输出长度估算。

curl -N -X POST <你的端点> \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <你的密钥>" \
  -d '{"model":"<模型名>","stream":true,"messages":[{"role":"user","content":"你好"}]}'

上面这条命令的作用是:把请求发出去但不要缓冲,直接看原始流式输出长什么样。先看清楚原始字节,再去写解析代码,比照着文档猜要可靠。看的时候重点确认三件事:增量内容在哪一层、结束标记是什么、错误是哪种形式返回。

  • 客户端做一层归一化,把各家返回体转成同一个内部结构,业务代码只认内部结构
  • 流式解析要能容忍字段缺失和空块,不要默认每个块都带内容
  • 用量字段缺的时候按输入输出长度估,并在日志里标一个来源,方便以后区分是真实统计还是估算
  • 结束标记按厂商分别处理,不要用一个通用判断逻辑套所有厂商

多模态与工具调用:兼容格式里最容易踩空的部分

图片、音频、文件的传参形式差异最大。有的走外部链接,有的要求内联编码,有的必须先单独上传拿到一个标识再在消息里引用。工具调用也是一样,支不支持、能不能强制调用、能不能并行调用,各家口径不同,这些都要先跑一遍再排进排期,别按文档想当然。

能力验证方式不通过时怎么办
图片输入传一张小图,看模型能否描述内容改用先上传拿标识的流程,或换支持该形式的模型
文件输入传一个小文本文件,问其中的内容退回先把文件内容当文本塞进消息
工具调用定义一个最简单工具,看是否触发和返回先用纯文本加结构化输出兜底,再评估必要性
并行工具调用一次给两个可并行的问题,看返回几个调用在上层串行拆成两次请求

有个判断标准值得记住:如果任务本身依赖多模态或工具调用,就别指望纯改写 base_url 能平滑迁移。这两类能力的差异是能力层面的,不是格式层面的,改地址解决不了。要做的是先验证目标模型支不支持你要的形式,再决定迁移方案。

模型名与版本后缀:别名、快照和「最新版」

同一家通常同时提供滚动别名和固定快照名。别名会随厂商调整指向,适合拿来试和做早期验证,不适合长期压测或者对稳定性要求高的线上任务,因为某天它指向变了,你的结果就跟着变。固定快照名相对稳定,但可能在某个时间点被下线。

滚动别名
指向会随厂商调整,适合试探,不适合作为长期固定依赖
固定快照名
指向相对固定,适合线上,但要留意下线通知
模型名配置化
把模型名做成配置项而不是写在代码里,换代时改配置不改逻辑

想核对各家当前在用的模型名、别名规则和定价口径,去站内页面对一遍当时的数字,别照抄旧笔记。具体路径是到 /models 看模型资料库,到 /price-watch 看价格追踪,两边对上了再写进配置。

迁移与上线的检查清单

迁移不要一步到位。按下面这个顺序一层层过,每层通过了再进下一层,出问题时你能立刻知道是哪个环节。灰度方式上,同一个业务入口按比例把流量切到新模型,对比失败率和耗时再决定是否全量。

  1. 连通性最简请求打一次,确认端点和鉴权都对。验证标准:返回正常结束,没有 404 和 401。
  2. 单轮非流式带完整业务参数发一次,看返回体能不能被你的解析代码吃下。验证标准:字段都能对上,不需要写特判。
  3. 流式打开流式再发一次,看增量内容和结束标记是否被正确解析。验证标准:拼接出来的文本和非流式结果语义一致。
  4. 多模态或工具调用按你的实际用法各跑一遍。验证标准:不通过就如实记录,别先排进排期。
  5. 错误码压测故意触发限流、超长输入、非法参数,看返回的错误体结构是否统一。验证标准:错误能被你的异常处理捕获并分类。
  • 回退要留开关,而且开关要能按请求维度切,不能只留一个全局环境变量,出问题时全局回退影响面太大
  • 灰度期间同时记录新旧模型的失败率和耗时,只切流量不对比等于没灰度
  • 上线前把模型名、端点、参数白名单三项都做成配置,改配置就能换,不用重新发版

接上之后怎么盯:日志、限流与成本

接上不是终点。按模型维度记请求量、失败率、首字延迟和总耗时,不记这些,出问题只能靠猜。被限流时先看对方返回的错误码含义,确认是并发超了还是频率超了,再调并发,别一上来就把重试次数拉高,那样可能让情况更糟。

盯的指标为什么要盯异常时先看什么
请求量与失败率判断是模型问题还是你这边的问题错误码分类,区分客户端错和服务端错
首字延迟流式体验的关键,用户能直接感觉到是不是某个模型或某个区域变慢
总耗时影响整体吞吐和超时设置输入长度分布是不是变了
按模型分开的用量成本核算的基础输入和输出分开记,别混在一起

成本这块,别在代码里写死单价做估算,单价会变。做法是记录用量,然后到站内 /price-watch 核对当时的数字再算,这样口径不会过期。如果你要多家中转或直连混用,到 /sites 看各家的可信度检测结果,再决定哪条链路走什么流量。

下一步把端点、鉴权、参数白名单这三样先落地,再去核对各家当前的模型名和价格口径,避免用旧笔记接入。

常见问题

换成另一家模型,是不是只改 base_url 和模型名就行?

简单文本对话多数情况可以,但别默认一定行。鉴权头、路径拼接、采样参数、流式结束标记、用量字段都可能不一样。稳妥做法是先跑通最小请求,再逐步加参数,把差异记录下来做一层适配。

为什么我传了某个参数,接口不报错但看起来没生效?

很可能是对方静默忽略了不认识的字段。报错反而好处理,静默忽略最容易误判。建议给每个模型维护参数白名单,请求前过滤,并且用同一提示词对比开启前后输出是否有区别。

流式输出接多模型时最常见的坑是什么?

增量文本字段位置和结束标记的处理方式不一致,有的还会在其中插入错误对象。写完要用网络异常和超长输出两种场景各测一遍,别只测一次正常返回。

多模型接入要不要在中间加一层自己的统一网关?

团队里接入超过两三家就值得加。网关负责鉴权、参数过滤、返回体归一化、日志和限流,业务侧只认内部结构。代价是多一次维护,人少、只接一家的项目可以不折腾。

怎么知道某家当前支持哪些模型、价格是多少?

本站不写死数字,因为各家调整频繁。到站内的官方 API 价格和厂商与平台目录核对当时的口径,再结合自己的用量估算,别拿几个月前的截图做预算。

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