OmniRoute Auto-Combo 引擎:自适应评分路由、自愈排除与零配置自动选商原理
【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute
OmniRoute 的 Auto-Combo 引擎让网关为每个请求动态挑选最优的 Provider/Model 组合:你只需声明一个候选池,引擎便通过加权评分函数、自愈排除机制与带探索(bandit)的流量分配来完成自动路由。本文基于仓库中docs/i18n/no/docs/routing/AUTO-COMBO.md文档(Auto-Combo 引擎说明),结合open-sse/services/autoCombo/下的真实源码,完整讲解评分因子与权重、Mode Packs、自愈逻辑、探索策略、REST API 用法与任务适配表,帮助你既能直接使用auto/*路由,也能理解并调优其底层选择逻辑。
它解决什么问题
在多 Provider 环境下(同一网关接入 Anthropic、Google、OpenAI 等多家上游),"该把这条请求发给谁"是一个持续变化的决策:配额会耗尽、线路会抖动、价格与延迟随任务类型而各有优劣。Auto-Combo 引擎把这个决策自动化——对每个候选(provider × model × connection)计算一个 0 到 1 之间的加权得分,选最高分者,并通过自愈机制自动把坏掉的候选暂时移出池子。
评分函数:6 因子加权模型
文档核心是一张 6 因子评分表。Auto-Combo 引擎为每个请求动态评估候选池,各因子取值均归一化到 [0,1] 区间,权重之和为 1:
| 因子 | 权重 | 说明 |
|---|---|---|
| Quota | 0.20 | 剩余容量 [0..1] |
| Health | 0.25 | 熔断器状态:CLOSED=1.0,HALF_OPEN=0.5,OPEN=0.0 |
| CostInv | 0.20 | 成本倒数(越便宜得分越高) |
| LatencyInv | 0.15 | p95 延迟倒数(越快得分越高) |
| TaskFit | 0.10 | 模型 × 任务类型的适配分 |
| Stability | 0.10 | 延迟/错误率方差低者得分高 |
源码中的评分实现
上述因子在 scoring.ts 中落地为calculateFactors()与calculateScore()两个纯函数,可以核对每行语义:
- Health 因子直接映射熔断器三态:
circuitBreakerState === "CLOSED" ? 1.0 : "HALF_OPEN" ? 0.5 : 0.0(scoring.ts#L325-L330)。 - CostInv / LatencyInv用池内最大值做归一化:
clamp01(1 - costPer1MTokens / maxCost)与clamp01(1 - p95LatencyMs / maxLatency)。池最大值通过computePoolMaxima()一次性预计算,避免逐候选重算把 O(n) 打分退化到 O(n²)。 - Stability同样以池内最大标准差归一化:
clamp01(1 - latencyStdDev / maxStdDev),延迟忽高忽低的候选会被压低。 - TaskFit通过回调
getTaskFitness(model, taskType)查任务适配表(见下文专节),查不到时回落到中性值 0.5。
最终打分calculateScore()是全部因子与对应权重的点积,并经clamp01约束在 [0,1]——注释里特别指出这同时防止了单条 NaN 遥测值导致排序不确定(scoring.ts#L160-L186)。
从当前仓库代码状态看,DEFAULT_WEIGHTS已从文档描述的 6 因子扩展为声明 16 个因子(新增tierPriority、tierAffinity、contextAffinity、cacheAffinity、reliability等信号,默认权重如 quota 0.1429、health 0.1605 等,见 scoring.ts#L62-L88)。文档中的 6 因子表描述的是模型的核心骨架;若你自定义权重,normalizeScoringWeights()会把任意非负权重重新归一化为和为 1 的分布(非法值按 0 处理,全零则回退默认权重,scoring.ts#L91-L107),所以配置时不需要手动凑总和。
Mode Packs:预设权重包
除默认权重外,引擎提供 Mode Pack——整份替换默认权重的一组预设,用于把选择偏向某一目标。文档定义的基础 4 个 Pack 及其关键权重:
| Pack | 取向 | 关键权重 |
|---|---|---|
| Ship Fast | 速度 | latencyInv: 0.35 |
| Cost Saver | 经济性 | costInv: 0.40 |
| Quality First | 最佳模型 | taskFit: 0.40 |
| Offline Friendly | 可用性 | quota: 0.40 |
仓库中的完整 Pack 实现
modePacks.ts 中的MODE_PACKS目前定义了 6 个 Pack(在文档 4 个基础包之外还多出reliability-first与chaos-mode),每个 Pack 都是对完整因子表的整份替换而非部分覆盖,权重和约为 1.0。代码中的确切取值:
- ship-fast:latencyInv 0.3048 + health 0.2667(低延迟、健康连接优先),taskFit 0.0952;
- cost-saver:costInv 0.3324 一骑绝尘(最便宜的 token 胜出);
- quality-first:taskFit 0.3524 + stability 0.1429(任务匹配 + 稳定性,追求"最好的模型且表现一致");
- offline-friendly:quota 0.3324 + health 0.2667(不顾速度与成本,最大化配额余量);
- reliability-first(#4235):health 0.3524 + stability 0.1905,供
auto/<category>:reliable后缀使用; - chaos-mode:health 0.4000 + taskFit 0.1905,面向故障注入测试,quota 权重被刻意压低(混沌模式并行扇出,配额多样性次要)。
对外只暴露两个查询函数:getModePack(name)(按名取 Pack,取不到返回 undefined 以便回退默认权重)与getModePackNames()(列出全部可用 Pack 名,modePacks.ts#L137-L146)。创建 auto-combo 时通过modePack字段指定即可。
Self-Healing:自愈与临时排除
这是 Auto-Combo 区别于普通轮询的关键。文档列出四条自愈规则:
- 临时排除:得分 < 0.2 的候选被排除 5 分钟(渐进式退避,最长 30 分钟);
- 熔断器感知:OPEN 状态的候选自动排除;HALF_OPEN 进入探测(probe)流程;
- 事故模式:当 >50% 候选处于 OPEN 时进入 incident mode——关闭探索、最大化稳定性;
- 冷却恢复:排除期满后的首个请求以缩短超时的"探测请求"身份发出。
selfHealing.ts 中的阈值与状态机
selfHealing.ts 把这些规则实现为SelfHealingManager,核心常量一一对应文档描述:
| 常量 | 值 | 对应文档规则 |
|---|---|---|
EXCLUSION_THRESHOLD | 0.2 | 得分低于此值触发排除 |
REENTRY_THRESHOLD | 0.3 | 再准入阈值(比排除阈值高,防抖) |
DEFAULT_COOLDOWN_MS | 5 分钟 | 首次排除时长 |
MAX_COOLDOWN_MS | 30 分钟 | 退避上限 |
INCIDENT_MODE_THRESHOLD | 0.5 | OPEN 占比超过 50% 进入事故模式 |
值得注意的退避细节:同一候选再次被排除时,冷却时长翻倍(min(cooldownMs * 2, MAX_COOLDOWN_MS)),反复翻车的线路会被越罚越久(selfHealing.ts#L77-L89)。探测侧则要求连续 3 次成功的探测才完全解除排除(recordProbeResult中probeCount >= 3时删除排除记录);探测失败则重置探测计数并再次翻倍冷却(selfHealing.ts#L109-L120)。事故模式由updateIncidentMode()统计全部熔断器状态中 OPEN 的占比,超过 0.5 即置位。
Bandit 探索:5% 随机流量
纯贪婪地永远选最高分,会让新加入的候选永远没有机会被评估。因此引擎保留了一小份探索流量:文档定义为5% 的请求(可配置)路由到随机 provider 用于探索,事故模式下自动禁用。
engine.ts 印证了这两点:AutoComboConfig.explorationRate的注释即0.05 = 5% exploratory(engine.ts#L43),而选择逻辑中先计算const effectiveExplorationRate = incidentMode ? 0 : config.explorationRate(engine.ts#L295)——事故期间探索率强制归零,与文档"Disabled in incident mode"完全一致。每个选择结果还会携带isExploration标记与excluded列表(被排除的候选及原因),便于排查为什么某条线路没被选中。
REST API:创建与查询 Auto-Combo
文档给出的 API 用法:
# Create auto-combo curl -X POST http://localhost:20128/api/combos/auto \ -H "Content-Type: application/json" \ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}' # List auto-combos curl http://localhost:20128/api/combos/auto请求体字段说明:
id/name:组合的唯一标识与显示名;candidatePool:候选 provider 名列表(空表示全部已连接 provider);modePack:上文的权重包名(ship-fast、cost-saver、quality-first、offline-friendly等)。
对应的路由实现在 src/app/api/combos/auto/route.ts。从引擎配置结构看(engine.ts#L25-L46),持久化的 auto combo 还可携带weights(自定义权重,会被normalizeScoringWeights()归一化)、budgetCap(单请求美元上限)、budgetFallback(cheapest或strict——全部候选超预算时是回退到最便宜者还是直接拒绝)、estimatedInputTokens(预算折算的 token 估算基准,默认 1000)与routerStrategy(可插拔的选商策略名)等字段,可按需补充进配置。
Task Fitness:模型 × 任务适配表
文档指出适配表覆盖30+ 模型 × 6 种任务类型(coding、review、planning、analysis、debugging、documentation),并支持通配符模式(例如*-coder→ 高 coding 分)。
taskFitness.ts 的头部注释给出了完整的解析链,优先级从高到低:
- 用户覆盖(DB
model_intelligence,source='user_override'); - Arena ELO(DB 同步的实时 ELO 排名);
- models.dev 层级(由
model_capabilities能力数据推导,且带厂商生命周期否决——已退役模型 id 永远不会拿到层级分); - 静态 FITNESS_TABLE——一个刻意保持精简的、只收录带版本号模型 id的手工维护表(文件中的
FITNESS_TABLE.coding等按任务类型分节); - 通配符加成——在 0.5 中性基线上按模式匹配加分,文档中的
*-coder就属于这一层。
注释特别强调:0.5 的基线含义是"无证据",不是"平庸"——查不到任何数据行的模型得到中性分,既不会被抬升也不会被惩罚。静态层只收录版本化 id 是为了避免无版本 family 模式(如裸claude)误匹配厂商已退役的旧模型并给出过高分数;配套脚本scripts/check/check-model-lifecycle.mjs会在构建期拦截此类行。
关键文件索引
文档附带的文件-职责对照表(路径为仓库根目录相对路径):
| 文件 | 职责 |
|---|---|
| open-sse/services/autoCombo/scoring.ts | 评分函数、DEFAULT_WEIGHTS、池归一化(computePoolMaxima) |
| open-sse/services/autoCombo/taskFitness.ts | 模型 × 任务适配查表(含五级解析链) |
| open-sse/services/autoCombo/engine.ts | 选择逻辑、bandit 探索、预算上限(BudgetExceededError) |
| open-sse/services/autoCombo/selfHealing.ts | 排除、探测、事故模式(SelfHealingManager) |
| open-sse/services/autoCombo/modePacks.ts | 权重包(基础 4 包 + reliability-first / chaos-mode) |
| src/app/api/combos/auto/route.ts | Auto-Combo REST API |
小结与调优建议
- 默认即可用:不指定
modePack与自定义权重时,引擎用DEFAULT_WEIGHTS直接评分,零配置完成自动选商; - 有明确目标时选 Pack:追求快用 ship-fast、省钱用 cost-saver、要质量用 quality-first、弱网/配额紧张用 offline-friendly;
- 想强化某信号时自定义权重:任意非负权重会被
normalizeScoringWeights()自动归一化,无需手动凑和为 1; - 理解选商异常:得分低于 0.2 的候选会被渐进退避排除(5 分钟起、最长 30 分钟),连续 3 次探测成功才完全回归;>50% 候选 OPEN 时进入事故模式并关闭 5% 探索流量——排查"某条线路一直收不到流量"时应先核对这两个状态;
- 想让特定模型更常命中:优先维护任务适配信号(用户覆盖 / 静态表 / 通配符),让 TaskFit 因子说话,而不是硬编码固定目标。
【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考