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