Day 57 Hard LLM Infra Reliability Vendor Risk 2026-10-07

LLM 供应链韧性LLM Supply-Chain Resilience: When Your Core Dependency Can Cut You Off, Reprice, or Compete

问题场景 + 需求约束

你负责一款 AI 编码助手:200 万 DAU,每天约 4000 万次模型调用,峰值约 2000 RPS,其中 75% 流量压在一家闭源前沿模型供应商上。传统依赖(数据库、云厂商)的风险是「宕机」;这条依赖的风险多三种:断供、改价、下场竞争。这三种都已经真实发生过:

需求:任一供应商在 72 小时内完全断供,核心功能可用、质量回退可度量且有上限;单任务成本有硬预算,毛利不为负;p95 首 token 延迟(TTFT)< 1.5s 不因切换而失守。

核心洞察:这不是「多加一个 fallback」能解决的可用性问题,而是供应链管理问题。供应商有自己的战略意图,失效模式是相关的、有预警但很短的、带商业动机的——和随机硬件故障完全不同。

高层架构

graph LR
    C["客户端 / Agent"] --> GW["LLM Gateway
统一请求 schema"] GW --> R{"Router
能力档 · 预算 · 健康度"} R --> A1["Adapter: 供应商 A
主力闭源"] R --> A2["Adapter: 供应商 B
热备闭源"] R --> A3["Adapter: 开放权重
托管 / 自建 vLLM"] R -.-> L[("成本账本
per-task budget")] R -.-> H[("健康 / 熔断状态")] S["影子流量采样"] --> EV["评测 Harness
golden set + 回归"] A1 -.-> S EV -->|"能力矩阵"| R CT["合同与容量注册表
通知期 · 配额 · 价格"] --> R

Gateway 把业务请求翻译成内部统一 schema(消息、工具定义、缓存提示),业务代码不直接 import 任何厂商 SDK。Router 按「这个任务需要哪档能力、预算还剩多少、谁现在健康」选模型。Adapter 吸收各家差异(工具调用格式、prompt caching 语义、流式事件)。评测 Harness 持续用影子流量给每个候选模型打分,产出「能力矩阵」喂回 Router——没有这张矩阵,切换就是盲切。合同注册表把商务条款变成路由能读的数据。

关键点 1:模型抽象层与能力契约

一句话 trade-off:抽象越厚,切换越快;但会抹平各家独有的能力(缓存、长上下文、特定工具格式),你为可移植性付性能税。

原理

抽象层的目标不是「所有模型都一样」,而是把差异显式化。每个模型声明一份能力契约:上下文长度、是否支持并行工具调用、结构化输出是否严格、prompt cache 的粒度与 TTL、价格。业务请求也声明它需要什么。路由时做的是约束匹配,而不是字符串替换模型名。最危险的反模式是半抽象:接口统一了,但 prompt 是对着某一家调出来的——切换时接口不报错,质量却悄悄掉。所以 prompt 也要按模型族版本化,和 adapter 一起存放。

选型 Trade-off

方案换来什么牺牲什么
直连厂商 SDK第一时间用上新特性,延迟最低切换成本按代码行数计;断供时要改业务代码
最小公分母接口切换只改配置prompt caching、扩展思考等差异化能力用不上,成本和质量都吃亏
能力契约 + 可选扩展(推荐)默认可移植,需要时显式用独有能力并登记依赖要维护能力矩阵与每家的 prompt 变体,评测成本随模型数线性增长

伪代码

# 能力契约:请求声明需求,路由做约束匹配(pseudo-code)
@dataclass
class Capability:
    max_context: int
    parallel_tools: bool
    strict_json: bool
    cache_ttl_s: int          # 0 = 不支持 prompt caching
    usd_per_mtok_in: float
    usd_per_mtok_out: float

def eligible(req, models):
    out = []
    for m in models:
        cap = m.capability
        if req.tokens_est > cap.max_context: continue
        if req.needs_parallel_tools and not cap.parallel_tools: continue
        if req.needs_strict_json and not cap.strict_json: continue
        if m.quality[req.task_type] < req.min_quality: continue  # 来自评测矩阵
        out.append(m)
    return out

def render_prompt(req, model):
    return PROMPTS[req.task_type][model.family].format(**req.vars)  # prompt 按模型族版本化
现实案例:Windsurf 2025-06 被切断 Claude 3.x 一手容量时,只有不到五天去找其他推理供应商。这说明抽象层的价值在断供前就要付清——临时去写 adapter 来不及。行业上,OpenRouter 的 provider routing 把同一模型的多家托管方、多模型 fallback 做成请求参数(models 优先级列表、allow_fallbacks、按价格/吞吐/延迟排序),是「抽象层即服务」的样本;代价是再引入一层第三方依赖。

关键点 2:多供应商路由——热备,而不是冷备

一句话 trade-off:多家同时承载真实流量(active-active)贵且质量不一致;只在出事时切过去(active-passive)便宜,但备用路径会悄悄腐烂。

原理

Day 23 讲过熔断、重试与舱壁;这里的新问题是备用路径的保鲜。一条从不走流量的 fallback,它的 prompt、配额、账号、限流参数都会过期——断供那天你才发现备用账号的 rate limit 只有主力的 1/20。所以要让备用供应商常年承载 5–15% 的真实流量,并保有书面确认的容量。第二个问题是相关故障:断供往往不是 5xx,而是 403、配额骤降、或某模型版本下线,健康检查必须把这些也当成故障信号。第三,降级要按能力档进行:主力不可用时,补全类任务可降到开放权重小模型,复杂 agent 任务宁可排队也不能降到会胡改代码的模型。

选型 Trade-off

方案换来什么牺牲什么
单供应商 + 冷备最省事,单一 prompt 调优备用路径未经验证;容量无保证;切换当天质量未知
主力 + 热备(10% 常驻)备用路径持续被真实流量验证,容量与配额已证实两套 prompt 与评测;用户体验有轻微不一致
按任务类型分供应商每类任务用性价比最优模型,天然分散任一家断供都会打掉一类功能;路由策略最复杂

伪代码

# 带熔断与能力档降级的路由(pseudo-code)
FATAL = {401, 403, 404}          # 鉴权失败 / 模型下线:不是抖动,是断供信号

def route(req):
    for m in rank(eligible(req, MODELS), by=req.objective):   # 成本 or 延迟
        if breaker[m].open(): continue
        try:
            resp = m.adapter.call(req, timeout=req.ttft_budget)
            breaker[m].success()
            ledger.charge(req.task_id, m.cost(resp.usage))
            return resp
        except ProviderError as e:
            if e.status in FATAL:
                breaker[m].trip(hold_s=3600); alert("supplier-level", m, e)
            else:
                breaker[m].failure()
    if req.tier == "agent":
        return enqueue(req)        # 宁可排队,不降到能力不够的模型
    return degrade(req)            # 补全类:降到开放权重小模型
现实案例:OpenAI 2026-08 宣布停止向 SpaceX 旗下的 Cursor 供货,访问在 11 月中旬关闭;Cursor 的说法是 OpenAI 模型只占约 5% 流量——分散的流量结构把一次断供变成了一次可控迁移;Anthropic 方面则公开表示会继续给 Cursor 加算力。对比 2025 年的 Windsurf,差别不在技术,而在断供前流量已经分散到什么程度。

关键点 3:开放权重兜底 + 按每任务成本做预算

一句话 trade-off:开放权重给你主权和成本下限,但要自己承担后训练、推理运维和能力差距;按 token 标价做预算会系统性低估推理模型的真实成本。

原理

MIT FutureTech 的 Gundlach 等人(2025)估算:达到固定基准水平的价格每年下降约 5–10 倍,但跑前沿模型本身的价格每年上升约 3–18 倍——模型更大、推理 token 更多。也就是说,单价表在变便宜,你实际的账单却可能变贵:同一任务,推理模型可能多吐一个数量级的 token。预算单位因此必须从「每百万 token 多少钱」换成「每个完成任务多少钱」,并按任务实时扣账、超预算即降档或中止。开放权重是这套账本的地板:它的价格不会被单方面上调,也不会在你被收购时被收回。

选型 Trade-off

方案换来什么牺牲什么
只用闭源前沿能力最强、零运维价格与供货由对方决定;毛利被上游锁死
托管开放权重(第三方推理商)无 GPU 运维,换供应商只换 endpoint仍有托管方依赖,但可在多家托管方之间迁移
自建开放权重 + 自有后训练成本与路线自主;可针对自家任务做 RLGPU 容量规划、推理优化、训练团队;能力差距要靠后训练补

伪代码

# 每任务预算账本:按完成任务计费,而不是按 token(pseudo-code)
class TaskBudget:
    def __init__(self, task_id, usd_cap, tier_ladder):
        self.spent, self.cap, self.ladder = 0.0, usd_cap, tier_ladder

    def before_step(self, est_tokens, model):
        projected = self.spent + model.cost_estimate(est_tokens)
        if projected <= self.cap:
            return model
        cheaper = self.ladder.next_below(model)       # 降一档:前沿 → 主力 → 开放权重
        if cheaper and self.spent + cheaper.cost_estimate(est_tokens) <= self.cap:
            return cheaper
        raise BudgetExceeded(self.task_id, self.spent)  # 交给产品层:提示用户或转人工

    def after_step(self, usage, model):
        self.spent += model.cost(usage)   # 推理 token 也计入:这是被单价表藏起来的部分
        metrics.histogram("usd_per_task", self.spent, tags={"model": model.name})
现实案例:Cursor 2026-03 承认 Composer 2 以 Moonshot 的开放权重 Kimi K2.5 为底座、再做大量 RL 后训练,经 Fireworks AI 的商业授权使用。据 TechCrunch 2026-04 报道,自研 Composer 加上调用 Kimi 等更便宜的模型,帮助其企业业务扭到略为正的毛利(个人开发者账户仍亏损)。GitHub Copilot 改按 token 用量计费,则是另一端:转售方把成本风险转回给用户。

关键点 4:合同、容量条款与切换前的评测门

一句话 trade-off:长约与预留容量换来价格和供货确定性,但锁定更深;短约灵活,但断供时没有任何书面保障。

原理

技术冗余只能缩短断供后的恢复时间,合同条款决定你有多少预警时间。要谈的关键条款:终止通知期(Windsurf 只有不到五天)、控制权变更条款(你被收购时对方能否单方终止——Cursor 案中 OpenAI 的理由正是对新母公司守约的不信任)、模型下线通知期、预留容量与限流配额、价格锁定期、数据使用限制。另一面是评测门:切到新模型前,用 golden set 加影子流量比较任务通过率,回退必须可度量且有上限,否则切换就是把质量事故推给用户。

sequenceDiagram
    participant V as 供应商 A
    participant Ops as 平台 on-call
    participant R as Router
    participant E as 评测 Harness
    V->>Ops: 终止通知 / 403 激增
    Ops->>R: 冻结 A 的新流量份额
    Ops->>E: 对候选 B、开放权重跑 golden set
    E-->>Ops: 能力矩阵(各任务通过率差值)
    Ops->>R: 按任务类型分批切流 10%→50%→100%
    R->>E: 持续影子比对 + 用户侧指标
    E-->>Ops: 回退超阈值则该类任务排队 / 降级

伪代码

# 切换门:每类任务的质量回退必须在上限内(pseudo-code)
def promote(candidate, incumbent, task_types, max_drop=0.03):
    plan = {}
    for t in task_types:
        base = eval_pass_rate(incumbent, GOLDEN[t]) if incumbent.alive else BASELINE[t]
        cand = eval_pass_rate(candidate, GOLDEN[t])
        shadow = shadow_agreement(candidate, t, sample=0.02)   # 线上影子比对
        if base - cand <= max_drop and shadow >= 0.9:
            plan[t] = "ramp"          # 10% → 50% → 100%
        else:
            plan[t] = "hold"          # 继续用热备 / 排队 / 显式告诉用户能力受限
    return plan
现实案例:Anthropic 2026-04-04 起不再让订阅额度覆盖 OpenClaw 等第三方 harness(提供一次性额度补偿),之后计划的更大范围计费调整又在 2026-06-15 生效当天被暂停。对下游来说,教训不是哪条规则对,而是非合同保障的使用权随时可能变:把业务建在消费者订阅额度上的工具,没有任何通知期可言。

扩展与优化

常见陷阱 + 面试问题

深入资源

深入思考

热备承载 10% 流量要多花多少钱?用一个数量级估算论证它值不值。

设月模型成本 100 万美元,热备单价比主力高 20%,10% 流量即多付约 2 万美元/月,外加一套 prompt 与评测的人力(约 0.5 人)。对比:若断供导致核心功能停摆 3 天,按月收入 300 万美元计,直接损失约 30 万美元,还没算流失。只要年断供概率高于约 10%,热备就划算——而过去 18 个月公开的断供与规则突变已有好几起。关键是把它算成保险费,而不是冗余浪费。

多供应商路由会不会让用户体验「人格分裂」?怎样让质量差异不被用户感知为 bug?

会。同一会话中途换模型,风格、工具调用习惯、甚至对代码库的理解都会断层。设计原则:会话粘性(会话内不换模型,除非熔断),按任务类型而非随机分流(让差异落在可解释的边界上),对显著降级显式告知。这与 Day 6 一致性里的「会话保证」同构:read-your-writes 保证的是用户看到自己的写,这里保证的是用户在一个会话里面对的是同一个「推理者」。

假如你就是模型供应商:从供应方视角,什么样的下游客户最可能被断供?这对下游设计有什么启示?

反推供应方动机:被竞争对手收购或即将被收购(Windsurf、Cursor 两例)、产品与供应商自营应用正面竞争、使用模式让单位成本失控(订阅额度被 agent 高频消耗)。启示是把战略风险也纳入依赖评估:融资与并购谈判期间提前加厚热备,与供应商自营产品重合度越高越要降低单一依赖,并避免把核心路径建在未入合同的使用权上。

开放权重模型的版本更新也可能破坏你的产品。开放权重真的消除了供应链风险吗?

它把风险从「被收回」变成「被停更」。权重已在你手里,旧版本永远能跑,所以不会被断供;但上游可能不再发布新版、许可证可能对新版本收紧,地缘政治也可能让某国模型在部分客户处不可用(企业采购审查)。所以开放权重兜底也要多源:至少两个不同来源的底座都在评测矩阵里,自有后训练流程能在两者之间迁移。风险没有消失,只是变成了慢变量,你有时间应对。

把本期与 Day 55「对象存储当真相源」对照:两者都把正确性押在一家厂商的语义上,差别在哪?

Day 55 押的是 S3 条件写这样有文档、有 SLA、长期稳定的原语,且多家对象存储已兼容同一语义,替换路径清晰。LLM 依赖押的是能力而非接口:接口可以统一,但「这个模型能把这类任务做对」没有规范可兼容,只能靠评测证明。所以前者的冗余是协议层的,后者必须是评测层的——评测矩阵才是 LLM 时代的「兼容性规范」。