- 后端
- API网关
- 模型推理服务
- AI Agent
【免费下载链接】semantic-router
An open, programmable decision layer for models and compute.
导读
本文围绕 semantic-router 提供的elo模型选择算法展开,介绍如何利用类 Elo 反馈分数对候选模型进行排序,在路由决策中复用历史成对对比反馈而非仅依赖当前请求的启发式判断。读完本文,你将掌握elo的 Bradley-Terry 评分原理、routing.decisions[].algorithm下的完整配置参数、反馈提交 API 的字段契约,以及评分持久化与可观测性的实现细节,可直接用于为重复工作负载的路由配置"越用越准"的模型选择策略。
概览:什么是elo选择算法
elo是一种基于反馈驱动的选择算法(selection algorithm),它以成对比较(pairwise comparison)为基础,使用类 Elo 评分体系对候选模型排序。在 semantic-router 的模型选择(model selection)体系中,它属于学习型(learning-based)选择器:通过UpdateFeedback接口从路由级反馈中在线学习,让候选模型的排名随对局(comparison)数量增加而持续改进。
在文档体系中,该算法对应选择算法片段config/fragments/algorithm/selection/elo.yaml(该片段随版本发布,实际使用时按下方配置章节在路由 decision 中直接声明)。核心实现位于 elo.go(EloSelector),持久化能力由 storage.go(FileEloStorage)提供。
主要优势
- 复用历史反馈:排序依据是历史上积累的成对比较结果,而非仅当前请求的单次启发式判断;
- 少量参数即可调排序行为:核心只需
initial_rating与k_factor两个参数即可控制冷启动起点与收敛/波动速度; - 类别感知加权:支持按不同工作负载(decision/category)维护相互独立的评分空间;
- 在线学习无需重训:评分随反馈到达逐步更新,无需离线重训练模型;
- 可选时间衰减与成本感知:可配置
decay_factor逐渐遗忘过期比较,也可通过cost_scaling_factor平衡质量与价格(详见配置章节)。
解决什么问题
模型质量会随时间变化,固定的胜者(静态优先级列表)过于僵化。elo让路由偏好历史上在相似流量上表现稳定的候选,将"谁更好"的判断从冻结的静态假设转换为由真实胜败统计驱动的动态评分。
何时使用
- 能够收集路由级反馈或质量对比(成对偏好数据);
- 期望排名随更多对局到来而逐步改进(在线学习场景);
- 单条路由存在重复工作负载,评分体系能发挥累积价值;
- 需要不重训模型即可持续学习的路由策略。
算法原理:基于 Bradley-Terry 模型的 Elo 评分
elo的数学基础是Bradley-Terry 模型(实现注释中注明参考 RouteLLM 论文思路)。它估计"模型 A 优于模型 B"的概率:
P(A ≻ B) = 1 / (1 + 10^((R_B - R_A) / 400))每次成对比较后按以下规则更新评分:
R_A' = R_A + K · (S_A - E_A)其中:
K为学习率(k_factor,默认 32);S_A为实际结果(胜 = 1,负 = 0,平 = 0.5);E_A = P(A ≻ B)为期望得分。
对应源码实现在 elo.go 的applyPairwiseFeedbackLocked:先用math.Pow(10, (loserRating.Rating-winnerRating.Rating)/400.0)计算期望胜率,再按rating += KFactor * (actual - expected)更新双方评分,同时累计Comparisons、Wins、Losses、Ties统计。
类别加权:开启category_weighted后,每个 decision 维护独立的按类别评分表(categoryRatings,键为 decision 名),使模型在"math"场景的表现不会污染其"coding"评分;选择时优先取类别评分,缺省时回退到全局评分(getRatingsForCandidates)。
三种反馈更新模式
源码updateRatingLocked支持三种反馈模式:
- 标准成对对比:
WinnerModel与LoserModel均设置,走 Bradley-Terry 完整更新;tie=true时双方实际得分均为 0.5; - 正向自反馈:仅设置
WinnerModel(如隐式信号判定某模型表现良好),评分增加KFactor * 0.1; - 负向自反馈:仅设置
LoserModel,评分减少KFactor * 0.1。
后两种模式适合只有单模型表现好坏、没有成对比较的自动信号场景(elo.go)。
配置指南:在路由 decision 中启用elo
在routing.decisions[].algorithm中声明:
algorithm: type: elo elo: initial_rating: 1200 k_factor: 32 category_weighted: true min_comparisons: 10其中initial_rating: 1200与min_comparisons: 10是教程文档示例采用的调参值;源码默认值为initial_rating: 1500、min_comparisons: 5(见DefaultEloConfig,elo.go),实际部署时可任选其一作为起点。
参数总表
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
initial_rating | float | 1500 | 新模型的起始 Elo 评分(示例用1200) |
k_factor | float | 32 | 评分波动幅度,越高越"激进"(建议范围 1–100) |
category_weighted | bool | true | 是否启用按类别(decision)独立评分 |
decay_factor | float | 0.0 | 旧比较的时间衰减(0–1,0 表示不衰减) |
min_comparisons | int | 5 | 评分被视为稳定的最少比较次数(示例用10) |
cost_scaling_factor | float | 0.0 | 成本考量强度(0 表示忽略成本) |
storage_path | string | — | 评分持久化文件路径(可选) |
auto_save_interval | string | 30s(源码兜底值) | 自动保存周期(如1m、5m、30s) |
参数解读与源码对照:
k_factor:控制单局评分变化量。k_factor越高适应越快但波动越大;Elk 默认常量EloKFactor = 32.0;min_comparisons:不仅用于文档所述的"稳定性判定",还直接参与置信度计算——calculateConfidence以min_comparisons为阈值中心,用 Sigmoid 函数1 / (1 + e^(-0.2·(comparisons - threshold)))把比较次数映射为 0.5~1 区间的置信度(elo.go);cost_scaling_factor:开启后,选择阶段会按模型每百万 token 价格(来自模型配置的Pricing.PromptPer1M)对候选评分做归一化折扣——更便宜的模型获得加分(applyCostAdjustment,elo.go),同时请求级CostWeight参与加权;decay_factor:源码EloConfig中已预留该字段(YAML 键decay_factor),用于逐步遗忘过期比较;auto_save_interval:仅在设置storage_path时生效;配置缺失或非法时回退到 30 秒默认值(见 auto_save_interval.go)。
选择器装配
elo选择器由 factory.go 的Factory.Create()依据method = elo创建:调用NewEloSelector(f.cfg.Elo)后用模型配置与类别列表执行InitializeFromConfig完成冷启动初始化。该选择器也注册进全局注册表(CreateAll),并作为hybrid选择器的组件之一复用。
选择流程:评分如何决定路由
源码层面的选择实现(Select,elo.go):
- 为每个候选模型获取评分(类别优先、全局兜底、缺失则用
initial_rating); - 按标准 Elo 概率尺度
10^(rating/400)计算各候选的归一化胜率分数(等价于将评分转为选择概率); - 若开启成本感知且请求携带
CostWeight,对分数做成本调整; - 选出分数最高者,依据其比较次数计算置信度,并生成人类可读的
Reasoning(含评分与胜负统计,类别加权时附带 decision 名); - 将各候选当前评分写入 Prometheus 指标(见可观测性章节)。
反馈流程:提交成对对比并更新评分
反馈更新链路为:POST /api/v1/feedback→ 解析Feedback→ 判定是否平局(平局双方S = 0.5,否则胜者 1.0、败者 0.0)→ 用 Bradley-Terry 计算期望分 → 更新全局与类别评分 → 按需持久化到磁盘。
Feedback API 示例
提交成对反馈:
curl -X POST http://localhost:8000/api/v1/feedback \ -H "Content-Type: application/json" \ -d '{ "query": "Solve: 2x + 5 = 15", "winner_model": "gpt-4", "loser_model": "llama-3.2-3b", "decision_name": "math_reasoning" }'反馈字段契约
| 字段 | 必填 | 说明 |
|---|---|---|
query | 是 | 原始查询文本 |
winner_model | 是 | 更优的模型名 |
loser_model | 否 | 被否定的模型(成对比较用;可留空做单模型自反馈) |
tie | 否 | 两模型表现相当 |
decision_name | 否 | 类别上下文(类别加权 Elo 使用) |
user_id | 否 | 用户标识(用于按用户追踪) |
confidence | 否 | 反馈置信度(0.0–1.0) |
反馈校验
UpdateFeedback首先调用NormalizeFeedback与ValidateFeedback(feedback_test.go 覆盖了完整契约):
- 模型名等状态键会去除首尾空白后规范化;
- 拒绝空反馈、缺模型、自身对比(
winner == loser)、置信度越界(负数、NaN、无穷大)等非法输入; - 校验失败的反馈在评分更新前即被拒绝,不会产生任何评分变更(测试
TestEloSelectorRejectsInvalidFeedbackBeforeMutation验证了这一点)。
Feedback结构还预留了FeedbackType(satisfied/need_clarification/wrong_answer/want_different)等隐式信号字段,供与自反馈模式配合使用(selector.go)。
冷启动:初始评分与静态分数种子
新模型默认以initial_rating起步。除统一起点外,InitializeFromConfig(elo.go)还支持两种种子方式:
- 全局评分初始化:为所有模型配置中的模型建立初始评分(已存在评分则保留);
- 类别静态分数转评分:当
category_weighted开启时,把类别配置中的静态ModelScores(0–1 区间)线性映射为 Elo 评分:rating = 1000 + score * 1000(常量EloMinRatingFromScore = 1000、EloRatingRange = 1000),即 0–1 分数映射到 1000–2000 区间。
映射逻辑的一个重要行为是保留已学习评分:测试 elo_category_seed_test.go 验证了"已从存储恢复的评分(如 1740)不会被静态种子(0.7 → 1700)覆盖,而缺失的模型才用静态分数补种"——这保证重启初始化不会抹掉在线学习成果。
评分持久化与多副本注意事项
文件存储
设置storage_path后,评分以 JSON 文件持久化(StoredRatings:version、last_updated、global_ratings、category_ratings),并在启动时加载、每次反馈更新后标记脏数据、由后台协程按auto_save_interval周期落盘(关闭时执行最终保存)。FileEloStorage的关键实现细节(storage.go):
- 原子写入:先写
.tmp临时文件再rename,避免写坏主文件; - 损坏文件兜底:解析失败时把原文件备份为
*.corrupted再返回错误,防止数据丢失; - 数据净化:加载时对评分做合理性钳制(100–3000),并修正负数胜负统计。
多副本状态警告
Elo 评分属于本地学习状态(内存或本地storage_path文件)。文档明确警告:在 Helm 部署中,当活动 decision 使用algorithm.type: elo时,多副本(multi-replica)路由渲染默认被拒绝——因为各副本评分互不同步会造成路由行为分裂。生产多副本场景需保持单副本,或将选择器状态外部化后再关闭该安全守卫。
可观测性:用 Prometheus 指标追踪评分演化
elo选择器深度集成 Prometheus 指标(见 metrics.go),随每次选择与反馈更新实时更新:
llm_model_elo_rating(gauge):按model, category维度的当前 Elo 评分,可用于 Grafana 追踪评分演化;llm_model_feedback_total(counter):按winner, loser, is_tie, category统计反馈事件;llm_model_rating_change(histogram):评分变化分布,桶覆盖典型 K-factor 变化范围(-32 ~ +32);llm_model_comparisons_total与llm_model_win_rate(gauge):各模型参与比较次数与胜率。
此外,GetLeaderboard(category)(elo.go)可按评分降序导出指定类别或全局的模型排行榜,便于调试与监控。
已知限制
- 依赖比较数量:评分稳定需要足够的成对比较(由
min_comparisons控制),早期阶段置信度偏低; - 冷启动偏差:新模型一律从
initial_rating起步,与其真实能力无关(可通过静态分数种子缓解); - 无语义理解:纯粹由反馈驱动,不理解查询语义,适合有反馈信号的路由场景;
- 状态本地化:内存/本地文件存储意味着多副本部署需要额外处理(见上文警告)。
小结
elo是 semantic-router 面向"反馈驱动、在线学习"场景的选择算法:以 Bradley-Terry 模型为数学内核,用成对反馈持续修正候选模型的评分;通过category_weighted隔离不同工作负载的偏好,通过decay_factor与cost_scaling_factor平衡时效与成本;配合文件持久化与 Prometheus 指标,可构建"越用越准、可观测、可复盘"的模型路由策略。若你的路由具备稳定的反馈来源与重复负载,elo是替换静态优先级排序的首选学习型方案。
- 后端
- API网关
- 模型推理服务
- AI Agent
【免费下载链接】semantic-router
An open, programmable decision layer for models and compute.
相关推荐
semantic-router 的 GMT Router 算法实战:基于多轮用户反馈的个性化模型选择
semantic router 的 GMT Router 算法实战:基于多轮用户反馈的个性化模型选择 gmtrouter 是 semantic router 中
后端API网关模型推理服务AI Agentsemantic-router 的 KNN 算法选择器:基于历史相似查询的模型路由实战指南
semantic router 的 KNN 算法选择器:基于历史相似查询的模型路由实战指南 KNN(K Nearest Neighbors)是 semantic
后端API网关模型推理服务AI AgentSemantic Router 的 Router DC 选择算法:基于双对比学习的语义相似度模型路由实战指南
Semantic Router 的 Router DC 选择算法:基于双对比学习的语义相似度模型路由实战指南 导读 router_dc 是 Semantic R
后端API网关模型推理服务AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考