好多刚入行的朋友私信问我:“你们聚合平台到底怎么同时接这么多家模型的?代码里难道要写三套不同的客户端吗?”

当然不是。要真那样,我早累得转行了。

今天把这块实操摊开给你看。不管你是想自己搭个小聚合层,还是单纯想让代码同时支持OpenAI、Claude和DeepSeek,下面这套“统一调用”的思路,拿过去就能用。


先认清一个事实:各家接口长得像,但细节膈应人

OpenAI打响了ChatGPT的第一枪,后面的厂商基本都照着它的API形状来设计——路径都是 /v1/chat/completions,请求体里都有 messagesmodeltemperature 这些字段。乍一看,好像无缝切换。

但真跑起来,坑就露头了。

Claude(Anthropic)虽然也兼容OpenAI格式,但它的 /v1/messages 端点要求 system 独立放在顶层,不能塞进 messages 数组里当第一个角色。你要是按OpenAI的习惯把系统提示放 messages[0],Claude直接报400。

DeepSeek更“聪明”——它官方宣称完全兼容OpenAI协议,实际用下来确实最省心,连 stop_sequences 这种偏门参数都能照传。但它的模型名你得写对,比如 deepseek-chatdeepseek-reasoner 指向不同能力,写错了也通不过校验。

所以统一调用的核心,不是在客户端做一堆 if provider == 'openai' 的脏分支,而是建一个适配层,把各家差异在中间消化掉。


我的做法:三层结构,把脏活累活隔离出去

别被“三层”吓着,说白了就三块:

第一层:标准化入参
你对外暴露的接口只接收一套通用参数:messages(数组)、model(字符串)、temperature(浮点数,可选)、max_tokens(整数,可选)、stream(布尔)。不管底层是谁,调用方永远按这套格式传。我们内部管这个叫“中间格式”。

第二层:适配器工厂
针对每个厂商写一个小适配函数,只做一件事——把中间格式转成该厂商要求的原生格式。

举个例子。OpenAI的适配器最简单,把 temperaturemax_tokens 原样塞进去就行。Claude的适配器多一步:从 messages 里把 role='system' 的那条抽出来,放到顶层的 system 字段,剩下的 messages 再发给Claude。DeepSeek的适配器几乎就是透传,但得把 model 映射成它的内部代号。

这层写好之后,你上层业务代码永远不感知底层差异。

第三层:统一响应归一
各家返回结构也不一样——OpenAI返回 choices[0].message.content,Claude返回 content[0].text,DeepSeek随OpenAI。你再写一个反向适配器,把各自响应统一成 {code, data, usage} 这种标准结构。前端或者下游服务只认你的格式,切换模型时不用改一行消费代码。


代码量到底多大?我给你个数

别以为这工程很浩大。我维护的这套适配层,核心代码不到200行Python。每个厂商的适配函数平均30~50行,加上一个路由表,根据传入的 model 前缀自动决定走哪个适配器——比如 gpt- 开头的走OpenAI,claude- 走Claude,deepseek- 走DeepSeek。

你要是连适配器都不想手写,社区有现成的轮子。比如 litellm 这个库,已经帮你把上百家模型的格式统一了,你只改一个环境变量 MODEL 就能切换。不过它封装得厚,出问题时排查链路长。我个人的偏好是手写薄适配层,透明、好改、出事儿三分钟定位。


几个接入时容易绊脚的细节

  • Token计数不准:OpenAI用 tiktoken,Claude用自己的tokenizer,DeepSeek又一套。你在聚合层没法统一算,我一般让各家在响应里带上 usage 字段,直接取官方数值计费,不自己二次估算。

  • 超时参数不同:有些模型推理慢,比如DeepSeek的推理模型,你给60秒超时大概率不够。在适配层里针对长思考模型单独拉长 timeout,别一刀切。

  • 流式响应的格式差异:OpenAI的流式是 data: [DONE] 结尾,Claude是 event: message_stop,解析逻辑不能共用。我的适配层里把流式也统一成生成器,上游只 for chunk in stream,不用管底层是SSE还是WebSocket。


实战小建议:别一上来就全量切换

刚搭好统一调用层,别急着把线上流量全切过去。我的习惯是先在测试环境用同一个请求分别打三家,对比返回内容和耗时。发现差异就调适配器,直到三家的输出在业务可接受范围内一致。

切生产时,用灰度发布。比如5%的请求走Claude,95%走OpenAI,观察两天的错误率和延迟。没问题再逐步放大比例。万一Claude抽风,你把路由权重调回0,用户侧毫无感知。


聚合层的额外红利:成本与容灾

统一调用层搞定了,顺带手就能做两件好事。

一是智能路由。你可以给每个模型配一个“成本系数”,请求进来时根据当前各渠道的实时延迟和价格,自动选最划算的那家。DeepSeek便宜就多切点过去,OpenAI推理强就留给复杂任务。

二是容灾降级。主模型返回超时或者503,你的适配层捕获后直接换备选模型重试,不需要上层业务写重试逻辑。我平台上的可用性从99.5%拉到99.9%,靠的就是这层兜底。


说到底,统一调用不是什么黑科技,就是一层薄薄的中介。但它能把后面的混乱挡在外面,让你专心写业务逻辑,而不是整天跟不同厂商的文档较劲。

动手写自己的适配层吧,200行代码换以后半年的安稳觉——这笔买卖,值。