通过数学建模揭示:低价模型轻微降质时重试率上升,累积升级流量可能快速耗尽高价模型配额,导致实际成本远超预期。
每次一个便宜模型降价——这周我的信息流里是 DeepSeek-V4-Pro-0813,上个月是另一个——白板上就会画出一套相同的架构:所有请求先打到便宜模型,"偶尔"在便宜模型处理不好时升级到贵价模型(Grok 4.6,或者你用的什么高级端点)。便宜加好,再加一点溢价。有什么可能出问题?
以下是一个我曾参与审查的系统实际出现故障的事件链:
便宜模型轻微降级(提供方悄无声息的变更)。可重试、低置信度的响应从 2% 升到 6%。
路由器的升级规则是:置信度低于阈值就升级。升级到高级模型的流量变成原来的三倍。
高级模型对账户触发限流。升级请求开始超时。
重试包装器重试这次升级——即重试高级调用——从而加深了限流程度。
当月高级预算在 9 天内耗尽。财务问原因,没人能说清哪些请求升级了、为什么。
这个实现没能守住的不变性是:升级率是一个有界的、可解释的系统属性,而不是阈值的副产品。如果你说不清自己的升级预算、证明不了你的路由器在降级时仍能遵守它,那你就不是一个路由策略——你只是在一个定时炸弹上等爆。
"便宜加好"是一个需要验证的主张,而不是事实。我没有对 DeepSeek-V4-Pro-0813 或 Grok 4.6 做基准测试,下文中的两个名字都仅作示例端点。你的测试工具必须在升级前验证质量。
每个请求产生一个主响应加一个标量置信度/质量信号。信号可以是验证器、评判模型或启发式方法——协议不在乎是哪种。
你有一个高级预算,用速率表示(例如≤ 5% 的请求可持续升级)和一个上限(窗口内的绝对计数)。
升级和重试共享同一个下游限流——这正是上面那个故障的耦合点。
把每个请求当作一个状态机,而不是一次函数调用:
PRIMARY_CALL ──ok, confident──▶ DONE
│
├─ok, low confidence──▶ BUDGET_CHECK ──allowed──▶ ESCALATE ──▶ DONE(escalated)
│ │
│ └─denied──▶ DONE(degraded, logged, sampled for replay)
│
└─error──▶ RETRY_ONCE ──▶ (same states; never re-escalate a retried escalation)
三条规则使其收敛:
升级前做预算检查,而不是之后。 一个令牌桶控制升级。拒绝升级时优雅降级到主答案并打上标记,以便后续离线用高级模型重放。
重试永不重新进入升级路径。 失败的重试升级返回降级结果,而不是再调一次高级。这打破了重试 ↔ 限流的反馈循环。
每次升级都带原因码(low_confidence、verifier_reject、timeout_primary)写入只追加日志。如果你解释不了自己的升级分布,就没法排查账单问题。
以下代码仅用标准库即可运行。它注入主模型降级和高级限流,然后检查你的路由器是否守住了升级不变性:
import random
from dataclasses import dataclass, field
@dataclass
class Bucket:
rate: float # tokens per request-window
cap: int
tokens: float = 0.0
def allow(self) -> bool:
self.tokens = min(self.cap, self.tokens + self.rate)
if self.tokens >= 1.0:
self.tokens -= 1.0
return True
return False
@dataclass
class Stats:
n: int = 0
escalated: int = 0
degraded: int = 0
premium_calls: int = 0
reasons: dict = field(default_factory=dict)
def simulate(n=20000, degradation_start=5000, low_conf_prob=0.02,
degraded_prob=0.06, premium_limit_per_100=8):
bucket = Bucket(rate=0.05, cap=50) # 5% sustained escalation budget
s = Stats()
premium_used_in_window = 0
for i in range(n):
s.n += 1
if i % 100 == 0:
premium_used_in_window = 0
low_conf = random.random() < (degraded_prob if i >= degradation_start else low_conf_prob)
if not low_conf:
continue
if not bucket.allow():
s.degraded += 1
continue
# premium rate limit: reject when window quota exhausted
if premium_used_in_window >= premium_limit_per_100:
s.degraded += 1 # rule 2: no retry-storm into premium
continue
premium_used_in_window += 1
s.escalated += 1
s.premium_calls += 1
s.reasons["low_confidence"] = s.reasons.get("low_confidence", 0) + 1
return s
s = simulate()
rate = s.escalated / s.n
print(f"escalation_rate={rate:.4f} degraded={s.degraded} premium_calls={s.premium_calls}")
assert rate <= 0.051, f"INVARIANT VIOLATED: escalation rate {rate}"
assert s.premium_calls <= s.n * 0.08, "premium ceiling violated"
print("invariant holds under 3x confidence degradation")
跑一下,然后把规则 2 改掉(让重试的升级重新进入高级路径),观察一旦限流触发,premium_calls 如何冲破上限。这个反例就是这个协议的论证。
P1(有界升级):在任何模拟降级≤基线 10 倍的情况下,持续升级率≤预算 + ε。
P2(无反馈循环):高级调用失败绝不会增加后续的高级调用量。
P3(可解释性):100% 的升级都携带原因码;原因分布在每个窗口期都有日志。
P4(优雅降级):被拒绝的升级仍返回主答案并打上标记,部分样本进入离线高级重放队列。
属性测试在这里优于肉眼观察,因为故障是分布性的——它只在降级情况下跨越数千请求才会显现。
对一个新的便宜模型做影子评估、跑这类故障注入测试工具需要真实 token 和一个运行 worker 的地方。披露:本文是 MonkeyCode 产品推广的一部分。MonkeyCode 的免费模型访问和免费服务器选项恰好适合这个阶段:将测试工具的"主"端点指向免费模型,在免费服务器上跑影子门控和模拟器 worker,等 P1–P4 通过后再接入付费高级端点。如果你打算试这个方案,免费层足够复现本文所有内容,无需动用信用卡。
只有当 P1–P4 在至少 10⁵ 个模拟请求(涵盖正常、3 倍降级、高级限流三种 regime)中全部通过,且在生产采样流量上完成影子运行(便宜模型的验证器一致率在声明容差范围内),才可推广路由策略。分母很重要:按总请求数报告升级率,而不是按可升级请求数。
谁不该用这个:如果你的请求量足够低,高级费用只是噪音,那这个协议就是过度设计——直接调好的模型。如果你的置信度/质量信号完全不可靠,预算门控能约束成本但无法约束质量;先修好验证器。另外,模拟器模拟的是速率,不是内容质量——它证明的是成本不变性,而不是便宜模型实际上够不够好。这需要配对的质量基准测试,那是另一个测试工具。
什么事件序列会打破你的升级不变性——主模型降级、高级限流、还是重新进入升级路径的重试策略——以及打破时,系统应该拒绝请求、离线重放高级、还是打上补偿标记降级?