AI 基建
0%
第十二部分 · 实践与运营 · 第 90 章

非确定系统的可靠性

作者Changkun Ou
阅读时长约 16 分钟

可靠的模型服务不是每次都返回相同的响应字节,而是始终兑现对面向用户的结果所作的明确承诺。这份可靠性契约可能要求系统及时响应、给出正确答案、只执行获准动作、使用时效符合要求的证据,或者让某项副作用发生的次数不超过预期。其中一些属性是确定性不变量,另一些则需要统计证据。生产可靠性两者都要。

非确定性改变了观察语义结果的方式,却没有取代站点可靠性工程的基础。传统服务同样会出现延迟波动、局部故障、数据过期和结果错误。HTTP 200 从来不能证明结果有用。模型系统新增的是一个庞大的结果空间,在这个空间里,字节相等尤其不适合作为质量代理。因此,运维上的答案不是另造一种“可靠性”,而是写出一份与用户承诺相匹配的可靠性契约,明确事件、判定条件、证据和恢复路径。

本章将构建这份契约。它会分开服务目标与测量实现,说明如何通过概率抽样估计语义质量,明确常见的 pnp^n 任务模型何时成立,并限定生成过程周围的重试、回退、降级和重放控制。

从结果契约出发

SRE 的事件模型是一个实用起点。服务水平指标(SLI),也就是对某项服务属性的量化指标,通常实现为合格事件中良好事件所占的比例。服务等级目标(SLO) 则为该指标设定某个时间窗口内的目标。关键在于,SRE 会区分 SLI 规格SLI 实现:前者说明应该测量什么,后者说明如何用现有遥测数据估计它 (Thurgood and Ferguson 2018)。当生产结果需要人或模型来判断时,这一区分尤其重要。

不要把整个服务压缩成一个含糊的“质量”数字。不同维度必须分别定义,否则健康的汇总指标可能掩盖已经失守的安全边界或影响边界。

维度 合格事件 良好事件判定条件 常见证据
可用性 已接受的请求 返回了合格响应 网关与应用日志
延迟 已接受的请求 合格结果在截止时间前到达 端到端计时
语义质量 属于指定任务和流量切片的请求 结果通过带版本的评分量规 概率样本及其裁定标签
策略 请求或拟执行动作 适用策略与授权检查通过 确定性策略决策与审计日志
时效性 依赖变化事实的回答 证据时效仍在声明范围内 来源与检索时间戳
影响正确性 请求的外部动作 预期影响按允许次数发生 工具回执与协调记录
测量覆盖率 合格事件 所需证据在标签截止时间前到达 遥测与标注流水线

契约必须写明合格事件、排除规则、总体与流量切片、观测窗口、系统发布版本、测量实现、缺失数据规则、目标和恢复动作。“良好答案超过 95%”还不是一份契约,因为它没有说明统计谁的答案、对应哪个发布版本、如何裁定,也没有说明裁判不可用时怎么办。

contract promise 用户承诺 event 事件与判定条件 promise->event evidence 证据 检查与抽样 event->evidence decision SLO 决策 evidence->decision action 运维与恢复 decision->action
图 90.1. 一项可靠性主张可以从用户承诺追溯到事件与判定条件,再追溯到证据和运维响应。确定性检查与抽样判断在决策环节汇合,而不是互相替代。

这种结构还能避免一个常见的分类错误。可达性、延迟、语义质量、策略合规、时效性和影响正确性彼此相关,却不能互换。针对某项具体产品承诺,可以使用复合验收条件,但每个组成部分仍然需要自己的 SLI 和切片视图。否则,大量快速、简单的请求就可能掩盖少见但严重的策略故障。

衡量语义结果,但不要把样本当成流量

假设每个合格生产事件 ii 都有一个语义结果标签 Yi{0,1}Y_i \in \{0,1\},其中 11 表示该事件通过一份冻结的评分量规。如果概率样本 SS 以已知纳入概率 πi>0\pi_i > 0 包含事件 ii,可以采用下面的加权比率估计量:

p^=iSYi/πiiS1/πi.\widehat{p} = \frac{\sum_{i \in S} Y_i / \pi_i} {\sum_{i \in S} 1 / \pi_i}.

这是一个 Hájek 式加权比率。每个已观测标签都通过逆纳入权重 1/πi1/\pi_i 代表相应的合格事件 (Horvitz and Thompson 1952)。所有事件纳入概率相同时,它会退化为普通的样本通过率。这个比率并不会神奇地在所有有限抽样设计中都无偏,但它比把过度抽样的故障与日常流量不加权地混在一起,更能描述目标总体。

抽样策略决定了可以提出什么主张。

  • 代表性概率样本可以估计明确指定的总体,因为每个合格事件都有已知且非零的入样机会。
  • 诊断样本会有意增加事件、罕见切片或低置信结果的比例。它非常适合发现缺陷,但原始通过率不是生产通过率。应把它与代表性样本流结合,或者在估计量中使用已记录的纳入概率。
  • 只由“碰巧拿到标签”的事件组成的便利样本,除非能论证其选择机制,否则既不能支持总体估计,也不能支持诊断样本的主张。

仅有抽样还不够。测量记录必须绑定流量定义、抽样策略、πi\pi_i、评分量规版本、裁判版本、系统发布版本和标签时间戳。裁判需要定期接受人工审计,以估计重要切片上的假阳性和假阴性。出现评测器漂移时,应重新校准或更换裁判。绝不能用发生实质变化的裁判给两个时间窗口打分,却悄悄把结果直接比较。第 52 章 的评测实践和 第 48 章 的统计区间提供了离线方法;生产环境还要处理选择偏差、延迟和缺失数据。

缺失标签应视为未知,而不是通过。质量指标旁边必须同时报告测量覆盖率。下面的 CC 表示截至标签截止时间,已到期的抽样事件中有多少已经获得标签:

C=按时已标注样本已到期样本.C = \frac{\text{按时已标注样本}} {\text{已到期样本}}.

分子只统计按时到达的标签,分母则包含所有标签已经到期的抽样事件。

如果用户反馈或下游影响很晚才出现,就要定义标签延迟,并按事件何时成为合格事件来划分群组,而不能只按标签出现时间划分。分析时仍未得到结果的事件属于删失数据,应报告数量,并采用适合延迟结果的方法,不能悄悄丢弃。覆盖率低于下限时,质量状态就是未知。裁判或日志链路故障属于遥测故障,不能证明服务有所改善。

把估计转化为运维策略

SLO 是目标,不是置信区间。SLO 文档应写明指标、目标、总体、切片、窗口和错误预算策略。不确定性方法则用来判断现有证据是否足以支持决策。例如,团队可以设定 30 天语义成功目标,只在考虑不确定性的估计和最低样本要求都表明错误预算正在快速消耗时告警。

抽样标签是关于合格服务事件的证据,不是错误预算的计量单位。如果把一个有意过度抽样的事件直接当作一个用户事件,分子和预算都会失真。应使用加权总体估计,保留抽样设计信息,并同时展示有效样本量和测量覆盖率。

对于高流量服务,可以使用比较多个燃尽率的多窗口告警,把能快速捕捉严重预算消耗的信号,与抗噪声的慢速信号结合起来 (Thurgood 2018)。低流量服务需要更长的窗口、合成或批量检查,以及明确的最低证据状态。只有两个标签的比率不能像精确测量一样触发告警。安全、授权和影响完整性等硬边界无论总体错误预算如何,都需要直接告警。最后,SLO 决策不会自动成为发布闸门。第 89 章 的部署策略可能要求更强的证据、相对对照组的非劣效结论,以及完整的保护条件,才允许扩大暴露范围。

下层约束:模型任务可靠性

多步骤智能体只有在一系列必要条件都成立时才能成功。对于步骤成功事件 S1,,SnS_1,\ldots,S_n,概率链式法则给出

P(S1,,Sn)=k=1nqk,qk=P(SkHk1),Hk1=(S1,,Sk1).\begin{aligned} P(S_1,\ldots,S_n) &= \prod_{k=1}^{n} q_k, \\ q_k &= P(S_k \mid H_{k-1}), \\ H_{k-1} &= (S_1,\ldots,S_{k-1}). \end{aligned}

每个因子都表示在前序步骤成功的条件下,第 kk 步成功的概率。常见的 pnp^n 曲线只是一个特例,其中 pp 表示每一步都相同的成功概率。这个简化式假设任务步数固定、各步结果相互独立、每一步失败都会导致任务失败,并且系统没有恢复路径。真实智能体经常同时违反这四项假设:后续步骤依赖前文,任务长度会变化,困难任务中的故障彼此相关,校验器也可能触发修复。需要真实主张时,应使用链式法则或实测端到端完成率;pnp^n 只适合解释理想化的复合机制。

图 90.2. 固定长度、每一步失败都会终止任务的理想化独立同分布模型。当 p = 0.99 时,五十个必要步骤全部成功的概率约为 0.605。这条曲线用于解释机制,不能替代对未测量智能体的估计。
import math

def iid_task_success(step_success: float, required_steps: int) -> float:
    assert 0.0 <= step_success <= 1.0
    assert required_steps >= 0
    return step_success ** required_steps

def attempts_success(single_attempt: float, attempts: int) -> float:
    """Independent attempts at one recoverable operation."""
    assert 0.0 <= single_attempt <= 1.0
    assert attempts >= 1
    return 1.0 - (1.0 - single_attempt) ** attempts

p = 0.99
for n in (1, 10, 50, 100):
    print(f"p={p:.2f}, n={n:3d}: {iid_task_success(p, n):.4f}")

assert math.isclose(iid_task_success(0.99, 50), 0.6050060671,
                    rel_tol=1e-9)
assert attempts_success(0.8, 2) == 0.96

减少不必要的步骤、提高每一步的条件成功率,都能改善任务可靠性。检查点的作用不同:它本身不会提高下一步成功的概率,而是减少失败后丢失的工作量和重启成本。只有同时保留有效状态、提供可用的重试或修复路径,并留有足够的截止时间与尝试预算时,检查点才会提高完成概率。应测量包含恢复耗尽在内的完整策略,不能拿两个检查点之间的最短距离代替 nn

按故障类别重试,而不是碰运气

重试本身也是一项消耗容量的请求。只有故障类别、副作用语义和剩余预算都表明再次尝试可能有用时,重试才合理。应先分类,再决定是否重试。

观测到的情况 默认处理 原因
瞬时传输故障 截止时间允许时做有界重试 换一条路径或一个实例可能成功
明确的限流响应 遵守服务端指引,执行退避和抖动 立即重试会放大过载
语义故障 修复上下文、更换方法或拒绝作答 盲目重采样可能重复系统性缺陷
策略故障 不得通过重试绕过策略 换一个样本不能绕过拒绝决定
写操作提交状态未知 执行协调,或使用该操作的幂等契约 超时不能证明影响没有发生
无效请求或永久性依赖错误 失败退出,或路由到兼容替代方案 等待不会修复请求本身

整条调用路径只传播一个端到端截止时间。每条路径指定一个重试负责人,防止 SDK、网关、模型和智能体内部的重试循环相乘。重试负责人应拥有重试预算、指数退避、抖动和最大尝试次数。依赖过载时正是容量最紧张的时候,重试还会继续消耗容量,因此限制重试属于可用性控制,而不只是成本控制 (Brooker 2019)。

幂等键只在声明的契约范围内有效。调用方和服务必须就键的作用域、保留期限、请求负载的身份判定、并发重复请求的处理方式、存储持久性和响应重放达成一致。键记录与预期写操作必须以合适的原子性共同提交 (Featonby 2021)。即使如此,幂等也不等于恰好执行一次:受保护事务之外的影响、已经过期的键,或者没有继续传递该身份的下游系统,仍可能重复执行。HTTP 对幂等的定义同样关注重复请求的预期影响,并不承诺响应完全相同,也不承诺所有请求都可以自动安全重试 (Fielding et al. 2022)。

把回退视为经过验证的契约变更

回退路径与主路径不同,并不代表它安全。它必须满足回退兼容性:替代路径接受同样的相关输入,保留授权与租户边界,产生调用方能够解释的结果,并遵守延迟、时效性、策略和影响限制。缓存答案可能过期,模板可能遗漏必要上下文,拒绝作答也可能没有成功交接给人工。每条终止路径都可能失败,因此设计目标是提供更窄但合格的结果和明确的失败模式,而不是假定最后一环永不失效。

fallback primary 主路径尝试 check 验证契约 通过则交付 primary->check alternate 兼容回退 随后再次验证 check->alternate 失败 narrow 按更窄契约 降级或拒绝作答 alternate->narrow 预算耗尽 handoff 交付或交接 观测结果 narrow->handoff
图 90.3. 有界回退策略会验证每一个结果,并可主动缩小承诺范围。任何分支都不被假定为永不失效,交付和交接本身仍是需要观测的结果。

优雅降级会有意缩小服务承诺,例如减少工具、使用较旧但仍在时效范围内的数据、提供部分答案,或者改为只读操作。降级模式必须预先验证,在用户界面和遥测数据中清晰可见。如果降级会改变权限或掩盖不安全的不确定性,就必须禁止降级。产品若承诺提供当前事实,检索中断后“只根据提示词回答”就不是优雅降级。系统已经注定无法按时完成时,负载削减可能比继续接单更安全,但过载路径必须提前测试 (Forero Cuervo 2017)。

拒绝作答是产品结果,不是评测时才考虑的附属情况。选择性系统在已回答请求的风险与覆盖率之间做取舍 (El-Yaniv and Wiener 2010)。它的风险与覆盖率契约至少应该报告:

  • 已接受答案中的错误率或伤害率;
  • 覆盖率,也就是按照完整契约回答的合格请求比例;
  • 拒绝作答率与交接率、对应延迟,以及最终解决结果;
  • 所有指标在重要流量切片上的结果。

增加拒绝作答可以让已接受答案看起来更好,却也可能放弃更多用户。取舍两端必须一起报告。

冗余只有跨越相关故障域才有效

仅仅发起两次调用,并不会让两个结果彼此独立。它们可能共享提供商、共享模型、共享提示词、共享检索索引、共享工具和共享裁判。相关设计缺陷一直是多版本冗余的根本限制 (Knight and Leveson 1986)。第二次采样只有提供条件多样性时才会改善可靠性:在给定请求和已知状态后,它仍要有足够高的概率避开第一条路径的故障。

应为每条回退路径或每个集成成员维护故障域矩阵,记录模型家族、提供商与区域、提示词谱系、检索来源、工具依赖、校验器或裁判、凭据和服务基础设施。随后主动注入共享故障。只体现在模型名称上的多样性,无法抵御被污染的索引、过期凭据、失效的评分量规或共同的区域依赖。共同模式故障必须通过实测识别,而不能凭组件数量推断。

约束依赖与过载

模型服务、工具、检索系统、策略引擎和裁判都是分布式依赖。它们都可能发生波动、延迟、局部提交或彻底失败。每次调用都应使用从端到端截止时间推导的超时,通过舱壁隔离容量,用负载削减拒绝过量工作,并在快速失败比继续增加负载更安全时使用熔断器 (Nygard 2018)。

生产熔断器不能只有三个状态名称。还要定义测量故障的窗口、最小样本量、哪些错误计入故障、触发阈值、打开时长、探测并发数、熔断器作用域和恢复条件。一次成功探测或许只能证明依赖可达,不能证明容量或语义结果已经恢复。只有声明的恢复条件满足后才能闭合熔断器,同时还要保留足够的探测流量,以识别仍未恢复的依赖。

breaker closed 闭合 测量窗口 open 打开 快速失败 closed->open 最小样本与阈值 probe 探测 限制调用 open->probe 打开时段结束 probe->closed 满足恢复条件 probe->open 尚未恢复
图 90.4. 熔断器限制对故障依赖的调用。它的转换策略包括测量窗口与最小样本、有界的打开时段、受限探测,以及明确的恢复条件。

延迟对冲与质量冗余必须分开。延迟对冲会在短暂等待后发出一个等价的只读或幂等请求,并采用第一个合格结果。条件允许时应取消落败请求,并为对冲设置容量预算,因为它会造成负载放大 (Dean and Barroso 2013)。质量冗余则获取多个结果,再应用校验、比较或聚合规则。最快返回的结果未必最好,因此“先到先得”不是语义质量策略。绝不能对未受保护的副作用做对冲。

构建可复现性,但不要把它等同于可靠性

确定性重放对调试、回归测试、缓存和取证很有价值。应把它视为覆盖完整系统的精确重放契约:模型修订版本与权重、请求与提示词、采样配置与种子、检索快照、工具响应、策略配置、服务运行时、内核实现、硬件和组批条件都必须固定。只固定温度和种子,却允许提示词、索引、工具或提供商运行时变化,不构成精确重放契约。

即使采用贪心解码,只要数值内核依赖动态组批,结果仍可能变化 (He 2025)。服务运行时可以在受支持的环境中提供批不变内核 (vLLM 2026),但具体机制和成本属于实现细节,需要针对已固定的发布版本进行基准测试。精确重放无法证明正确性、安全性或可用性,它只能证明相同的记录条件会重现相同的计算。

这不是在确定性与验证之间二选一。健壮的系统会在 Schema、授权、配额、影响身份和来源证明等边界上使用确定性不变量,为语义结果收集统计证据,也可能保留可重放的事件夹具。三种机制各自回答不同的问题。第 31 章 中的服务机制决定了精确重放需要记录哪些输入,以及必须保存哪些容量控制信息。

把质量故障作为事件处置

当面向用户的结果、重要流量切片或测量系统违反契约时,就发生了质量事件。如果测量覆盖率崩溃,应立即把语义状态标记为未知,不能等待一个虚假安心的通过率。运行手册应包含以下步骤:

  1. 确认范围。 检查发布指纹、流量分配、切片、裁判版本、标签延迟和遥测故障模式。
  2. 遏制伤害。 冻结提升,禁用相关工具或路由,降低权限,切换到合格回退路径,削减负载,或者回滚完整发布包。
  3. 保留证据。 在隐私限制内保留请求与发布标识、策略决策、检索来源证明、工具回执、原始结果、裁判记录和人工干预记录。
  4. 修复并验证恢复。 重现故障,离线测试拟议修复,以有限流量恢复服务,并同时依据语义保护条件和确定性保护条件验证恢复,然后再扩大流量。
  5. 吸取经验。 把故障加入语料库,更新故障域矩阵,并判断是否是 SLI、策略或回退契约遗漏了它。

还要用场景测试演练运行手册:裁判中断与评测器漂移、提供商退化、检索结果过期、限流风暴、提交状态未知后的超时、重复交付影响、幂等状态过期、相关回退故障、标签缺失,以及熔断器探测时发生过载。测试必须断言用户可见结果和恢复动作,不能只检查内部组件是否改变状态。

可靠性发布记录

只有证据随发布一起流转,可靠性才能真正进入运维。可靠性发布记录是本章的产物,其中应包含:

  • 发布指纹和负责人;
  • 每项 SLI 规格与 SLI 实现、合格总体、切片、窗口、目标、排除规则和缺失数据规则;
  • 抽样策略、纳入概率、裁判与评分量规版本、人工审计结果、不确定性方法和测量覆盖率;
  • 重试负责人和预算、截止时间传播、幂等契约、回退兼容性、降级模式和拒绝作答策略;
  • 依赖与故障域矩阵、熔断器配置、容量限制和共同模式分析;
  • 场景测试结果、告警与燃尽率策略、事件运行手册、回滚目标和恢复证据。

这份记录把 第 89 章 的部署包与运维承诺连接起来,也让分歧可以审查。团队可以合理地选择不同的评分量规、抽样率、拒绝作答策略或恢复阈值,但不应该因为裁判、流量总体或故障假设从未写明,而在不知情的情况下得出不同结论。

争议所在
  • 开放式质量能否使用 SLO? 只有当产品能够定义可重复的结果判定条件,并验证测量方法时才可以。对于探索性工作,一组切片指标和用户伤害保护条件,可能比单一通过率更诚实。
  • 重采样何时算作修复? 它可以降低独立抽样错误,却也可能掩盖系统性的提示词、知识、策略或裁判缺陷。答案取决于实测的条件故障,以及延迟成本。
  • 多少多样性才足够? 不同提供商或模型家族可以减少某些共同模式故障,却可能继续共享数据、提示词、检索或评测器故障。多样性是故障域中的实测属性,不是架构图上的标签。

因此,非确定系统的可靠性既不是字节相等,也不是盲信大样本。它是一份可追溯的契约:定义结果,观察正确的总体,量化不确定性与缺失数据,约束恢复,并在影响边界周围保留确定性边界。这样,系统就能测量并管理变化,而不是拿变化为无法证伪的承诺开脱。

延伸阅读

  • Beyer, Betsy; Jones, Chris; Petoff, Jennifer; Murphy, Niall Richard. Site Reliability Engineering: How Google Runs Production Systems (SLI、SLO、错误预算). O'Reilly Media, 2016. sre.google
    Google SRE 一书提供了本章改造到 AI 系统上的运营词汇:服务承诺、错误预算、事故指挥以及从失败中学习。
  • Dean & Barroso, “The Tail at Scale” (尾延迟、对冲请求), 2013. research.google
    Dean 与 Barroso 解释了尾延迟为何主导大型分布式服务,并介绍了包括对冲请求在内的尾延迟容忍技术。
  • Nygard, Michael T.. Release It! Design and Deploy Production-Ready Software (超时、熔断器、舱壁、稳定性模式). Pragmatic Bookshelf, 2018.
    Nygard 总结了生产软件的稳定性模式,包括断路器、隔板与超时。
  • He, “Defeating Nondeterminism in LLM Inference” (依赖批次的数值内核与精确推理重放), 2025. thinkingmachines.ai
    He 将温度为零时的推理差异追溯到结果依赖动态组批的数值内核,并提出批不变的替代方案。
  • vLLM, “Batch Invariance” (用于可复现服务的批不变内核), 2026. docs.vllm.ai
    vLLM 记录了一种服务模式,其受支持内核能在固定环境中使输出不受组批方式影响。

评论

登录后评论