人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。------------ 马尔科姆·格拉德威尔

🌟 Hello,我是Xxtaoaooo!
🌈 "代码是逻辑的诗篇,架构是思想的交响"
摘要
2026 年的模型市场正在以"周"为单位刷新:Google 发布 Gemini 4 Carbon,距上一代 Argon 不到一个月;OpenAI 用 Luna、Terra、Sol、Astra 四档命名明确划分能力梯队;Anthropic 的 S-1 文件则透露,上线超过六个月的模型贡献的收入不足 20%------模型的半衰期越来越短,应用侧不可能再绑死单一模型。与此同时,微软 Copilot Fusion 已开始在 Claude 与 GPT 之间按任务路由编码请求,OpenRouter 更是彻底重建了默认路由算法:从只按价格排序,升级为综合有效价格、首 Token 延迟(TTFT)、吞吐、错误率与输出质量的 Routing Cost 模型,官方实测 TTFT 下降 16.9%、429 错误减少 67%。本文围绕这条前沿主线展开:先拆解 Routing Cost 的五维评分模型与归一化方法,再用不到 200 行 Python 实现一个带 EWMA 健康统计、加权选路、熔断冷却与失败重放的智能路由器,随后给出 TTFT 趋势、错误分布、Provider 象限三张观测图与调参建议,最后附上完整踩坑清单。全文配 5 张可视化图、3 段代码与 2 张对比表,适合正在构建多模型网关、Agent 平台或 LLM 应用的工程师与架构师阅读。
一、引言:模型爆炸时代,"选路"本身就是产品能力
三条新闻勾勒出问题的轮廓。其一,Gemini 4 Carbon 以 59 分登上 Artificial Analysis 智能指数榜首,距上一代 Argon 发布不到一个月;其二,微软推出 Copilot Fusion,在 Claude 与 GPT 之间按任务路由编码请求,在编码智能体榜上以 60 分紧咬 Claude Code 的 62 分,但每任务成本 5.59 美元、约为对方一半;其三,OpenRouter 宣布重建默认 Provider 路由算法------旧的"只按价格排序"被 Routing Cost 取代,实测 TTFT 降低 16.9%、429 错误减少 67%。
这三条新闻指向同一个结论:当模型供给以月为单位迭代、价格与质量矩阵持续洗牌时,"这次请求发给谁"从运维细节升级成了核心产品能力。选路做得好,同成本下体验与正确率双升;做不好,要么贵、要么慢、要么在高峰期被 429 淹没。
二、原理:把五个目标压成一个分数
2.1 Routing Cost 的五个维度
| 维度 | 含义 | 典型量纲 | 影响什么 |
|---|---|---|---|
| 有效价格(effective price) | 单价 × 实际用量(含缓存折扣) | $ / 1M tokens | 直接成本 |
| 首 Token 延迟(TTFT) | 请求发出到首个 Token 返回 | ms | 交互感知流畅度 |
| 吞吐(throughput) | 生成阶段每秒输出 Token 数 | tok/s | 长文本等待时间 |
| 错误率 | 429 / 5xx / 超时占比 | % | 可用性与重试成本 |
| 输出质量 | 编码、推理等榜单成绩归一化 | 分 | 正确率与返工率 |
2.2 评分模型:归一化再加权
2.2.1 归一化:把不同量纲拉到同一把尺上
五个维度量纲完全不同:价格是美元、延迟是毫秒、质量是分数。Routing Cost 的第一步是对每个维度做 min-max 归一化,统一到 0~1,且方向对齐为"越小越好"(质量取反向)。
2.2.2 权重:场景决定取舍
权重没有万能值:交互式入口把 TTFT 权重调高,离线批处理把价格权重调高,Agent 关键链路则应把错误率与质量权重调高。每次请求到达后,先过滤掉冷却中的 Provider,再对候选池逐维归一化、加权求和,选 Routing Cost 最低者。
图1:一次请求的路由决策流程(flowchart|从实时观测、归一化评分到失败冷却的闭环,观测数据持续回写使评分自动收敛)
#mermaid-svg-imsVZF3YEb1pkngh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-imsVZF3YEb1pkngh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-imsVZF3YEb1pkngh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-imsVZF3YEb1pkngh .error-icon{fill:hsl(30, 28.5714285714%, 100%);}#mermaid-svg-imsVZF3YEb1pkngh .error-text{fill:#000000;stroke:#000000;}#mermaid-svg-imsVZF3YEb1pkngh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-imsVZF3YEb1pkngh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-imsVZF3YEb1pkngh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-imsVZF3YEb1pkngh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-imsVZF3YEb1pkngh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-imsVZF3YEb1pkngh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-imsVZF3YEb1pkngh .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-imsVZF3YEb1pkngh .marker.cross{stroke:#0b0b0b;}#mermaid-svg-imsVZF3YEb1pkngh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;}#mermaid-svg-imsVZF3YEb1pkngh p{margin:0;}#mermaid-svg-imsVZF3YEb1pkngh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-imsVZF3YEb1pkngh .cluster-label text{fill:#000000;}#mermaid-svg-imsVZF3YEb1pkngh .cluster-label span{color:#000000;}#mermaid-svg-imsVZF3YEb1pkngh .cluster-label span p{background-color:transparent;}#mermaid-svg-imsVZF3YEb1pkngh .label text,#mermaid-svg-imsVZF3YEb1pkngh span{fill:#333;color:#333;}#mermaid-svg-imsVZF3YEb1pkngh .node rect,#mermaid-svg-imsVZF3YEb1pkngh .node circle,#mermaid-svg-imsVZF3YEb1pkngh .node ellipse,#mermaid-svg-imsVZF3YEb1pkngh .node polygon,#mermaid-svg-imsVZF3YEb1pkngh .node path{fill:#F6F8FA;stroke:#5B8FF9;stroke-width:1px;}#mermaid-svg-imsVZF3YEb1pkngh .rough-node .label text,#mermaid-svg-imsVZF3YEb1pkngh .node .label text,#mermaid-svg-imsVZF3YEb1pkngh .image-shape .label,#mermaid-svg-imsVZF3YEb1pkngh .icon-shape .label{text-anchor:middle;}#mermaid-svg-imsVZF3YEb1pkngh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-imsVZF3YEb1pkngh .rough-node .label,#mermaid-svg-imsVZF3YEb1pkngh .node .label,#mermaid-svg-imsVZF3YEb1pkngh .image-shape .label,#mermaid-svg-imsVZF3YEb1pkngh .icon-shape .label{text-align:center;}#mermaid-svg-imsVZF3YEb1pkngh .node.clickable{cursor:pointer;}#mermaid-svg-imsVZF3YEb1pkngh .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-imsVZF3YEb1pkngh .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-imsVZF3YEb1pkngh .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-imsVZF3YEb1pkngh .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-imsVZF3YEb1pkngh .edgeLabel{background-color:hsl(90, 28.5714285714%, 97.2549019608%);text-align:center;}#mermaid-svg-imsVZF3YEb1pkngh .edgeLabel p{background-color:hsl(90, 28.5714285714%, 97.2549019608%);}#mermaid-svg-imsVZF3YEb1pkngh .edgeLabel rect{opacity:0.5;background-color:hsl(90, 28.5714285714%, 97.2549019608%);fill:hsl(90, 28.5714285714%, 97.2549019608%);}#mermaid-svg-imsVZF3YEb1pkngh .labelBkg{background-color:rgba(248, 250, 246.0000000001, 0.5);}#mermaid-svg-imsVZF3YEb1pkngh .cluster rect{fill:hsl(30, 28.5714285714%, 100%);stroke:hsl(30, 0%, 90%);stroke-width:1px;}#mermaid-svg-imsVZF3YEb1pkngh .cluster text{fill:#000000;}#mermaid-svg-imsVZF3YEb1pkngh .cluster span{color:#000000;}#mermaid-svg-imsVZF3YEb1pkngh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(30, 28.5714285714%, 100%);border:1px solid hsl(30, 0%, 90%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-imsVZF3YEb1pkngh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-imsVZF3YEb1pkngh rect.text{fill:none;stroke-width:0;}#mermaid-svg-imsVZF3YEb1pkngh .icon-shape,#mermaid-svg-imsVZF3YEb1pkngh .image-shape{background-color:hsl(90, 28.5714285714%, 97.2549019608%);text-align:center;}#mermaid-svg-imsVZF3YEb1pkngh .icon-shape p,#mermaid-svg-imsVZF3YEb1pkngh .image-shape p{background-color:hsl(90, 28.5714285714%, 97.2549019608%);padding:2px;}#mermaid-svg-imsVZF3YEb1pkngh .icon-shape .label rect,#mermaid-svg-imsVZF3YEb1pkngh .image-shape .label rect{opacity:0.5;background-color:hsl(90, 28.5714285714%, 97.2549019608%);fill:hsl(90, 28.5714285714%, 97.2549019608%);}#mermaid-svg-imsVZF3YEb1pkngh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-imsVZF3YEb1pkngh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-imsVZF3YEb1pkngh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-imsVZF3YEb1pkngh .stage>*{fill:#E8F0FF!important;stroke:#5B8FF9!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .stage span{fill:#E8F0FF!important;stroke:#5B8FF9!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .stage tspan{fill:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .decide>*{fill:#FFF1D6!important;stroke:#F6BD16!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .decide span{fill:#FFF1D6!important;stroke:#F6BD16!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .decide tspan{fill:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .bad>*{fill:#FFE9EC!important;stroke:#E8684A!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .bad span{fill:#FFE9EC!important;stroke:#E8684A!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .bad tspan{fill:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .good>*{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .good span{fill:#E6FFFB!important;stroke:#13C2C2!important;color:#13191c!important;}#mermaid-svg-imsVZF3YEb1pkngh .good tspan{fill:#13191c!important;} 全部冷却中
有候选池
是
429 或 5xx
请求到达
读取各 Provider 实时指标
EWMA:TTFT / 错误率 / 吞吐
存在可用 Provider?
兜底:排队或返回默认档
五维指标 min-max 归一化
Routing Cost 加权求和
选取成本最低的 Provider
发起调用
成功?
回写健康度:延迟 / 成功
进入冷却 60s
重放到次优 Provider
返回结果
2.3 与经典负载均衡的关系
加权轮询、一致性哈希解决的是"同质节点"的分发问题;Routing Cost 面对的是异质且动态的节点------同一个请求在不同 Provider 处的价格、延迟、质量都不同,且随负载实时波动。它本质上是把 Google SRE 处理过载的思想(基于实时压力信号丢弃或转移请求)延伸到了"按多维性价比主动选路"。
《Google SRE 运维解密》在"处理过载"一章中的告诫同样适用于 LLM 路由:"无差别的重试是一把双刃剑------它恰恰会在系统最脆弱的时刻注入最大流量。"这正是路由器必须内置冷却与重放上限的原因。
| 路由策略 | 决策依据 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 价格优先(旧默认) | 单价 | 成本最低 | 延迟与错误率失控 | 离线批处理 |
| 加权轮询 | 预设比例 | 实现简单 | 对质量与故障全盲 | 同质供应商池 |
| P95 延迟 SLO | 延迟分位 | 体验稳定 | 忽略成本与质量 | 在线交互单一诉求 |
| Routing Cost | 五维加权 | 全局最优、动态收敛 | 依赖观测基建 | 生产环境默认 |
三、代码实战:两百行以内的智能路由器
3.1 健康度统计:用 EWMA 平滑观测
意图与要点:延迟与错误率是高频抖动信号,直接用瞬时值选路会来回打摆。指数加权移动平均(EWMA)让新样本权重高、历史平滑衰减,只需一个系数就能兼顾灵敏度与稳定性。
python
import time
from dataclasses import dataclass, field
ALPHA = 0.3 # 平滑系数:越大越灵敏,越小越稳重
@dataclass
class Provider:
name: str
price: float # 每百万输出 token 有效价格(美元)
quality: float # 质量分(榜单成绩归一化到 0~1)
ttft_ewma: float = 800.0 # 首 token 延迟(ms),初始给保守值
err_ewma: float = 0.02 # 错误率(429 / 5xx / 超时)
cooldown_until: float = 0.0 # 冷却截止时间戳
def record(self, ttft_ms: float, ok: bool):
"""每次调用后回写观测:延迟与错误率都用 EWMA 平滑。"""
self.ttft_ewma = ALPHA * ttft_ms + (1 - ALPHA) * self.ttft_ewma
err = 0.0 if ok else 1.0
self.err_ewma = ALPHA * err + (1 - ALPHA) * self.err_ewma
def available(self) -> bool:
return time.time() >= self.cooldown_until
def penalty(self, seconds: int = 60):
"""触发 429/5xx 后进入冷却,避免重试风暴压垮同一家。"""
self.cooldown_until = time.time() + seconds
核心点评: 初始值很关键------新接入的 Provider 没有历史数据,给保守的 800ms / 2% 错误率起步,相当于"新人先小流量试跑",用真实观测逐步修正。
3.2 评分与选路:Routing Cost 的核心实现
意图与要点:先过滤可用节点,再对候选池逐维归一化、按场景权重加权求和。注意质量维度方向相反------分数越高越好,归一化后要取反。
python
# 权重按场景调整:交互入口重延迟,Agent 链路重错误率与质量
WEIGHTS = {"price": 0.30, "ttft": 0.25, "err": 0.30, "quality": 0.15}
def normalize(values: list[float], lower_is_better: bool = True) -> list[float]:
"""min-max 归一化到 0~1,方向统一为越小越好。"""
lo, hi = min(values), max(values)
if hi == lo:
return [0.0] * len(values)
scaled = [(v - lo) / (hi - lo) for v in values]
return scaled if lower_is_better else [1 - s for s in scaled]
def routing_cost(providers: list[Provider]) -> list[float]:
"""多维指标加权压缩成单个可比分数:越低越优。"""
dims = {
"price": normalize([p.price for p in providers]),
"ttft": normalize([p.ttft_ewma for p in providers]),
"err": normalize([p.err_ewma for p in providers]),
"quality": normalize([p.quality for p in providers],
lower_is_better=False), # 质量越高越好
}
return [sum(WEIGHTS[k] * dims[k][i] for k in WEIGHTS)
for i in range(len(providers))]
核心点评: hi == lo 的分支不可省略------当所有候选价格相同(常见于同厂多区域端点)时除零会产生 NaN,选路将随机失效,这是我在联调时踩过的真实坑。
3.3 失败降级与重放:把一次调用变成一条链路
意图与要点:失败不是异常而是常态,路由器要把"重试下一个"内建为语义:429/5xx 触发冷却并重放到次优节点,全池耗尽前绝不放弃。
3.3.1 冷却:给重试风暴上保险
python
import asyncio
import httpx
MAX_RETRY = 3
async def route_and_call(providers: list[Provider], payload: dict) -> dict:
"""选路 + 失败重放:单次请求映射为一条降级链。"""
for _ in range(MAX_RETRY):
pool = [p for p in providers if p.available()]
if not pool: # 全员冷却 → 等待一个窗口
await asyncio.sleep(1)
continue
costs = routing_cost(pool)
best = pool[costs.index(min(costs))] # Routing Cost 最低者胜出
try:
t0 = time.perf_counter()
async with httpx.AsyncClient(timeout=30) as cli:
r = await cli.post(f"https://{best.name}/v1/chat", json=payload)
ttft = (time.perf_counter() - t0) * 1000
r.raise_for_status()
best.record(ttft, ok=True)
return r.json()
except httpx.HTTPStatusError as e:
best.record(9999, ok=False)
if e.response.status_code in (429, 500, 502, 503):
best.penalty(60) # 冷却 60s,换下一家
except httpx.HTTPError: # 网络层异常
best.record(9999, ok=False)
best.penalty(30)
raise RuntimeError("all providers exhausted")
核心点评: 示例用请求总耗时近似 TTFT,生产环境应在流式响应的首字节处埋点才是真 TTFT;重放次数必须封顶,否则降级链会放大成 SRE 警告的"重试风暴"。
图2:失败降级链时序(sequenceDiagram|429 触发冷却后请求被重放到次优 Provider,观测数据回写使下一轮评分自动收敛)
备选Provider 低价Provider 路由器 客户端 备选Provider 低价Provider 路由器 客户端 #mermaid-svg-yeERlzOx0wopYEoK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yeERlzOx0wopYEoK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yeERlzOx0wopYEoK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yeERlzOx0wopYEoK .error-icon{fill:hsl(39.1304347826, 100%, 100%);}#mermaid-svg-yeERlzOx0wopYEoK .error-text{fill:#000000;stroke:#000000;}#mermaid-svg-yeERlzOx0wopYEoK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yeERlzOx0wopYEoK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yeERlzOx0wopYEoK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yeERlzOx0wopYEoK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yeERlzOx0wopYEoK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yeERlzOx0wopYEoK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yeERlzOx0wopYEoK .marker{fill:#5B8FF9;stroke:#5B8FF9;}#mermaid-svg-yeERlzOx0wopYEoK .marker.cross{stroke:#5B8FF9;}#mermaid-svg-yeERlzOx0wopYEoK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;}#mermaid-svg-yeERlzOx0wopYEoK p{margin:0;}#mermaid-svg-yeERlzOx0wopYEoK .actor{stroke:#5B8FF9;fill:#E8F0FF;}#mermaid-svg-yeERlzOx0wopYEoK text.actor>tspan{fill:#333;stroke:none;}#mermaid-svg-yeERlzOx0wopYEoK .actor-line{stroke:#5B8FF9;}#mermaid-svg-yeERlzOx0wopYEoK .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-yeERlzOx0wopYEoK .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-yeERlzOx0wopYEoK .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-yeERlzOx0wopYEoK #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-yeERlzOx0wopYEoK .sequenceNumber{fill:#13191c;}#mermaid-svg-yeERlzOx0wopYEoK #sequencenumber{fill:#333;}#mermaid-svg-yeERlzOx0wopYEoK #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-yeERlzOx0wopYEoK .messageText{fill:#333;stroke:none;}#mermaid-svg-yeERlzOx0wopYEoK .labelBox{stroke:#5B8FF9;fill:#E8F0FF;}#mermaid-svg-yeERlzOx0wopYEoK .labelText,#mermaid-svg-yeERlzOx0wopYEoK .labelText>tspan{fill:#333;stroke:none;}#mermaid-svg-yeERlzOx0wopYEoK .loopText,#mermaid-svg-yeERlzOx0wopYEoK .loopText>tspan{fill:#333;stroke:none;}#mermaid-svg-yeERlzOx0wopYEoK .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#5B8FF9;fill:#5B8FF9;}#mermaid-svg-yeERlzOx0wopYEoK .note{stroke:#F6BD16;fill:#FFF7E6;}#mermaid-svg-yeERlzOx0wopYEoK .noteText,#mermaid-svg-yeERlzOx0wopYEoK .noteText>tspan{fill:#333;stroke:none;}#mermaid-svg-yeERlzOx0wopYEoK .activation0{fill:#D6E4FF;stroke:hsl(99.1304347826, 100%, 85.4901960784%);}#mermaid-svg-yeERlzOx0wopYEoK .activation1{fill:#D6E4FF;stroke:hsl(99.1304347826, 100%, 85.4901960784%);}#mermaid-svg-yeERlzOx0wopYEoK .activation2{fill:#D6E4FF;stroke:hsl(99.1304347826, 100%, 85.4901960784%);}#mermaid-svg-yeERlzOx0wopYEoK .actorPopupMenu{position:absolute;}#mermaid-svg-yeERlzOx0wopYEoK .actorPopupMenuPanel{position:absolute;fill:#E8F0FF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-yeERlzOx0wopYEoK .actor-man line{stroke:#5B8FF9;fill:#E8F0FF;}#mermaid-svg-yeERlzOx0wopYEoK .actor-man circle,#mermaid-svg-yeERlzOx0wopYEoK line{stroke:#5B8FF9;fill:#E8F0FF;stroke-width:2px;}#mermaid-svg-yeERlzOx0wopYEoK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 观测回写 EWMA,下一轮评分自动收敛 chat 请求1计算 Routing Cost2转发请求3429 Too Many Requests4P1 冷却 60s 并记录错误5重放到次优 Provider6200,首 Token 690ms7流式返回结果8
四、效果观测与调参
4.1 TTFT 趋势:验证路由升级的收益
图3:路由算法切换前后的 TTFT 走势(xychart-beta|数值为按官方公布的 16.9% 降幅校准的示意曲线,上为 p95、下为 p50)
#mermaid-svg-EcQyxZLybF0BKpNt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EcQyxZLybF0BKpNt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EcQyxZLybF0BKpNt .error-icon{fill:#552222;}#mermaid-svg-EcQyxZLybF0BKpNt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EcQyxZLybF0BKpNt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EcQyxZLybF0BKpNt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EcQyxZLybF0BKpNt .marker.cross{stroke:#333333;}#mermaid-svg-EcQyxZLybF0BKpNt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EcQyxZLybF0BKpNt p{margin:0;}#mermaid-svg-EcQyxZLybF0BKpNt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TTFT trend after Routing Cost upgrade (ms) Old(price-first)Day7Day14Day21Day30 16001400120010008006004002000 TTFT ms
切换后 p95 与 p50 同步下行且差距收窄,说明长尾请求(被路由到慢节点的那些)受益最明显------这正是多目标评分相对"价格优先"的核心增益。
4.2 错误分布:定位下一优化点
图4:路由升级前一周的错误类型分布(pie|示意数据,限流类 429 占比近半,是冷却机制设计的直接依据)
#mermaid-svg-a1JdFVg2XwCUFvzk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-a1JdFVg2XwCUFvzk .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-a1JdFVg2XwCUFvzk .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-a1JdFVg2XwCUFvzk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-a1JdFVg2XwCUFvzk .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-a1JdFVg2XwCUFvzk .marker.cross{stroke:#0b0b0b;}#mermaid-svg-a1JdFVg2XwCUFvzk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;}#mermaid-svg-a1JdFVg2XwCUFvzk p{margin:0;}#mermaid-svg-a1JdFVg2XwCUFvzk .pieCircle{stroke:#000000;stroke-width:2px;opacity:0.7;}#mermaid-svg-a1JdFVg2XwCUFvzk .pieOuterCircle{stroke:#000000;stroke-width:1px;fill:none;}#mermaid-svg-a1JdFVg2XwCUFvzk .pieTitleText{text-anchor:middle;font-size:25px;fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-a1JdFVg2XwCUFvzk .slice{font-family:"trebuchet ms",verdana,arial,sans-serif;fill:#000000;font-size:17px;}#mermaid-svg-a1JdFVg2XwCUFvzk .legend text{fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:17px;}#mermaid-svg-a1JdFVg2XwCUFvzk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 46%22%18%9%5%路由升级前一周错误类型分布(示意) 限流 429 46 网关 5xx 22 超时 18 网络异常 9 内容截断 5
4.3 Provider 选择:用象限图定期复核
图5:Provider 性价比矩阵(quadrantChart|坐标按 Artificial Analysis 公开评测与定价折算的示意,左上象限构成首选池)
#mermaid-svg-catTAcm7GmQDZ75L{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-catTAcm7GmQDZ75L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-catTAcm7GmQDZ75L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-catTAcm7GmQDZ75L .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-catTAcm7GmQDZ75L .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-catTAcm7GmQDZ75L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-catTAcm7GmQDZ75L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-catTAcm7GmQDZ75L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-catTAcm7GmQDZ75L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-catTAcm7GmQDZ75L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-catTAcm7GmQDZ75L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-catTAcm7GmQDZ75L .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-catTAcm7GmQDZ75L .marker.cross{stroke:#0b0b0b;}#mermaid-svg-catTAcm7GmQDZ75L svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:14px;}#mermaid-svg-catTAcm7GmQDZ75L p{margin:0;}#mermaid-svg-catTAcm7GmQDZ75L :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Premium Pool Best Value Pool Bulk Pool Avoid Claude Opus 5.5 GPT-6 Luna Gemini 4 Carbon GLM 5.3 Flash DeepSeek V4.1 Flash Low PriceHigh PriceLow QualityHigh Quality Provider Value Matrix
矩阵每月复核一次即可:模型迭代太快(Gemini 4 Carbon 距 Argon 不到一个月),静态矩阵会迅速过期,它的价值在于为权重调整提供直觉锚点,而非精确答案。
4.4 调参建议
- EWMA 系数从 0.3 起步,抖动明显再降;新 Provider 单独给更高系数加快收敛。
- 冷却时长按错误类型分级:429 给长冷却(对方确实过载),网络抖动给短冷却。
- 质量维度定期用榜单或自建回归集回填,否则评分会随模型迭代悄悄漂移。
- 灰度切换:新旧路由并行跑影子流量,TTFT 与错误率双向验证后再切默认。
五、踩坑清单:五条实战教训
- 别在选路时同步查询指标:健康度必须内存常驻、异步更新,否则路由器自己成为延迟瓶颈。
- 缓存命中的请求别进评分池:缓存命中价格近乎为零,混入会污染价格维度的归一化。
- 长上下文请求单独分池:128K+ 请求的 TTFT 分布完全不同,与短请求混评会互相拖累。
- 失败请求也要回写观测:只记成功样本会让慢节点"看起来很快",评分系统性失真。
- 给权重留配置接口:业务高峰期临时调高错误率权重,比临时扩容便宜得多。
六、总结
复盘这次从零实现路由器的过程,我最大的收获是换了一个视角看模型市场:模型每几个月就换一代,Anthropic 的 S-1 甚至显示上线超半年的模型贡献收入不足两成,但路由器会沉淀为资产------它把"选模型"从一次次人工决策,变成了一套随观测数据自动进化的机制。Routing Cost 的本质是多目标决策:把价格、TTFT、吞吐、错误率、质量五个互相牵制的维度压成一个可比分数,权重即产品策略。实现层面,EWMA 让观测抗抖动,min-max 归一化解决量纲冲突,冷却与重放把故障隔离成局部事件而非全局雪崩;而 OpenRouter 公布的 TTFT 下降 16.9%、429 减少 67% 证明这套机制在真实流量规模上同样成立。我也踩过不少坑:归一化除零、只记成功样本、同步查指标拖慢选路,这些教训都已沉淀进上文清单。下一步我打算引入按任务类型分池与质量回归集自动回填,让"交互池"与"批处理池"各得其所。如果你正在搭建多模型网关或 Agent 平台,我的建议是从 300 行以内的自研路由器起步,先把观测埋点做扎实------没有数据,一切选路策略都是猜测。
🌟 嗨,我是Xxtaoaooo!
⚙️ 【点赞】让更多同行看见深度干货
🚀 【关注】持续获取行业前沿技术与经验
🧩 【评论】分享你的实战经验或技术困惑
作为一名技术实践者,我始终相信:
每一次技术探讨都是认知升级的契机,期待在评论区与你碰撞灵感火花🔥
参考链接
1 OpenRouter 官方文档(Provider 路由机制) --- https://openrouter.ai/docs
2 LiteLLM:开源 LLM 网关与路由实现 --- https://github.com/BerriAI/litellm
3 《Google SRE 运维解密》处理过载一章 --- https://sre.google/sre-book/handling-overload/
4 LangGraph:智能体编排框架 --- https://github.com/langchain-ai/langgraph
5 Artificial Analysis 模型评测榜 --- https://artificialanalysis.ai