Fleet Ladder——模型阶梯
Effort: light — 任何派发之前,对目标梯级做一次带缓存的实况探测。消除:把活派给已死的服务商,以及写死在调用点、模型退役当天就断掉的模型名。
永远不手搓服务商调用,也永远不在调用点写死模型名。"此刻这活该哪个模型干?"这个问题归一个解析器管——而它用活的真相回答,不用配置文件的一面之词。
什么时候跑
- 任何派给模型的工作之前:构建、评审、review、有界工人任务。
- 服务商挂了、你需要知道谁回退到谁的时候。
- 你发现自己正往代码或 prompt 模板里敲模型名的那一刻。
步骤
- 声明角色,不声明模型。 每个任务要的是一个角色——
builder、grader或worker。阶梯把角色映射到按序排列的候选模型。builder:实现与修复。grader:独立评审——结构上绝不能是干活的那个模型。worker:有界、规格清晰的任务。便宜的梯级在这里没问题。
- 从配置读阶梯。 一个文件按角色列出候选,按显式回退顺序:最强的在前,一路排到 你的本地保命尾巴(所有云服务商全黑时,你自己硬件还能跑的东西)。改模型、加模型都 改这个文件——绝不改代码。起步模板:ladder.example.yaml ——复制它,换掉占位符。
- 先活探,再信任。 配置里列着只是主张,不是真相。过期条目会列出已死的模型,
也会漏掉活着的模型。派单到某一级之前先探测服务商——调一次 models 端点或发一个
一 token 的请求,例如:
curl -s "$PROVIDER_BASE_URL/v1/models" -H "Authorization: Bearer $API_KEY"(或对 chat 端点发同样形状、带"max_tokens": 1的请求。) 探测结果按合理窗口缓存——别每次调用都重探、把服务商敲一遍。只在真正需要新鲜真相 时刷新缓存。 - 大声往下走。 派给最好的可用梯级。传输失败时,大声报告失败,再试下一级。 绝不无声跳过——记录必须能看出哪些梯级失败了、为什么。
- 耗尽就大声失败。 每一级都挂了,就抛一个写明试过什么的清晰错误。派不出去的 任务绝不无声成功、无限等待、或降级成一个编造的答案。
- 记录来源。 每次派单都追加日志:角色、选中的模型、跳过的梯级及原因。事后你必须 答得出"这活到底是谁干的?"
硬规则——破一条即失败
- 调用点不出现模型名。 代码要的是角色;阶梯回它一个模型。grep 你的代码库找模型名 字面量——每一个都是 bug。
- 活探压过配置。 人说某个模型存在而配置说没有,就去探。探了、它应了,就算定案; 一张过期清单说了不算。
- builder 和 grader 绝不解析到同一个模型(对同一个改动)。阶梯要是把两者塌缩到 一个模型上,grader 就取下一个独立梯级——否则任务大声失败。
- 有界探测。 探测要便宜、有缓存、懂退避。对一个死掉的服务商跑密集重试循环是 被禁止的。
- 不搞无声回退。 每次下探都在日志和报告里可见。悄悄降级正是一条断路无人发现地 死掉的方式。
搭配使用
- model-fusion——评审团和裁判都通过这架阶梯解析模型。
- blind-tribunal——陪审员来自不同家族;阶梯挑出活着的。
- bounded-loops——探测节奏、退避、熔断开关。