OmniRoute Auto-Combo 引擎深度指南:自适应评分、零配置自动路由与自愈调度
本指南以仓库内的 AUTO-COMBO.md(及其多语言本地化版本 docs/i18n/az/docs/routing/AUTO-COMBO.md)为核心脉络,结合
open-sse/services/autoCombo/下的真实实现编写。Auto-Combo 是 OmniRoute 网关的"自我管理模型链":它不再要求你手动维护 provider 故障转移链,而是对每一次请求实时评估全部已连接 provider 的健康、成本、延迟与任务适配度,自动选出最优目标,并在故障时自愈、在预算内兜底。读完本文,你将掌握它的 16 因子评分模型、6 套模式权重包、auto/零配置路由、请求级控制头、自愈与探索机制,以及如何通过 API 与自定义路由策略把它接入自己的客户端。
一、从 6 因子到 16 因子:Auto-Combo 的评分模型
Auto-Combo 引擎的核心是每个请求动态选出最佳 provider/model。本地化文档以一张"6 因子评分表"概括其骨架:
| 因子 | 权重 | 说明 |
|---|---|---|
| Quota | 0.20 | 剩余配额/速率余量 [0..1] |
| Health | 0.25 | 熔断器状态:CLOSED=1.0, HALF=0.5, OPEN=0.0 |
| CostInv | 0.20 | 反向成本(越便宜分越高) |
| LatencyInv | 0.15 | 反向 p95 延迟(越快分越高) |
| TaskFit | 0.10 | 模型 × 任务类型适配度 |
| Stability | 0.10 | 延迟/错误的低方差 |
而当前源码 open-sse/services/autoCombo/scoring.ts 中的 DEFAULT_WEIGHTS 已经演进为 16 因子模型——上述 6 个核心因子全部保留,权重重新分配并新增了账号层级、上下文亲和、会话可用性等信号,总和精确等于 1.0:
| 因子 | 默认权重 | 说明(以源码注释为准) |
|---|---|---|
quota |
0.1429 | 剩余配额/速率限制余量 [0..1] |
health |
0.1605 | 熔断器健康分(CLOSED=1.0 / HALF_OPEN=0.5 / OPEN=0.0) |
costInv |
0.1429 | 反向混合成本(60% 输入 + 40% 输出 token 价格归一化),越便宜分越高 |
latencyInv |
0.1143 | 反向 p95 延迟,按候选池归一化 |
taskFit |
0.0762 | 任务类型适配度(coding/review/planning/analysis/debugging/docs) |
stability |
0.0476 | 基于延迟标准差的方法稳定性 |
tierPriority |
0.0476 | 账号层级优先级:Ultra=1.0, Pro=0.67, Standard=0.33, Free=0.0 |
tierAffinity |
0.0476 | 候选层级与 manifest 推荐层级的亲和度 |
specificityMatch |
0.0476 | 请求特异性(manifest 提示)与模型层级的匹配度 |
contextAffinity |
0.0476 | 请求上下文窗口需求与模型上下文窗口的亲和度 |
sessionAvailability |
0.0476 | OAuth 会话可用性(非 OAuth 连接记 1.0) |
connectionDensity |
0.0476 | 同 provider 多连接间的负载分散(防集中) |
cacheAffinity |
0.00 | 对最可能已持有本请求 prompt-cache 前缀的连接的亲和度,默认关闭 |
resetWindowAffinity |
0.00 | 偏向配额重置窗口更有利的连接,默认关闭 |
quality |
0.03 | 来自路由事件质量追踪器的输出质量信号;无观测的候选取中性 0.5 |
reliability |
0.00 | 观测成功率 1 - failureRate(24h 历史、十样本下限),默认关闭 |
三个权重为 0 的因子(cacheAffinity、resetWindowAffinity、reliability)仍会被计算,只是默认不参与投票——cacheAffinity 还在评分之外独立门控 prompt-cache 去重(见 open-sse/services/combo/promptCacheAffinity.ts)。
评分的实现细节
calculateScore()用clamp01()把加权和钳制到 [0,1]:单个 NaN 因子不会把分数变成 NaN(NaN 排序不确定),浮点漂移也不会让分数超过 1。- 用户自定义权重通过
normalizeScoringWeights()归一化成概率分布(逐项除以总和),总和非正时回退到DEFAULT_WEIGHTS。 - 成本/延迟/稳定性三个因子依赖"池内最大值"做归一化。源码专门暴露
computePoolMaxima()让调用方一次算好再传给calculateFactors(),避免在候选池膨胀到上千目标时把 O(n) 评分退化成 O(n²) 并引发堆内存压力(源码注释记载了相关 OOM 事故的教训)。
二、Mode Packs:六个开箱即用的权重档案
本地化文档列出 4 个"模式包",当前源码 open-sse/services/autoCombo/modePacks.ts 已扩展为 6 个,本地化文档中以"关键权重"(如 Ship Fast → latencyInv 0.35 量级)概括的各包倾向,在源码中精确如下(每包总和为 1.0):
| 因子 | ship-fast | cost-saver | quality-first | offline-friendly | reliability-first | chaos-mode |
|---|---|---|---|---|---|---|
quota |
0.1333 | 0.1333 | 0.0952 | 0.3524 | 0.1333 | 0.0476 |
health |
0.2667 | 0.1810 | 0.1714 | 0.2667 | 0.3524 | 0.4000 |
costInv |
0.0476 | 0.3524 | 0.0476 | 0.0952 | 0.0381 | 0.0190 |
latencyInv |
0.3048 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0286 |
taskFit |
0.0952 | 0.0952 | 0.3524 | 0.0000 | 0.0952 | 0.1905 |
stability |
0.0000 | 0.0476 | 0.1429 | 0.0952 | 0.1905 | 0.1714 |
tierPriority |
0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0190 |
tierAffinity |
0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 |
specificityMatch |
0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 |
contextAffinity |
0.0095 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0286 |
sessionAvailability |
0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 |
resetWindowAffinity |
0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 |
connectionDensity |
0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 |
各包倾向速览:
- ship-fast → latencyInv 0.3048 + health 0.2667:低延迟 + 健康连接;
- cost-saver → costInv 0.3524:最便宜 token 胜出;
- quality-first → taskFit 0.3524 + stability 0.1429:任务适配最好且稳定;
- offline-friendly → quota 0.3524 + health 0.2667:无论速度与成本,最大化可用余量;
- reliability-first → health 0.3524 + stability 0.1905:最少意外;
- chaos-mode → health 0.4000 + taskFit 0.1905:故障注入型画像(并行扇出测试用)。
需要注意两个特性:包是整表替换而非合并——选择任意包后,DEFAULT_WEIGHTS 中 0.03 的 quality 因子会被清零,即"质量反馈信号静默关闭";tierAffinity、specificityMatch、resetWindowAffinity 在所有包中都是 0。
三、零配置自动路由:直接使用 auto/ 前缀
Auto-Combo 最大的使用亮点是无需创建任何组合。任何支持 OpenAI 格式的客户端把模型名设为 auto 或 auto/<variant> 即可:
# 任意支持 OpenAI 格式的 IDE 或 CLI 工具
Base URL: http://localhost:20128/v1
API Key: <your-endpoint-key>
# 代码/配置中设置 model:
model: "auto" # 均衡默认
model: "auto/coding" # 编码任务最优
model: "auto/fast" # 可用中最快
model: "auto/cheap" # 每 token 最便宜
7 个可调用模型 ID(源码 open-sse/services/autoCombo/autoPrefix.ts 中的 VALID_VARIANTS 定义 6 个变体,第 7 个是裸 auto):
| 模型 ID | 变体 | 行为 |
|---|---|---|
auto |
默认 | 全部已连接 provider,LKGP 策略,均衡权重 |
auto/coding |
coding | 质量优先权重,适合代码生成 |
auto/fast |
fast | 低延迟加权选择 |
auto/cheap |
cheap | 成本优化路由(最便宜优先) |
auto/offline |
offline | 偏向配额可用性最高的 provider |
auto/smart |
smart | 质量优先 + 更高探索率(10%) |
auto/lkgp |
lkgp | 显式 LKGP(与默认 auto 相同) |
auto/chaos |
chaos | 故障注入权重,用于韧性测试(混沌工程) |
parseAutoPrefix() 的解析规则:auto → {valid: true, variant: undefined};auto/coding → 合法变体;autocoding、auto/unknown → 非法。值得注意:虽然 chaos 出现在解析器中,但英文主文档的"Auto Variants Recap"只列举 auto、auto/coding、auto/fast、auto/cheap、auto/offline、auto/smart、auto/lkgp 七个 ID,可调用集合以 AUTO-COMBO.md 为准。
Category × Tier 组合:auto/<category>:<tier>
类似 OpenRouter 的后缀语法把"路由什么"(category)与"如何优化"(tier)解耦(实现见 open-sse/services/autoCombo/suffixComposition.ts):
- Category(按能力过滤候选池):
coding·reasoning·vision·chat·multimodal; - Tier(选择评分权重或池过滤):
fast(ship-fast)·cheap(别名floor)·reliable(熔断健康 + 延迟稳定)·free/pro(通过classifyTier过滤免费层/付费层)。
| 示例 | 解析结果 |
|---|---|
auto/coding:fast |
coding 池 + 低延迟权重 |
auto/coding:cheap |
coding 池 + 成本优化(别名 auto/coding:floor) |
auto/reasoning:pro |
仅 reasoning/thinking 模型 + 付费层 |
auto/vision |
视觉模型(无 tier → 均衡权重) |
auto/multimodal:free |
多模态模型 + 仅免费层 |
过滤采用fail-open语义:若约束匹配不到任何已连接模型,则回退到完整候选池,路由永远不会因为过滤而中断。核心打分器(combo.ts 链路)不变,category/tier 过滤在 buildAutoCandidates 中应用。另外,ARENA_ELO_SYNC_ENABLED 开启时,适配度由实时 Arena ELO 排名 + models.dev 层级数据驱动(否则回退静态适配表)。
请求处理链路
从英文主文档与 src/sse/handlers/chat.ts 可还原完整调用链:
Request: { model: "auto/coding" }
↓
src/sse/handlers/chat.ts 检测 auto/ 前缀
↓
createVirtualAutoCombo('coding') → 从活动连接构建候选池
↓
handleComboChat(与持久化组合共用同一引擎)
↓
自动评分选出每次请求的最佳 provider/model
零配置模式的六个关键属性:始终开启(无需开关/配置)、动态(自动反映当前已连接 provider)、会话粘性(LKGP 优先上次成功 provider)、多账号感知(每个 provider 连接都是一个独立候选)、零 DB 写入(虚拟组合仅存在于请求内)。
四、虚拟工厂:每次请求现场构建候选池
open-sse/services/autoCombo/virtualFactory.ts 是零配置模式的构造器,按如下步骤在内存中构建 AutoComboConfig:
- 拉取
getProviderConnections({ isActive: true })(所有启用连接); - 过滤出具备有效凭据的连接(API key 或未过期 OAuth token,
hasUsableOAuthToken()); - 与
getProviderRegistry()交叉核对模型可用性与价格; - 为每个
(provider, model, connection)三元组构造VirtualAutoComboCandidate; - 取
connection.defaultModel(或注册表首个模型)作为派发目标; - 用 16 因子
scorePool()+ 所选权重包打分; - 返回内存中的
AutoComboConfig交给handleComboChat()——从不持久化到 DB。
这意味着新增一个启用了 auto/* 的 provider,候选池自动扩张,无需手工编辑组合;且虚拟组合每个请求都重建,新添加或刚恢复健康的连接会被立即纳入。
发现端点:GET /api/combos/auto
src/app/api/combos/auto/route.ts 提供只读发现接口(需要管理鉴权 requireManagementAuth),枚举全部变体(基础变体、模板变体、auto/<category>:<tier> 后缀变体、auto/<family> 家族变体,见 open-sse/services/autoCombo/builtinCatalog.ts),并返回每个变体解析后的候选池,以及 context_length / max_output_tokens——取候选池各窗口的 MAX 值。客户端(如 opencode 插件)必须上报这些真实数值而非 0:广告 0 上下文会禁用客户端的自动压缩,让会话无限膨胀直到网关的历史清理破坏上下文。广告 MAX 是安全的,因为 auto-combo 的上下文预过滤会把超大请求路由到大窗口候选。
五、自愈机制:排除、探测与事故模式
open-sse/services/autoCombo/selfHealing.ts 实现了文档描述的四个自愈能力,源码中的阈值如下:
- 临时排除:评分 < 0.2(
EXCLUSION_THRESHOLD)→ 排除 5 分钟(DEFAULT_COOLDOWN_MS),重复命中冷却翻倍,上限 30 分钟(MAX_COOLDOWN_MS); - 熔断器感知:OPEN → 自动排除;HALF_OPEN → 放行 probe 探测请求;
- 事故模式:OPEN 占比 > 50%(
INCIDENT_MODE_THRESHOLD)→ 关闭探索(bandit),最大化稳定性; - 冷却恢复:排除结束后,首次请求是"probe"(降低超时)。探测逻辑为:连续 3 次成功探测才完全重新接纳(
recordProbeResult),失败则冷却翻倍并重置探测计数; - 另有重新接纳阈值 0.3(
REENTRY_THRESHOLD):评分回升且冷却到期时自动解除排除。
SelfHealingManager 以单例 getSelfHealingManager() 暴露,getStatus() 可输出当前排除数量、事故模式标志与每个排除的剩余时间。
六、Bandit 探索:5% 的随机探索流量
open-sse/services/autoCombo/engine.ts 中的 AutoComboConfig.explorationRate 默认 0.05——5% 的请求会被路由到随机 provider 进行探索,用于发现表现更好但尚未被评分模型充分认识的候选。该比例可配置(如 auto/smart 变体提升到 10%),且在事故模式下被禁用,避免探索流量干扰稳定性。
七、请求级控制:三个 Header 精调单次请求
除了持久化配置,auto 组合还支持每次请求通过 Header 覆盖评分权重与预算(实现为纯函数 open-sse/services/autoCombo/requestControls.ts,仅对携带 Header 的这一次请求生效):
| Header | 取值 | 效果 |
|---|---|---|
X-OmniRoute-Mode |
fast/balanced/quality/cheap/reliable/offline 或原始包名 ship-fast/cost-saver/quality-first/offline-friendly/reliability-first |
覆盖本次请求的评分权重;balanced/default 强制默认权重 |
X-OmniRoute-Budget |
正数(单请求最大 USD) | 硬成本上限:估算成本超限的候选在选择前被过滤 |
X-OmniRoute-Budget-Fallback |
cheapest(默认,别名 cheapest-viable/soft)或 strict(别名 block/hard) |
cheapest:回退全局最便宜候选(超限也选,旧行为);strict:拒绝选择,快速失败返回 HTTP 402 |
# 强制最快画像、单请求预算 $0.05、超预算硬阻断
curl -sS http://localhost:20128/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-OmniRoute-Mode: fast" \
-H "X-OmniRoute-Budget: 0.05" \
-H "X-OmniRoute-Budget-Fallback: strict" \
-d '{"model":"auto","messages":[{"role":"user","content":"hi"}]}'
strict 模式下若无任何候选(含最便宜者)落入预算,engine.ts 会抛出 BudgetExceededError(携带 budgetCap 与 cheapestCostUsd),调用方应将其转换为明确的"成本超预算"响应,而不是静默超支或 500。
八、路由策略:从默认评分到自定义实现
19 种组合路由策略
组合引擎共声明 19 种路由策略(src/shared/constants/routingStrategies.ts 的 ROUTING_STRATEGY_VALUES),Auto-Combo 本身对应 auto 策略(推荐),其余供持久化组合使用:priority、weighted、round-robin、context-relay、fill-first、p2c、random、least-used、cost-optimized、reset-aware、reset-window、headroom、strict-random、auto、lkgp、context-optimized、cache-optimized、fusion(并行扇出 + 裁判合成)、pipeline(顺序流水线)。
持久化 auto 组合的 6 种 RouterStrategy
持久化 strategy: "auto" 组合可通过 config.routerStrategy(或旧键 config.auto.routerStrategy)指定选择算法(实现见 open-sse/services/autoCombo/routerStrategy.ts):
rules(默认):16 因子加权评分,先过滤 OPEN 候选再scorePool()取最高分;cost/eco:按costPer1MTokens升序选最便宜健康 provider——适合批量、后台任务;latency/fast:按p95LatencyMs + errorRate * 1000排序,错误率惩罚保证"名义延迟低但不可靠"的 provider 排名靠后——适合实时聊天、自动补全;sla-aware/sla:按延迟/错误率/成本 SLO 合规度打分(延迟 35% + 错误率 35% + 健康 15% + 成本 10% + 稳定性 5%),hardConstraints: true时先按违规程度排序;lkgp:优先"最后已知良好 provider"(会话粘性),再回退rules——适合多轮对话;score:选配置加权分最高的候选,平分时保持配置顺序。
自定义策略可经公开 API 注册,然后在 config.routerStrategy 中引用:
import {
registerStrategy,
type RouterStrategy,
} from "@omniroute/open-sse/services/autoCombo/routerStrategy";
class MyCustomStrategy implements RouterStrategy {
readonly name = "my-custom";
readonly description = "My custom routing strategy";
select(pool, context) {
// 你的路由逻辑
return { provider: pool[0].provider, model: pool[0].model, strategy: this.name,
reason: "MyCustomStrategy: ...", candidatesConsidered: pool.length, finalScore: 1.0 };
}
}
registerStrategy("my-custom", new MyCustomStrategy());
选型参考:均衡负载用 rules;控成本用 cost;控延迟用 latency;严格 SLO 用 sla-aware;多轮会话用 lkgp。
九、Task Fitness:模型 × 任务适配查找
Task Fitness 为 30+ 模型在 6 种任务类型(coding、review、planning、analysis、debugging、documentation)上打分,支持通配符模式(如 *-coder → 高 coding 分)。实现 open-sse/services/autoCombo/taskFitness.ts 采用多层解析链(优先级从高到低):
- 用户覆盖(DB
model_intelligence,source='user_override'); - Arena ELO(DB
source='arena_elo');2b. 通过resolveScoresAs继承基础模型的分数;2c. 若模型已退役(#11625),跳过 1-3 层,防止陈旧竞技场数据短路第 3 层的否决; - models.dev 层级(来自
model_capabilities表,带厂商生命周期否决); - 静态
FITNESS_TABLE(仅收录带版本号且存在于目录中的模型 ID,防止家族模式误伤退役模型); - 通配符加成(在 0.5 中性基线上叠加)。
特别地,未知模型的基线是 0.5,含义是"无证据"而非"平庸模型"——中性点绝不能读作质量评价。
十、API 调用方式:零配置 vs 持久化组合
本地化文档中的 POST /api/combos/auto 属于早期接口形式;当前版本(3.8.x)不再提供独立的 POST 端点,Auto-Combo 通过两种方式消费(英文主文档 AUTO-COMBO.md 已明确更正):
方式一:零配置(推荐)——直接发请求,model 填 auto 或 auto/<variant>:
curl -X POST http://localhost:20128/v1/chat/completions \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"model":"auto/coding","messages":[{"role":"user","content":"Hello"}]}'
方式二:持久化组合——通过常规组合端点创建 strategy: "auto" 的组合并存储,可复用:
curl -X POST http://localhost:20128/api/combos \
-H "Content-Type: application/json" \
-d '{"id":"my-auto","name":"Auto Coder","strategy":"auto","config":{"auto":{"candidatePool":["anthropic","google","openai"],"weights":{"quota":0.15,"health":0.3,"costInv":0.05,"latencyInv":0.35,"taskFit":0.1,"stability":0,"tierPriority":0.05}}}}'
注意两个常见坑:auto 不使用你的持久化组合(除非组合恰好命名为 auto);openrouter/auto 是 OpenRouter 的真实付费产品("Auto Best Available"),不是 OmniRoute 别名,可用"隐藏付费模型"设置将其从 auto 候选池中排除。
十一、测试与覆盖
- 确定性路由决策矩阵:
npm run test:combo:matrix(tests/integration/combo-matrix/*.test.ts)在模拟上游下端到端验证全部 19 种策略的决策结果,覆盖 quota-share 的 DRR 公平性、context-relay 全目标数通用交接等,CI 中以--test-concurrency=1确定性运行,无需真实凭据; - 门控 live 冒烟(不在 CI):
npm run test:combo:live(进程内真实路由 +RUN_COMBO_LIVE=1)、npm run test:combo:live:vps(HTTP 调用线上服务器,需COMBO_LIVE_BASE_URL)、npm run test:combo:live:vps:failover(刻意故障切换场景)——这些测试走真实 wire 路径(组合 → provider → 补全),因需要真实凭据与 VPS 访问而有意排除在 CI 之外。
十二、实现文件速查表
| 文件 | 职责 |
|---|---|
| open-sse/services/autoCombo/scoring.ts | 16 因子评分函数、DEFAULT_WEIGHTS、池归一化 |
| open-sse/services/autoCombo/modePacks.ts | 6 个权重画像包 |
| open-sse/services/autoCombo/engine.ts | 选择逻辑、bandit 探索、预算上限 |
| open-sse/services/autoCombo/selfHealing.ts | 排除、探测、事故模式 |
| open-sse/services/autoCombo/autoPrefix.ts | auto/ 前缀解析 + 6 变体 |
| open-sse/services/autoCombo/suffixComposition.ts | auto/<category>:<tier> 组合解析 |
| open-sse/services/autoCombo/virtualFactory.ts | 由实时连接构建内存 AutoComboConfig |
| open-sse/services/autoCombo/taskFitness.ts | 模型 × 任务适配查找(5 层解析链) |
| open-sse/services/autoCombo/routerStrategy.ts | 可插拔 RouterStrategy 与注册 API |
| open-sse/services/autoCombo/requestControls.ts | 请求级 Header 解析(纯函数) |
| src/app/api/combos/auto/route.ts | 发现端点 GET /api/combos/auto |
| src/sse/handlers/chat.ts | auto 前缀短路集成 |
| src/shared/constants/routingStrategies.ts | 19 种路由策略声明 |
想快速上手或了解日常配置,可直接阅读 Auto-Combo 用户指南;想从零理解整体架构,可参考 ARCHITECTURE.md 与 自适应路由说明。
图源:docs/diagrams/auto-combo-scoring.mmd,可用
npm run docs:render-diagrams重新渲染。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00