模型适配层
统一入口不等于统一参数
做 AI 网关时,很容易先追求一个漂亮的入口:所有请求都走 /v1/generate,客户端只传 model、input 和 parameters。这个设计看起来干净,前端也容易接。
问题在于,模型能力不是统一的。文本模型、图像模型、视频模型的输入结构不同;同样是图像模型,有的支持 size,有的支持 aspect_ratio,有的只接受 prompt 和 negative_prompt。如果网关把参数原样透传,上游很快会返回「不支持字段」。
统一 API 的价值不是假装所有模型一样,而是把差异收束在网关内部。
所以适配层要做两件事:对外保持稳定,对内承认差异。客户端看到的是同一个任务 API,服务端看到的是每个模型自己的参数表、调用路径和响应格式。
参数声明要前置
模型适配最容易失控的地方,是把 parameters 当成万能袋子。短期看省事,长期看会把错误推迟到运行时:前端不知道能填什么,后端不知道该拒绝什么,上游报错也很难转成清晰的业务错误。
更稳的做法是让每个模型声明自己的参数边界。
{ |
这份声明不只是文档。它应该直接参与校验、前端表单生成、错误提示和模型路由。调用前能拒绝的参数,就不要交给上游拒绝。
这样做还有一个好处:新增模型时,改动集中在适配器和模型定义里,不需要到处判断 if model == ...。模型差异被保留,但不会扩散。
调用路径也要适配
参数不同只是第一层差异。更麻烦的是调用路径不同。
有些文本模型可以走 OpenAI 兼容端点;有些图像模型必须用运行时绑定调用;有些推理模型可能使用另一套响应格式。网关如果只抽象 URL,很快会卡在「同一个模型名,不同调用协议」的问题上。
适配层应该把一次调用拆成三个明确动作:
- 把统一请求转换成上游请求
- 调用对应的上游入口
- 把上游响应转换成统一响应
type Adapter = { |
接口不需要复杂,但边界要清楚。转换逻辑在适配器里,业务 API 只关心任务状态、输出结果和错误码。
适配层是在保护产品
模型会变,供应商会变,参数也会变。如果没有适配层,变化会直接打到前端、文档和调用方。
好的 AI 网关不是把所有供应商包装成一个巨大的透传代理,而是把不稳定的部分关在后端。外部调用方只需要知道:这个模型能做什么,需要哪些参数,失败时会得到什么错误。
这就是模型适配层的意义。它不是为了写更多代码,而是为了让 API 可以长期稳定。