logo

AI 系统的 SLO:质量、延迟、可用性与安全

Published on

AI 系统的 SLO:质量、延迟、可用性与安全

传统 Web 服务的 SLO 往往很直观:99.9% 的请求成功,P95 延迟小于 300 毫秒。AI 系统如果也只看这两个数字,会得到一个非常荒谬的结论:模型返回了 HTTP 200,接口很快,所以服务很好。

但用户拿到的是一个没有依据的答案,或者答案虽然正确却等了 20 秒;一次越权检索把别人的文档送进了上下文,接口仍然可以返回 200。对于 AI 系统来说,“服务正常”不能只代表机器还活着,还要代表结果足够有用、足够及时、没有越过安全边界。

我以前把可观测性理解成监控 CPU、内存和错误日志,后来发现 AI 产品最难排查的故障往往不是进程挂了,而是质量悄悄下降:索引版本错了,Prompt 变长了,某个模型更新后更爱拒答,或者回答开始引用过期内容。SLO 的价值,就是把这些模糊的“感觉变差了”变成团队可以共同讨论、共同负责的目标。

一、先分清 SLI、SLO 和 SLA

  • SLI:实际测量的指标,例如有效回答率、P95 首 Token 延迟。
  • SLO:内部希望达到的目标,例如有效回答率不低于 95%。
  • SLA:对客户或合同承诺的服务等级,通常伴随赔偿或其他责任。

不要一上来就承诺“所有回答 99% 正确”。先定义可以测量、可以复现的指标,再根据业务风险决定目标。客服 FAQ、代码补全、医疗问答和自动发邮件,允许的错误程度完全不同。

二、AI 系统至少需要四类 SLO

1. 质量 SLO

质量不是一个数字。RAG 应用可以分别设置:

召回命中率 Recall@K ≥ 0.90
有依据回答比例 ≥ 0.95
无答案时正确拒答率 ≥ 0.92
结构化输出校验通过率 ≥ 0.99
用户负反馈率 ≤ 0.08

“有依据回答比例”需要通过引用校验、人工抽检或经过校准的自动评审得到。自动评审可以扩大覆盖,但不能把评审模型的输出当成绝对真理。高风险场景仍然需要人工样本和明确的不可接受错误。

2. 延迟 SLO

聊天应用不应只记录完整响应时间,还要拆分:

P95 首 Token 延迟 ≤ 800ms
P95 完整回答延迟 ≤ 5s
P95 检索延迟 ≤ 300ms
P95 工具调用等待 ≤ 2s

流式输出时,首 Token 早到并不代表整段体验好;工具调用多的 Agent 可能首句很快,最终结果却迟迟不来。不同产品还要区分交互式请求和后台长任务,不能用同一套延迟目标互相污染。

3. 可用性 SLO

可用性不只是 API 成功率,还包括“请求成功但任务没有完成”。例如模型返回格式错误、工具调用失败后被吞掉、RAG 检索为空却被当成正常答案,这些都应该被统计为有效性失败,而不是健康请求。

type AvailabilityResult = {
  transportOk: boolean
  modelResponded: boolean
  schemaValid: boolean
  taskCompleted: boolean
  safeToReturn: boolean
}

只有满足业务定义的成功条件,才能计入有效可用请求。否则系统可以通过“快速返回一个错误格式的答案”把可用性数字做得很好看。

4. 安全 SLO

安全目标通常是上限型指标:

  • 越权检索事件为 0;
  • 高风险工具未经确认执行次数为 0;
  • 敏感信息进入不允许供应商的事件为 0;
  • 已删除文档再次被召回的事件为 0;
  • 安全策略违规输出低于规定阈值。

安全不能简单用平均值冲淡。一次跨租户泄漏不能被 100 万次正常请求“平均掉”。对不可接受事件,要设置硬门槛、立即告警和明确的暂停发布规则。

三、质量指标要有采样和标签

线上不可能人工阅读每个答案,但可以建立分层采样:按租户、模型版本、功能、语言、风险级别和用户反馈抽取样本。每个样本关联完整 Trace:

type QualitySample = {
  traceId: string
  modelVersion: string
  retrievalVersion: string
  promptVersion: string
  riskLevel: 'low' | 'medium' | 'high'
  grounded: boolean
  relevant: boolean
  safe: boolean
  reviewedBy?: 'human' | 'judge-model'
}

质量 SLO 最好同时看总体和关键切片。总体有 96% 的有效回答,但某个重要租户只有 82%,或者高风险问题的拒答准确率明显下降,仍然应该触发调查。

还要避免数据泄漏。评测集中的问题不能原样混入训练或 Prompt 优化数据,否则指标会越来越漂亮,真实能力却没有提升。每次质量下降都要保留失败样本,形成回归集,而不是只在仪表盘上画一条下降曲线。

四、错误预算让团队敢于做改进

如果质量 SLO 是“有效回答率 95%”,那么允许的 5% 就是错误预算。预算不是鼓励犯错,而是承认任何复杂系统都不可能零风险,并把风险控制在可接受范围内。

目标窗口:10,000 次有效请求
SLO:95%
错误预算:500 次不可接受或无效结果

当预算充足时,可以尝试新模型、改 Prompt 或调整切分策略;当预算快速消耗时,暂停高风险实验,优先修复质量回归和基础设施问题。

不同指标的预算不能随便相加。延迟超标、质量下降和安全事件是不同维度,安全预算通常不是“可以慢慢用完”的预算。团队要事先写清楚哪些指标可以权衡,哪些指标一旦越线就必须停止。

五、降级要提前设计,不要故障时临时发挥

当主模型、Reranker、向量库或工具不可用时,系统需要知道怎么退:

主模型不可用
切换备用模型
减少上下文与关闭非关键工具
返回经过验证的检索结果
明确提示暂时无法完成

降级不能突破权限和安全边界。备用模型同样要经过数据策略检查;关闭 Reranker 后,如果召回质量不达标,就应该拒答或转人工,而不是把低质量上下文直接交给模型。

降级结果也要单独计数。否则所有失败都被包装成“服务仍然可用”,团队看不到用户实际承受了多少质量损失。

六、发布门禁要同时看离线和在线

新模型或新 Prompt 发布前,先跑固定黄金数据集;小流量上线后,再比较线上指标。门禁可以这样设计:

离线:关键集质量不得下降超过 2%
离线:高风险类别不得下降
线上:灰度 1 小时无安全违规
线上:P95 延迟不超过预算
线上:负反馈率不显著上升

不能只看平均提升。新版本总体质量提高 1%,但关键场景下降 5%,就不应该自动全量。灰度期间要能快速切回旧模型、旧 Prompt 和旧索引,回滚本身也应该定期演练。

七、告警要连接到行动

一个好的告警包含四件事:发生了什么、影响范围、可能原因和建议动作。

告警:RAG 有依据回答率低于 92%
范围:模型 v7、租户组 B、过去 15 分钟
线索:检索 Recall@5 同时下降,索引版本刚切换
动作:暂停索引 v43,切回 v42,回放失败 Trace

如果告警只写“质量异常”,值班同学还要从几十个系统里找线索,最后很容易疲劳并忽略真正的问题。指标必须能下钻到模型、Prompt、索引、租户和请求样本。

八、SLO 也要防止被滥用

指标一旦变成考核,就可能被优化成数字游戏。比如把低质量回答排除出分母,把超时请求直接丢弃,把用户负反馈入口藏起来。解决方法是让指标定义公开,分母固定,失败样本可审计,并且同时保留多个互相制约的指标。

质量、延迟、可用性和安全应该一起看:降低上下文可以提升延迟,却可能伤害召回;关闭安全检查可以提高成功率,却会增加风险;使用更大模型可以提高质量,却可能超出成本和延迟预算。没有单一“北极星数字”能替代这些取舍。

总结:SLO 是团队对用户体验的共同承诺

AI 系统的 SLO 最终不是一张监控大屏,而是一套共同语言。质量告诉我们答案有没有用,延迟告诉我们用户等得是否值得,可用性告诉我们任务是否真的完成,安全则规定了哪些错误绝不能发生。

我现在看一条“服务正常”的告警,会继续追问:正常的是服务器,还是用户?如果答案没有依据、请求虽然成功但任务没有完成、越权内容已经进入上下文,那么绿色的 HTTP 状态码没有太大意义。

把指标拆开,给每个目标设定预算,提前设计降级和回滚,用离线评测与线上灰度互相验证,AI 系统才有可能从“偶尔很好用”走向“长期值得信任”。SLO 不是给工程师增加报表,而是提醒我们:模型会变化,数据会变化,用户也会变化,只有把变化测出来,系统才有机会在变坏之前被修好。

🤪 您也可以编辑此页: