技术文章

接入多家模型供应商之后,我总结的 7 条铁律

接第二家模型供应商之后,真正难的不再是调通接口,而是保证每一笔业务只花一次钱。这 7 条是踩过之后定下来的。

2026-10-04 架构 · 模型路由 · 系统设计

AI 应用接了第二家模型供应商之后,事情就不再是”多加一个接口”那么简单了。

我们先后接了火山方舟、阿里云百炼,以及一个自有的 OpenAI 兼容网关。接下第一家的时候一切顺利;接第二家的时候,问题才开始冒出来——不是调不通,是钱会算错。

下面这 7 条,是我们踩过之后定下来的规矩。每一条背后都有代价。

先讲一个前提:为什么必须要多供应商

只接一家会有三个问题:

问题后果
单点故障上游挂了,你的产品就停
价格被动他涨价你只能跟
能力受限只有他有的模型你才能用

所以多供应商是必然的。而一旦多了,你就不再是”调 API 的人”,你是”管钱和管状态的人”。

先分清楚四层责任

在讲那 7 条之前,先说我们最后定下来的分层。很多坑的根源是分层没想清楚。

层负责什么不负责什么
创作端公开模型、能力参数、参考素材、预计积分供应商名、上游模型 ID、密钥、协议字段
主站 API权限、能力校验、选路、预占 / 结算 / 退款各家供应商的请求差异
自有网关协议映射、上游提交与查询、能力清单、线路治理用户、画布、积分、素材权限
官方直连网关提交前故障时的受控兜底已被上游接受任务的二次提交

注意最后两列——创作端不知道供应商是谁,主站不管各家协议差异,网关碰不到用户和钱。 这条边界一旦模糊,后面全是麻烦。


铁律一:同一任务、同一次尝试,永远用同一个执行键

AI 生成是异步的,一次任务可能要等几十秒到几分钟。这中间会发生什么?

客户端超时重试、网络抖动、服务重启、用户狂点提交按钮。

如果没有一个稳定的执行键,同一个任务就会给上游提交两次。

后果分两种:

  • 两次都成功 → 用户扣两次钱,拿到两份结果
  • 一次成功一次失败 → 你扣了一次钱,但上游跑了两个任务,成本算你的

执行键要在创建任务时就生成好,并且重试时复用——不是每次重试新生成一个。这一条不实现,后面每一条都没意义。

铁律二:上游返回任务 ID 之后,立刻落库

拿到任务 ID 的那一瞬间意味着什么?

钱已经花出去了。 上游已经开始跑,不管结果回不回来,成本都可能产生。

如果这时候没把 ID 存下来,服务一重启,你就:

  • 不知道有这个任务在跑
  • 不知道去哪里轮询结果
  • 用户的钱扣了,东西拿不到

所以规则是:先持久化 ID,再回应用户。 不是”存库里异步处理”,是同步写入成功才算提交成功。

铁律三:只有”拿到 ID 之前”的连接失败,才允许切备用线路

这一条最微妙,也最值钱。

失败分两种:

类型能不能切备用线路
连接失败(请求根本没发出去)✅ 可以切
提交后超时(请求到了,响应没回来)❌ 绝对不能切

为什么第二种不能切?因为你不知道上游到底接没接。

如果接了,你再切备用线路重发一次,就是付两次钱。

所以我们的规则是:只有自有网关在获得任务 ID 之前连接失败,才允许切换官方备用线路。 一旦拿到 ID,无论后面发生什么,都不再切。

这一条的价值在于:它把”我可能付两次钱”的概率,从”每次超时都可能”降到”零”。

铁律四:拿到 ID 之后即使失败,也只能退款,不能重发

这是上一条的推论,但反直觉。

直觉上”失败了要重试”。但在付费的异步任务里,重试的代价可能是双倍成本。

所以:已经拿到任务 ID 的任务,失败就是失败——记录失败、原路退款,不创建第二个付费任务。

宁可这次体验差一点,也不能让账目变得不可解释。

铁律五:凭据必须精确匹配所有者,不能跨租户借用

如果支持用户自带密钥(BYOK),这一条是红线。

系统通常会有”个人 → 团队 → 平台”的凭据查找顺序。这里有个极其危险的默认行为:用户的个人密钥失效了,系统静默用平台额度顶上。

用户以为花的是自己的钱,实际花的是你的。

所以我们的规则是:

  • 凭据只能精确匹配当前所有者
  • 换线路时禁止跨凭据层切换——用户密钥失效就报错,不许偷偷换平台账号继续跑
  • 平台、团队、个人三层凭据,各自独立,不互相兜底

这一条同时保护两件事:你的钱,和用户对你账目的信任。

铁律六:付款来源在创建任务时就固化

一次生成会经历:选路 → 预占积分 → 执行 → 结算或退款。

如果这中间有任何配置变了(团队预算规则调整、用户换了凭据、线路改了报价),退款的时候就会出现一个问题:这笔钱该退给谁?

所以规则是:任务创建时就把”付款来源”写死在任务记录上,退款只能回到原 Workspace 账本或原付款用户。

不固化的话,账目会随着配置漂移,最后没法对。

铁律七:浏览器永远拿不到明文密钥,创作端不展示供应商

两条:

一、密钥不进浏览器。 只要密钥出现在前端代码、网络请求或者页面里,它一定会泄露——这是时间问题,不是概率问题。

二、创作端不展示供应商信息。 用户看到”这条走的是某某供应商的某某模型”,下一步就是绕开你直接去找上游。

所以创作端只给用户看三样:公开模型名、能力参数、预计积分。


除了这 7 条,还有三件事要做

1. 线路健康探测与熔断。 定时探测每条线路,连续失败到阈值就进入冷却,冷却结束自动恢复。没有这个,上游挂了你还在一直接单。

2. 统一的任务取消。 用户点取消,要做三件事:主站退款、标记任务、通知路由站——路由站再尽力调用上游取消接口。上游不支持取消时,要在日志里留下明确诊断,别让运维猜。

3. 结果状态归一化。 每家上游的任务状态命名都不一样。统一成五个状态就够:

QUEUED → RUNNING → SUCCEEDED
                 → FAILED
                 → CANCELED

内部逻辑只认这五个,外部差异全部在网关层吃掉。

最后

接第一家供应商的时候,你觉得这是个技术问题。

接第二家的时候你会发现——这是个账目问题。

而这 7 条的共同点只有一个:都在防止”同一笔业务被花两次钱”。