给 OpenRouter 模型配回退链:主模型挂了自动换下一个

2026-08-18

本文所有事实均来自 OpenRouter 官方文档 openrouter.ai/docs/guides/routing/model-fallbacks 于 2026-08-18 的公开内容。该平台迭代频繁,字段与限制以官方文档最新内容为准。

一、这个东西是给谁准备的

你把一个模型 ID 写死在服务里,跑了几周都好好的,某天凌晨接口开始批量 500,日志里全是同一个模型返回的错误。这时候能做的事非常有限:要么手动改配置换模型重新发布,要么在自己的代码里写一层 try/catch 再发一次请求——后者听起来简单,真写起来要处理重试计数、要区分哪些错误值得重试、要保证消息体不被改坏,还得考虑第二次请求算谁的账。

OpenRouter 官方文档的《Model Fallbacks》页给的是把这层挪到平台侧的做法:请求体里除了主模型,再带一个候选列表,主模型出错时由 OpenRouter 顺着列表往下试。文档对这个能力的一句话描述是:models 参数让你在主模型的 provider 宕机、被限流,或因内容审核拒绝回复时,自动尝试其它模型。

注意这句话的措辞——它说的是「主模型的 provider」出问题。同一个模型在 OpenRouter 上可能由多个 provider 提供,provider 之间怎么挑是另一页文档(openrouter.ai/docs/guides/routing/provider-selection)的事,本文只讲模型之间的回退,两者不是一回事,别混着调。

二、前置条件

这个字段不是所有调用姿势下都叫同一个名字,动手前先确认你走的是哪条路。文档里给出的组合是这几种:

  • OpenRouter 官方 TypeScript SDK@openrouter/sdk):在 chat.send 的参数里直接写 models 数组。
  • 直接发 HTTP 请求POST https://openrouter.ai/api/v1/chat/completions,请求体 JSON 里放 models。文档同时给了 TypeScript 的 fetch 版本和 Python 的 requests 版本。
  • 用 OpenAI 官方 SDK 指到 OpenRouterbase_url 设成 https://openrouter.ai/api/v1models 要放进 extra_body,因为它不是 OpenAI SDK 自己认识的字段。
  • 用 Anthropic 官方 SDK 指到 OpenRouter:这条路走的是 /api/v1/messages 端点,参数名不叫 models,叫 fallbacks,形状也不一样。文档的示例调用的是 anthropic.beta.messages.create——这是 SDK 上的 beta 命名空间,照实标出来,不要当成稳定接口对待。

鉴权方面,文档示例里是 Authorization: Bearer 加密钥。密钥本文一律写成 <OPENROUTER_API_KEY>,你自己的代码里也别硬编码进源文件——这是通用工程做法,不是官方文档里的要求。在 Windows 上,PowerShell 里临时设环境变量用 $env:OPENROUTER_API_KEY="<YOUR_API_KEY>",cmd 里用 set OPENROUTER_API_KEY=<YOUR_API_KEY>;Linux/macOS 的 shell 里用 export OPENROUTER_API_KEY=<YOUR_API_KEY>。这一段属于各平台通用做法,官方文档没有讲环境变量怎么设。

三、字段怎么写,每一步在改什么

models:一个按优先级排的数组

文档对工作方式的描述是:按优先级顺序提供一个模型 ID 数组,如果第一个模型返回错误,OpenRouter 会自动尝试列表里的下一个。

直接发 HTTP 请求时的写法(原样抄自官方文档的 Python 示例):

import requests
import json

response = requests.post(
  url="https://openrouter.ai/api/v1/chat/completions",
  headers={
    "Authorization": "Bearer <OPENROUTER_API_KEY>",
    "Content-Type": "application/json",
  },
  data=json.dumps({
    "models": ["~anthropic/claude-sonnet-latest", "gryphe/mythomax-l2-13b"],
    "messages": [
      {
        "role": "user",
        "content": "What is the meaning of life?"
      }
    ]
  })
)

data = response.json()
print(data['choices'][0]['message']['content'])

代码里那两个模型 ID 是官方文档当时写的示例值,平台上有哪些模型、哪些 ID 还有效随时在变,别把它当成可用模型清单抄进生产配置,用之前去官方的模型页确认当前的 ID。

modelmodels 同时出现时谁先跑

用 OpenAI SDK 的那段示例里两个字段都在:model 写的是 ~openai/gpt-latestextra_body 里的 models 是另外两个。文档对这个组合的说明很明确:~openai/gpt-latest 会被先尝试,然后 models 数组按顺序作为 fallback 依次尝试。

from openai import OpenAI

openai_client = OpenAI(
  base_url="https://openrouter.ai/api/v1",
  api_key=<OPENROUTER_API_KEY>,
)

completion = openai_client.chat.completions.create(
    model="~openai/gpt-latest",
    extra_body={
        "models": ["~anthropic/claude-sonnet-latest", "gryphe/mythomax-l2-13b"],
    },
    messages=[
        {
            "role": "user",
            "content": "What is the meaning of life?"
        }
    ]
)

print(completion.choices[0].message.content)

TypeScript 那版官方示例里,models 是和 model 平级直接写在参数对象里的,上面还挂了一行 // @ts-expect-error——因为 OpenAI 的类型定义里没有这个字段,编译期会报错。这行注释是文档原文里就有的,不是我们加的。

fallbacks:Anthropic Messages 端点上的另一套形状

/api/v1/messages 时,参数叫 fallbacks,是一个对象数组,每个对象点名一个要按顺序尝试的 fallback 模型:

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  baseURL: 'https://openrouter.ai/api',
  apiKey: '<OPENROUTER_API_KEY>',
});

const message = await anthropic.beta.messages.create({
  model: 'anthropic/claude-sonnet-4.5',
  max_tokens: 1024,
  fallbacks: [{ model: 'anthropic/claude-opus-4.1' }],
  messages: [{ role: 'user', content: 'What is the meaning of life?' }],
});

这段里出现的两个模型 ID 同样是官方文档当时写的示例值,不是推荐搭配,也不是可用清单——平台上有哪些模型、ID 怎么写随时在变,照抄前去官方的模型页对一遍。baseURL 写到 https://openrouter.ai/api 而不是带 /v1,这也是文档示例里的原样写法,别自己给它补一截。

这里有个容易误会的点,文档专门用一个 Note 说清楚了:这套 fallback 路由是 OpenRouter 自己处理的,fallbacks 参数不走 Anthropic 的服务端 fallback 功能。文档同时写明,这个列表映射到的就是 OpenRouter 的 models 路由,所以触发条件和下面那份错误清单一致——不是只在模型拒答时才触发。这一条值得记:参数名和 Anthropic SDK 的形状对齐了,但语义归 OpenRouter 管。

四、边界:什么会触发、什么不支持

默认触发条件是「任何错误」

文档的原话是:默认情况下,任何错误都可以触发使用 fallback 模型,并列了四类(这四类是我们照着文档那份列表数的):

文档列出的触发场景说明
Context length validation errors上下文长度校验失败
Moderation flags for filtered models被过滤模型的内容审核标记
Rate-limiting被限流
Downtime宕机

文档用的是「默认情况下」这个措辞,措辞本身留了余地,但这一页文档没有说明这个默认能不能改、怎么改,也没有列出可配置的触发条件白名单。想只在限流时回退、不在审核拒答时回退,本文给不出依据,也不替文档推断有没有这样的开关。

回退只兜一层

文档对失败链路的描述是:如果你选的模型返回错误,OpenRouter 会尝试使用 fallback 模型;如果 fallback 模型也宕机或返回错误,OpenRouter 就会把那个错误返回给你。

按字面读,这句话说的是「回退之后再失败就返回错误」。数组里排到第三个、第四个的模型会不会继续接力,这一页没有展开说,我们不替它推断。你的调用方还是得有兜底路径,不能假设配了数组就一定拿得到回复。

fallbacks 的三条硬限制

文档的 Limitations 小节列了三条,每条踩中都是 400:

  • 每个 fallbacks 条目只接受 model 一个字段。按次覆盖的参数——文档点名的有 max_tokensthinkingspeedoutput_config——会被拒绝并返回 400 错误。也就是说你不能给回退模型单独设一套参数。
  • fallbacks 不能和 models 参数一起用,两个都发会返回 400 错误。
  • fallbacks 的条目数有上限,超过上限的列表会返回 400 错误。具体上限是接口校验里的一个阈值,这类数值随版本调整的成本很低,本文不写死,动手前去官方文档确认当前值。

注意第三条只约束 fallbacksmodels 数组有没有长度上限,这一页官方文档没有说明。

这三条合起来划出的边界是:fallbacks 是一个只能点名模型、不能带参数、长度受限、且和 models 互斥的轻量结构。想给回退模型单独调参数,或者想排一条更长的候选链,这条路走不通——要么改走 chat/completionsmodels,要么把这层逻辑留在自己的代码里。

计价按最终跑的那个模型算

文档写明:请求按最终实际使用的模型计价,而这个模型会在响应体的 model 属性里返回。具体价格数值本文不写,去官方定价页看当前值。

这条对做成本预算的人有实际影响:回退链里排在后面的模型,价格未必和主模型一个量级,触发一次回退,这次请求的成本口径就换了。所以候选列表不能只按「能顶上」来排,得同时看你能接受的成本区间。

五、怎么确认它真的配对了

最直接的验证点就是上面那个 model 属性——文档说明最终使用的模型会在响应体里返回,那么把它打出来就能知道这次请求到底落在了谁身上:

data = response.json()
print(data['model'])
print(data['choices'][0]['message']['content'])

以上为按官方文档中的参数语义组合的示例,未经实测,以官方文档与 --help 的实际输出为准。

几个建议的检查动作,按可核实程度排一下:

  1. 正常路径先跑通:主模型可用时发一次请求,读响应体的 model 字段,确认它等于你写的主模型。这一步只是证明字段名没写错、extra_body 放对了位置。
  2. 确认字段被接受:用 OpenAI SDK 时,models 如果没进 extra_body,行为不受官方文档保证;TypeScript 那边则要留意 // @ts-expect-error 的位置。走 /api/v1/messages 时,把 fallbacksmodels 同时发一次,按文档应该拿到 400——这是文档写明的行为,可以拿来当「参数确实被平台解析了」的反向验证。
  3. 不要用制造真实故障的方式去测:文档没有提供模拟 provider 宕机的开关,也没有提供强制触发回退的参数。我们没有对这个能力做过实测,所以不给「怎么造一次故障」的操作建议。

最后提醒一句口径问题:这一页讲的全是模型级回退,和同一模型下 provider 之间怎么挑、order / only 之类的 provider 路由字段不在一个层面。线上排查时先分清你这次失败是「模型不可用」还是「某个 provider 不可用」,两边的配置项不通用,改错地方会白忙一晚上。


本文依据 OpenRouter 官方文档(openrouter.ai/docs)于 2026-08-18 的公开内容整理。 该平台闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观与运行表现的任何描述。 该平台的供应商、模型与路由策略随时变动,文中不列具体供应商名单与模型清单; 价格、额度与限流的具体数值请以官方定价页与用量说明为准。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。