Amux

路由与故障转移

最近更新:2026年9月15日

多家供应商提供同一模型时请求落到哪一家:候选池如何构成、如何排序、失败如何切换,以及三层配置的合并规则。

同一个模型通常有多家供应商提供。当请求中未指定供应商时,平台按配置排出一条有序的候选序列,依次尝试直到成功。本页说明这条序列如何生成,以及你可以在哪几个位置影响它。

路由分两步

步骤回答的问题依据
准入哪些供应商进候选池模型白名单、货源范围、指定供应商、上下文容量、协议可达性、供应商状态
排序池子里先试谁排序策略、优先供应商

两步互不干涉:排序永远不会扩大候选池,准入也不决定顺序。理解这一点可以解释绝大多数「为什么这个请求没有走到我想要的那家」。

准入:谁进候选池

一条「模型 × 供应商」报价需要同时满足以下条件才能进入候选池:

  • 模型在该密钥的可调用模型白名单之内(白名单为空表示不限制)
  • 该供应商在密钥与账户的指定供应商名单之内(名单为空表示不限制)
  • 货源层级在生效的货源范围之内
  • 上下文上限装得下本次请求
  • 其支持本次请求所用的协议
  • 供应商与该条报价处于可路由状态

候选池为空时请求返回错误,不会回落到范围之外的供应商。这是刻意的:静默放宽约束意味着你以为生效的限制实际并不生效。

⚠️ 上下文容量的比对使用估算值,估算偏小时放行。因此长度极端接近上限的请求仍可能在上游被拒绝。

排序:先试谁

排序策略

策略依据同档容差
balanced全部候选视为同一档,按权重加权随机。默认值——
price按站内售价由低到高相对 2%
latency按最近 24 小时的平均首字延迟由低到高相对 20%
throughput按最近 24 小时的平均吐字速率由高到低相对 20%
reliability按最近 24 小时的成功率由高到低绝对 1 个百分点

同档容差决定了策略有多"硬"

策略影响的是倾向,不是保证。 排序时先按指标算出全序,再按容差分档——差距在容差之内的候选归入同一档,档内继续按权重加权随机分流

容差不是保守取值,而是对应各指标的真实噪声水平:

  • 延迟与吞吐的 20% —— 测量噪声本来就在这个量级,差 5% 就排出先后是假精度。这也解释了一个常见疑问:选了「延迟优先」之后流量仍然是分散的,因为表现接近的几家被判为同档。
  • 价格的 2% —— 价格是确定值,容差只用于吸收促销系数的舍入。
  • 成功率的 1 个百分点 —— 成功率本身就是比例,用相对差会让低分段的容差被不当放大(0.99 与 0.98 相差 1%,0.10 与 0.09 相差 11%,但两组的实际差距都是 1 个百分点)。

price 比的是合成单价

价格策略按 输入价 × 3 + 输出价 × 1 的加权合成单价排序,而不是单看某一项。因此一家输出便宜但输入昂贵的供应商未必排在前面。

排序依据是你实际支付的站内售价,已包含促销与账户专属折扣——不是平台的进货成本。

统计类策略在数据不足时的行为

latencythroughputreliability 依赖最近 24 小时的实测数据,样本量不足的候选不下结论:

  • 部分候选缺少样本 —— 按中位数插入队列中部,而不是排到最后。没有数据不等于表现差,排到最后会让它更难获得样本,形成自我实现的判断
  • 全部候选都缺少样本 —— 整体退化为 balanced。新模型或新供应商刚上线时属于正常情况,统计积累后自动生效

三项统计的分母均不含客户端错误:请求本身写错导致的失败不计入供应商的表现。

会话亲和:同一会话排序稳定

多轮对话如果每一轮都换一家供应商,上游的提示缓存必然不命中——输入 token 按全价计费,而命中缓存通常只需约十分之一的价格,首字延迟也更高。

因此加权随机的随机源由会话键派生:同一个会话每一轮都排出相同的候选顺序,而不同会话之间互不相关,整体仍按权重分流。

会话键按以下顺序确定:

优先级来源
1请求体中的 prompt_cache_key
2请求体中的 user
3由系统提示词与首条消息推导

建议显式传入 prompt_cache_key 自动推导依赖对话开头保持不变,而显式指定不受这一前提约束,对长会话与多分支对话更可靠。这是成本优化中性价比最高的一项。

优先供应商

除排序策略外,还可以指定一组优先供应商。候选池被分成两组:优先组在前,其余在后,两组各自按排序策略排序。

优先供应商不改变候选池,因此永远不会让一个模型变得不可调用——优先的那几家全部不可用时,请求仍会落到其余供应商。

当优先名单一家都没命中、或者全部命中时,分组自动失效,退回单组排序。

熔断的优先级最高

连续失败的链路会被熔断,并在排序之后被移到序列末尾。也就是说,熔断可以推翻你的排序偏好:偏好表达的是「正常情况下先试谁」,而熔断表达的是「这一条刚刚连续失败」。

全部链路都处于冷却状态时,请求返回错误并明确说明原因。

故障转移

尝试失败后是否切换到下一个候选,由错误类型决定:

  • 可转移:连接失败、超时、上游 429、上游 5xx
  • 不可转移:参数错误、鉴权失败、内容策略拒绝、超出上下文等客户端归因的错误

不可转移的错误会立即返回。换一家供应商得到的是同样的结果,继续尝试只会延长响应时间。各错误类型是否触发故障转移,见 API 参考的错误表

转移过程中失败的尝试不计费,对应的上游成本由平台承担。完整的尝试链记录在调用日志的「路由尝试」中,可以看到依次尝试了哪几家、各自因何失败。

只有归因于上游的失败才计入熔断统计。客户端错误不会导致链路被摘除——否则一个写错参数的脚本就能把正常链路全部摘掉。

三层配置

排序策略与候选范围可以在四个位置配置,越靠近请求的越具体

位置作用范围谁能改
账户设置个人账户作用于个人工作区;组织账户作用于该组织下的全部工作区账户主人 / 组织管理员
工作区该工作区下的全部密钥仅组织管理员(工作区管理员只能看)
API 密钥仅这一把密钥密钥归属人
请求后缀仅这一次请求调用方

工作区这一层只存在于组织工作区。个人工作区之上只有账户设置。

两类配置的合并规则不同,这是刻意的:

字段合并规则
偏好排序策略、优先供应商最具体者胜。密钥配置过就完全不看账户设置
约束货源范围、指定供应商取交集。密钥只能收得更窄,不能放宽

偏好轴采用整体覆盖而非逐字段继承:否则会出现「这把密钥只覆盖了一半配置,另一半跟着全局默认漂移」,而管理员以为自己只改了默认值。

约束轴取交集,是为了保证账户层设定的下限无法被密钥绕过。

货源范围的交集

三种取值不构成全序——「仅官方质量层」与「仅低价层」互不包含,交集为空。 交集逐层计算(账户 ∩ 工作区 ∩ 密钥),下表适用于任意相邻两层:

上一层 \ 下一层全部货源仅官方质量层仅低价层
全部货源全部货源仅官方质量层仅低价层
仅官方质量层仅官方质量层仅官方质量层冲突
仅低价层仅低价层冲突仅低价层

冲突的组合在保存时即被拒绝,不会留到运行时;收窄上层配置时,如果会导致下层 某些工作区或密钥候选为空,保存同样会被拒绝并列出受影响的名称。

上层限定之后,下层界面会直接显示结果

当上一层已经把货源范围限定为某一档时,下一层不再提供下拉选择——因为此时 每一个合法选项算出来的生效值都相同。界面直接显示生效值,并标注是被哪一层限定的。

指定供应商同理:上层点名之后,下层的候选只剩那几家。

请求级后缀

后缀写在模型 ID 之后,以冒号分隔。

指定供应商

{ "model": "anthropic/claude-opus-5:anthropic" }

锁定之后候选池只剩这一家,该供应商不可用时请求直接失败,不会切换。需要确定性时适合锁定;需要更高可用性时应保留自动路由。

指定的供应商若不在密钥允许的名单之内,请求返回 invalid_request——继续重试不会改变结果。

指定排序策略

{ "model": "anthropic/claude-opus-5:@price" }

@ 是策略后缀的固定前缀,用于与供应商标识区分。

⚠️ 策略后缀默认被密钥锁定。 要允许调用方在请求中指定策略,需在密钥设置中开启「允许请求覆盖策略」。未开启时使用该后缀会返回错误,而不是被静默忽略。

⚠️ 两种后缀不能同时使用。 指定供应商之后候选池只剩一家,排序不再有意义,此类请求返回错误。

请求后缀只能改变排序,不能放宽范围。 货源范围与指定供应商名单由配置层决定,请求无法覆盖。

模型 ID 中本身带冒号的情况

部分模型的规范名称或别名本身包含冒号,例如 llama3.1:70b 或 Bedrock 风格的 ...-v2:0。解析时先以完整字符串查询一次别名表,命中即视为完整模型名;未命中才按最后一个冒号拆分后缀。因此这类名称可直接使用,无需转义。

常见问题

为什么请求没有走到价格最低的那一家

可能的原因依次为:该供应商不在生效的候选范围之内(货源范围或指定供应商名单);其上下文上限装不下本次请求;它不支持本次使用的协议;它正处于熔断冷却中;或者当前排序策略不是 price。调用日志的「路由尝试」会显示实际尝试过哪几家。

改了账户的默认策略,为什么某些密钥没变

排序策略属于偏好轴,采用最具体者胜。已经单独配置过策略的密钥不跟随账户默认值,需要在密钥上单独修改,或将其改回「跟随工作区默认」。

故障转移会重复计费吗

不会。转移过程中失败的尝试不计费,只有最终成功的那一次产生费用。

流式响应中途上游失败会怎样

已经发送给客户端的内容不会回滚。此时请求按已产生的用量计费,日志中标记为上游截断。

相关