AIHub

大模型也开始限流了:给自己搭一套多模型备胎与自动切换方案

进阶约 13 分钟读完2026-08-07#大模型#API#故障转移#限流#工程实践
大模型也开始限流了:给自己搭一套多模型备胎与自动切换方案

过去一周的 AI 圈有两条新闻值得连起来看:一是 Kimi 新模型 K3 因访问量过大暂停了新用户订阅,二是 OpenAI 在 ChatGPT 里升级了 GPT-5.6 Sol 档位,把产品重心从"问答"推向"任务完成"。再往前翻,几乎每个主流厂商今年都经历过至少一次区域性故障或配额收紧。结论很简单:大模型服务正在变成一种会拥堵、会涨价、会临时调整策略的基础设施。

如果你的工作流——不管是自己写的小工具、公司的客服机器人,还是跑在服务器上的自动化脚本——只接了一家的 API,那么对方的每一次限流、改版、维护,都是你的事故。这篇文章讲清楚怎么给自己搭一套"备胎系统":平时无感,出事时秒切,成本还可控。

一、先想清楚:你需要哪种级别的备胎

不是所有场景都值得上重方案。按故障的容忍度分三档:

场景 可接受中断时长 推荐方案
个人工具、实验脚本 几分钟到几小时 第一层:手动切换
内容生产、内部自动化 几十秒 第二层:代码级自动切换
面向用户的产品、关键业务 秒级,且要可观测 第三层:统一网关 + 监控

大多数人处在第一、二层之间。建议直接从第二层做起——代码量不大,一次写好长期受益。第三层适合已经有多人、多项目共用 API 的团队。

二、第一层:十分钟就能搞定的手动备胎

最低成本的方案,适合不想写代码的人:

  1. 同时持有两家以上厂商的账号和 key。选择标准很简单:主用一家,备用一家协议兼容的。目前绝大多数国产模型(Kimi、DeepSeek、通义、智谱等)都提供 OpenAI 兼容接口,换模型基本只改 base_url、api_key 和模型名三个值。
  2. 把配置写成环境变量而不是硬编码。比如 LLM_BASE_URL、LLM_API_KEY、LLM_MODEL。限流发生时改三个环境变量重启服务,比翻代码快得多。
  3. 备一个聚合 API 账号作为"最后备胎"。聚合平台一个 key 能调几十家模型,虽然单价略高,但胜在永远不会"全家都挂"。平时不用,出事时顶上去。

这一层的短板很明显:切换靠人发现、靠人操作,半夜出问题就要半夜爬起来。所以要往上走一层。

三、第二层:代码级自动故障转移(核心实战)

思路一句话:按优先级配置一个模型列表,请求失败时自动降级到下一个,全部失败才报错。下面是一个可以直接用的 Node.js 实现(用 OpenAI 官方 SDK,因为兼容协议最通用):

import OpenAI from "openai";

// 按优先级排列:主模型在前,备胎在后
const PROVIDERS = [
  {
    name: "primary",
    baseURL: process.env.LLM_BASE_URL,        // 主厂商
    apiKey: process.env.LLM_API_KEY,
    model: process.env.LLM_MODEL,
  },
  {
    name: "backup-1",
    baseURL: process.env.LLM_BACKUP_BASE_URL, // 备用厂商
    apiKey: process.env.LLM_BACKUP_API_KEY,
    model: process.env.LLM_BACKUP_MODEL,
  },
];

// 这些错误值得切换备胎:限流、服务端错误、超时、配额用尽
const RETRYABLE = [429, 500, 502, 503, 504];

async function chatWithFailover(messages, options = {}) {
  let lastError;
  for (const p of PROVIDERS) {
    const client = new OpenAI({ baseURL: p.baseURL, apiKey: p.apiKey, timeout: 30_000 });
    try {
      const res = await client.chat.completions.create({
        model: p.model,
        messages,
        ...options,
      });
      if (p.name !== "primary") {
        console.warn(`[failover] 主模型不可用,已由 ${p.name} 接管`);
      }
      return res;
    } catch (err) {
      lastError = err;
      const status = err?.status;
      if (!RETRYABLE.includes(status) && status !== undefined) {
        throw err; // 400 这类错误是自己请求有问题,换模型也没用,直接抛
      }
      console.warn(`[failover] ${p.name} 失败(${status ?? err.message}),尝试下一个`);
    }
  }
  throw lastError;
}

这段代码里有几个容易踩坑的细节,值得单独说:

  • 不是所有错误都该切换。400(请求格式错误)、401(key 失效)换了厂商也一样失败,盲目重试只会浪费钱。只对 429(限流)和 5xx(服务端故障)做转移。
  • 不同厂商的模型能力不对等。备胎模型的输出风格、上下文长度、工具调用能力可能和主模型有差异。降级时最好在日志里打标,方便事后排查"那天为什么输出质量下降了"。
  • 超时必须设。不设 timeout 的话,主厂商挂起时你的请求会一直挂着,备胎永远轮不到。
  • prompt 里不要写死厂商特有指令。比如某些模型特有的系统提示词约定,写死了会让备胎模型表现异常。

如果用的是 Python,思路完全一样:OpenAI SDK 的 base_url 参数 + 一个 for 循环即可,不赘述。

四、第三层:自建统一网关,一次解决所有项目

当你有三个以上的项目都在调大模型,在每个项目里复制一份 failover 代码就变得很蠢。这时候该把切换逻辑收敛到一个网关里。开源社区最常用的是 One API / New API 这类项目,部署一个就拥有:

  • 统一的 OpenAI 兼容入口,所有项目只填一个地址、一个 key;
  • 渠道(channel)级别的优先级与自动禁用:某个渠道连续失败会被自动摘下,恢复后再加回;
  • 按模型名路由:gpt-5.6 走 A 厂商,k3 走 B 厂商,调用方无感知;
  • 用量统计与额度管理,团队多人共用时分账清楚。

部署用 Docker 一行起,数据用 SQLite 就能跑,个人服务器完全够用:

docker run -d --name llm-gateway -p 3000:3000   -v /opt/llm-gateway/data:/data   --restart always   calciumion/new-api:latest

起好之后在 Web 后台添加各家厂商渠道、设置优先级,然后把所有项目的 base_url 指向 http://你的服务器:3000/v1 即可。之后再新增备胎厂商,业务代码一行都不用改。

需要提醒:自建网关意味着所有厂商的 key 都集中在一台机器上,务必给网关加访问令牌、不要把端口裸奔在公网,最好只允许内网或指定 IP 访问。

五、注意事项与常见问题

1. 切换备胎后上下文还连续吗? 连续。多轮对话的历史消息是你自己传给 API 的,换厂商不影响会话内容。但要注意各家对 system prompt 的处理细节略有差异,关键指令在消息里显式重复一次更稳。

2. 成本会不会失控? 备胎一般是"用时才计费",平时零成本。真正要防的是故障转移触发后的循环重试——上面的代码每个请求最多遍历一遍列表,不会在故障期间放大请求量。

3. 流式输出(stream)怎么处理? 流式场景下故障可能发生在传输中途,此时换厂商重发会导致用户看到内容重复。工程上常见的做法是:建连失败才切换,传输中断则就地报错让前端重试。

4. 厂商协议不兼容怎么办? 优先选提供 OpenAI 兼容接口的备胎。实在不兼容的,用 LiteLLM 这类代理库做协议抹平,比自己在业务代码里写分支干净。

5. 多久演练一次? 建议每季度手动把主模型 key 改错一次,确认备胎真的接得上。备胎方案最常见的失败模式是"配好了从来没测过,真出事时发现 key 早过期了"。

小结

模型侧的拥堵和策略变动只会越来越频繁——今天是 Kimi 暂停新订阅,明天可能是任何一家。应对思路归纳成三句话:配置外置,让手动切换足够快;代码里写好失败降级,让自动切换不靠人;项目多了就把逻辑收进网关,一处维护全局受益。从第二层的代码做起,一个下午就能搭完,换来的是以后再看到"某某模型限流"的新闻时,可以安心划走。

相关教程

大模型也开始限流了:给自己搭一套多模型备胎与自动切换方案 | AIHub