news 2026/10/8 5:52:09

AI 应用的 SLO 怎么定:质量、延迟与成本三类目标

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI 应用的 SLO 怎么定:质量、延迟与成本三类目标

说明:本文讨论的是 AI 应用的服务等级目标怎么定与怎么维护,属于 AI 运维话题,不涉及具体模型版本与价格。AI 领域版本迭代极快,凡涉及版本号、价格、可用性,请以你阅读时的官方页面为准。文中代码为结构示意,请按自己的技术栈调整后再上生产。

一、可用性在 AI 应用上会给出错误答案

传统服务的可用性口径只有两个量:请求成功率和响应时间。对读写业务库的服务,这个口径大体够用,返回成功就等于业务做成。AI 应用不满足这个前提:返回成功只说明请求被受理、产出了内容,内容对不对,可用性指标不知道。

1.1 可用性的定义域里没有对错这个概念

可用性回答的是服务有没有接住请求,不回答接住之后给的东西能不能用。这两个问题在传统业务里高度重合,在 AI 应用里可以完全脱钩。

于是会出现一个看起来矛盾的组合:可用性长期停在 99.9%,用户侧却持续反馈答案不能用。两者不冲突,量的是不同的东西。延迟分位同理,它量的是等待时长,不是等待的价值——一个 200 毫秒返回的错答案,在延迟指标上比一个 3 秒返回的好答案好看得多。

结论先行:可用性要保留,但它不能当 AI 应用的唯一目标。至少并行维护三类:质量、延迟、成本。

1.2 六种在监控上看不出来的失败

失败形态监控上长什么样用户侧实际感受归属目标
答非所问200,输出长度正常,延迟正常内容不可用质量
结构崩掉200,但下游消费方解析失败流程中断质量
静默截断200,结束标记正常,内容不完整结论缺一半质量
依赖兜底200,实际走了降级分支结果明显变差质量
变慢200,延迟分位上移等待过长延迟
变贵200,用量上移无感,事后对账才发现成本

对照传统口径:只有后两行会反映到可用性与延迟指标上,前四行在可用性、响应时间、错误率上全是绿的。这就是可用性骗人的机制——定义域覆盖不到这些失败。

1.3 三类目标与一条前置条件

质量、延迟、成本三类各自独立度量,互不替代。把三者压成一个综合分,是这套体系里最常见的第一处错误,第 2 章讲为什么。

还有一条前置条件:每个目标都要能被自动测量,测量结果要能落进同一个固定窗口的口径里。做不到自动测量的目标会退化成口号——写进文档,没人能判断有没有达成,也就没人会为它做取舍。

二、质量 SLO:从可自动判定的代理指标起步

质量的定义本身是主观的:同一条回答,换个用户、换个场景,判定可能相反。所以质量目标不能直接定,要先找到与质量相关、又能自动算出来的代理指标。

2.1 什么是合格的代理指标

一个代理指标要同时满足三个条件,缺一不可:

  • 与质量单调相关:指标变差时用户感知的质量大概率也变差,不能反过来。
  • 可自动判定:判定过程不需要人在环,否则做不成门禁。
  • 有稳定基线:同一批流量正常情况下的波动范围有限,波动能被识别成异常。

常见错误是把代理指标当成质量本身。它的作用是发现质量下降,不是证明质量合格——这个定位要提前跟消费这个指标的人说清楚,否则质量出事后一定有人追问为什么指标没报警。

2.2 四个可以起步的代理指标

代理指标怎么算能抓到什么抓不到什么
解析成功率返回能被下游结构消费的请求数除以总请求数结构崩掉、空返回内容对不对
拒答率明确拒答与转人工的数量除以总请求数可用性收缩拒答是否合理
引用可解析率引用能定位到真实来源的条数除以总引用条数来源被编造来源是否支撑结论
人工抽检一致率抽检样本中人工判定合格的数量除以抽检样本数内容层面的整体质量单条问题的归因

四个指标分工互补:解析成功率和拒答率覆盖能不能用,引用可解析率覆盖依据是否真实,人工抽检一致率覆盖内容层面。引用可解析率怎么校验是另一个话题,这里只把它当一个可自动算的比值。

拒答率要双向看:它升高时质量类风险下降,但同时说明服务在收缩——用户没拿到东西,等价于一次失败。所以拒答率的目标是区间,不是单边上下限。

2.3 为什么不能只用一个总分

把四个代理指标加权合成一个 0 到 1 的总分,看着好看,实际会引入三个问题:

  • 方向相反被抵消:拒答率上升拉低可用性感知,却可能拉高某些质量项,加权后互相抵消,总分纹丝不动。
  • 量级不对等被掩盖:解析成功率涨 1 个点,可以掩盖引用可解析率跌 5 个点,后者对用户信任的破坏更严重。
  • 归因失效:总分掉下来不知道该动哪一段,工程上只能靠猜。

做法是把总分降级成看板排序依据,不进发布门禁。门禁逐项读:任何分项低于目标值都拦住发布,或要求随发布附一份降级方案。总分只回答哪个方向先看,不回答能不能发。

⚠️ 代码待验证

# 质量代理指标计算示意:分项各自统计,不合成单一总分defquality_proxies(window_events):total=len(window_events)iftotal==0:returnNoneparsed_ok=sum(e["downstream_parsed"]foreinwindow_events)refused=sum(e["is_refusal"]foreinwindow_events)ref_total=sum(e["ref_count"]foreinwindow_events)ref_ok=sum(e["ref_resolvable"]foreinwindow_events)return{"parse_success":parsed_ok/total,# 解析成功率"refusal_rate":refused/total,# 拒答率,看区间不看单边"ref_resolvable":(ref_ok/ref_total)ifref_totalelseNone,# 引用可解析率"sample_size":total,# 样本量必须一起返回}# 判据:样本量低于阈值时只记录趋势,不出结论,避免小样本噪声进发布门禁MIN_SAMPLE=200# 示意值,按自己的流量规模与窗口长度调整

三、延迟 SLO:首字与端到端分开定

延迟是三类目标里最好量的一类,也是最容易被一个均值糊弄过去的一类。定延迟目标之前,先要确定量的是哪一段。

3.1 首字延迟与端到端延迟是两种体感

首字延迟指用户看到第一个字的时间,端到端延迟指任务完成的时间。流式输出把两者彻底分开:首字可能很快,用户觉得响应及时;也可能首字很慢,后端还在正常生成,用户已经在找关闭按钮。

影响因素也不同:首字主要受排队位置、输入长度与预填充影响;端到端还叠加输出长度、工具调用次数与重试次数。优化手段不同就不能合成一个目标——合成后首字变慢会被端到端变快抵消,而用户感知恰恰是变差的。

判据:一个改动让首字延迟下降、端到端延迟上升,算不算改进取决于场景是交互式还是批处理。这一点要写在目标定义里,不能留给事后讨论。

3.2 分位数选哪个

均值在延迟上几乎没用:一小撮很慢的请求被大量快请求摊平,均值看着正常,那一小撮用户却已经把体验做坏了。用分位数,并且分层用:

  • 50 分位:看典型体感,回答多数请求大概等多久。
  • 95 分位:主要目标值,覆盖到足够多的用户,样本量也足够稳定。
  • 99 分位:只做观察,不进发布门禁。样本少、抖动大,作为门禁会频繁误伤发布,把团队逼到调阈值而不是改问题。

这里只引用分位数的概念,怎么测出来、压测怎么设计属于另一套话题,不在本文展开。

3.3 长任务用完成时间,不用请求时间

异步与批处理任务上,请求时间这个量直接失效:请求早返回了,真正的工作在后面慢慢跑。这时要看两个分开的量:排队时长和执行时长。

任务类型该看什么不该看什么理由
流式对话首字与端到端分开只报端到端首字决定等待体感
单轮问答端到端 95 分位均值均值掩盖长尾
工具链多轮单次工具往返加全链路只报首字大部分时间花在工具等待
异步批任务排队时长与执行时长分开请求时长请求早已返回,量不到真实等待

排队时长要单独定目标,它受并发水位影响,执行时长受任务本身影响。合成一个完成时间目标,就会出现队列积压拉高完成时间、执行环节却没问题的误判。

⚠️ 代码待验证

# 延迟目标定义示意:首字与端到端分开,异步任务拆排队与执行latency_slo:-item:first_token# 首字延迟,交互式场景的主要体感channel:streamingquantile:95window:28dgate:true# 进发布门禁,阈值按测量窗口的基线分位定-item:end_to_endchannel:streamingquantile:95window:28dgate:true# 与首字分开统计,超阈值计数互不冲抵-item:end_to_endchannel:streamingquantile:99window:28dgate:false# 只观察,样本少、抖动大,进门禁会误伤发布-item:async_completechannel:batchsplit:[queue_time,exec_time]# 排队与执行分开,避免队列问题算成执行问题window:28dgate:true

四、成本 SLO:按每完成一件任务定目标

成本目标最容易定错的地方是分母。分母选错,目标就会奖励错误的行为。

4.1 每次调用与每件任务是两个不同的分母

按每次调用定成本,数字看起来干净,但它奖励的是削减单次调用,不是削减完成任务的代价。重试、工具调用、多轮改写都会让单次调用便宜、整体更贵。

按每完成一件任务定,口径是:窗口内的总用量除以窗口内成功完成的任务数。失败任务和重试产生的用量必须留在分子里,否则成本会被成功样本稀释,看起来越来越便宜,实际是失败被藏进了另一个统计口径。

判据:某一周成功任务数下降、单次调用成本不变时,按每件任务算出的成本一定上升。这个上升是正确的信号,不该被平滑掉。

4.2 成本与质量互相牵制

成本和质量的张力不是意外,是结构性的。下表列出四类常见动作对三个目标的方向影响,用于在定目标时提前说清取舍:

动作质量影响成本影响延迟影响
增加检索轮次通常上升上升上升
加大上下文边际上升,很快趋平明显上升上升
失败重试上升上升上升,长尾更明显
裁剪上下文降级下降下降下降

这张表逼着定目标的人在纸上先选一次,而不是等出事时现场吵。降级动作要提前定义触发条件:质量分项未跌破下限、成本分项连续两个窗口超目标时触发并记录;质量一旦跌破下限,降级立即停止。不要让降级自己决定要不要降级。

4.3 目标值怎么给

先测基线,再定目标,顺序不能反。做法是:

  1. 上线后先只观测,跑一个完整的测量窗口,本文按 28 天示意。
  2. 按任务类型分别取基线分布,记下 50 分位与 75 分位。
  3. 目标值定在基线与更优之间,留一段缓冲,不拍整数。
  4. 目标值与基线一起记录,注明定值时间,方便复核。

成本目标要区别任务类型。把短问答和长文档处理混在一个目标里,长任务拉高目标,短任务的实际消耗被掩盖。账单归因与分账是另一套话题,这里只定目标值与门禁。

五、错误预算:怎么算、烧完之前做什么

三类目标定好之后,还需要一个把它们和发布节奏绑定的东西。错误预算就干这个:它把目标值翻译成一份可以消耗的额度。

5.1 预算怎么算

预算的定义很简单:目标值的补集。质量目标允许失败的样本数、延迟目标允许超阈值的请求数、成本目标允许超支的额度,都是预算。

有一条换算必须遵守:预算要换算成绝对量,不要只留百分比。百分比在决策时没用——它不告诉你还剩多少。换算完再把额度按时间摊到窗口上,才有可比的消耗速度。

窗口用滚动窗口,本文按 28 天示意,好处是预算会自然回补,不会因为月初一次事故把整月判死。

5.2 烧毁速率与动作分档

只有剩余比例不够用,还要看消耗速度。同一个剩余比例,平稳消耗和三天烧掉一半是两个完全不同的事件。烧毁速率就是当前消耗速度与允许速度的比值。

烧毁速率区间(示意值)判断动作
小于 1消耗慢于允许速度不动,继续观察
1 到 2消耗偏快,尚未失控记入发布评审,暂停非必要变更
2 到 5明显异常,存在持续劣化冻结发布,定位窗口内最近的变更
大于 5预算将在窗口内耗尽回滚最近变更,同时启动保底降级

四档动作里只有最后一档改运行态,前三档只影响发布节奏。这个设计是刻意的:预算管节奏,不管故障处置。

5.3 预算与发布门禁怎么挂钩

门禁读分项预算,不读综合分,规则可以简化成三条:

  1. 所有分项剩余高于阈值,正常发布。
  2. 剩余低于阈值,但最近一次变更与该分项无关,可发布,需附降级方案与回滚点。
  3. 剩余低于阈值,且最近一次变更与该分项直接相关,拦住,先复核再发。

还有一条容易忽略:短窗烧得快、长窗没动时先别动门禁,去查那个短窗里发生了什么。短窗波动经常来自流量结构变化,不是真劣化。

⚠️ 代码待验证

# 错误预算与烧毁速率:分项各算一份,不合成总分defburn_rate(consumed,allowed,window_fraction):ifallowed<=0:returnNoneexpected=allowed*window_fraction# 该时间点允许消耗的量ifexpected<=0:returnNonereturnconsumed/expected# 短窗看突变,长窗看趋势;长短窗都要看,避免被单次抖动带偏SHORT_WINDOW="1h"# 示意值LONG_WINDOW="6h"# 示意值BUDGET_WINDOW="28d"# 示意值,滚动窗口,预算会自然回补

完整版资料清单:本文用到的错误预算计算示例与烧毁速率对照表都整理在里面了,扫码即可获取:

六、SLO 与告警的分工

SLO 和告警都盯着同一批信号,但它们回答的问题不同。混着用,两个都会失效。

6.1 两者看的时间尺度不同

SLO 看趋势,尺度在天到周,回答的是这个服务最近是不是在变差、要不要调整工程节奏与发布计划。告警看短窗口,尺度在分钟到小时,回答的是现在有没有东西需要立刻处理。

两种误用都会出问题:

  • 拿 SLO 当告警:预算还在正常范围,服务在缓慢劣化,因为没到阈值,没人知道。
  • 拿告警当 SLO:短窗一抖就触发,天天有通知,长期趋势却平稳,团队被训练成忽略通知。

6.2 边界怎么划

维度SLO告警
时间尺度天到周分钟到小时
依据目标值与错误预算单个或少数几个窗口内的信号
输出要不要改变发布与工程节奏现在要不要有人介入
影响范围发布与排期即时响应
定错的代价要等一个窗口才发现,纠正慢反复打扰,降低响应意愿

这张表只划边界,告警怎么分级、怎么抑制重复属于另一套话题。这里强调的是不要把预算趋势接进即时通知:它变化慢,接进分钟级通道只会变成噪声,稀释真正需要即时响应的信号。

6.3 两个方向的抬升判断

边界划清之后,还有两个方向要显式判断,否则两边会各自以为是对方的问题:

  • 告警反复触发、预算没动:告警阈值与当前流量结构不匹配。回看短窗的触发原因分布,而不是去调 SLO 目标值。
  • 预算持续下降、告警没响:覆盖缺口,这条劣化路径没有对应的短窗信号。补一条能反映该分项的短窗判据,并验证它能被触发。

每轮预算复盘时对一次表:把预算下降的时段与告警触发记录并排放,看有没有跨窗口的空白段。

⚠️ 代码待验证

# SLO 与告警的分工:两条链路读不同的窗口与数据源slo:window:28d# 趋势判断,服务于发布门禁source:budget_ledgerfeeds:release_gate# 输出给发布门禁,不产生即时通知alerting:window:5m# 即时判断,只看短窗口source:short_window_metricsfeeds:incident_flowexcluded_sources:# 预算趋势不进即时通道,避免噪声稀释信号-budget_trend

七、目标值怎么定与怎么维护

最后一章讲这套东西怎么落地,以及上线之后怎么维护。

7.1 先测量再定值

上场就定一个目标值,是最常见的返工来源。定值前必须先有一个测量窗口:只观测、不出结论、不设门禁,跑满一个完整窗口(本文按 4 周示意)。

测量窗口结束之后,按下面三步定值:

  1. 按任务类型分别取分项指标的分布,记下 50 分位与 75 分位。
  2. 目标值取在基线的偏优一侧,留出缓冲,并把缓冲大小写进定义。
  3. 每个目标值都注明定值时间与当时的基线值,方便下次复核时对照。

不要拍整数。一个看起来整齐的目标值往往离真实基线很远,结果要么长期不达标、门禁形同虚设,要么长期轻松达标、什么也拦不住。

7.2 分层:按档位、按租户、按任务类型

一个目标值管不了全部流量。分层的常用维度有三个:

  • 按档位:不同服务等级对应不同的质量与延迟目标。档位之间要有明确判定条件,否则会成为扯皮入口。
  • 按租户:租户之间用量结构差异大,混在一起会让大租户拉偏整体目标。分租户看,也要有一套整体口径对外说明。
  • 按任务类型:长任务与短任务的质量、延迟、成本分布差别明显,分开定是基本要求。

分层的陷阱是层级太细:一个目标底下只剩很少的样本量,指标抖动就会淹没真实变化,门禁变成随机拦截。判据:某层在一个窗口内的样本量低于最小阈值时,该层只观测不设门禁,向上合并到上一层。

7.3 变更之后必须重定并复核

目标值不是一次定完就不动的。触发重定的变更有三类,要重看的指标也不同:

  • 模型换代:质量与延迟都要重看,成本通常同时变化。
  • 提示词或流程大改:重点看质量分项,尤其是拒答率与引用可解析率。
  • 依赖换代:重点看延迟与成本,质量可能滞后一个窗口才体现。

复核动作固定成一条:变更上线后重测一个完整窗口,把新基线与旧目标值对照,决定调目标还是改实现。不要把复核做成一次性动作,它要进发布流程、和变更绑定,否则一定被跳过。

⚠️ 代码待验证

# 目标值维护要看的观测项(示意,指标名按自己的监控系统改写) slo_objective{target=quality, item=proxy_name} # 当前目标值,按层拆开 slo_actual{target, item} # 窗口内实际值 slo_gap{target, item} # 目标与实际的差值 error_budget_remaining_ratio{target, item} # 剩余预算比例 burn_rate{target, item, window=short} # 烧毁速率,长短窗各一份 slo_layer_sample_size{layer=tier} # 分层样本量 slo_review_total{reason=model_change} # 复核触发计数 # 复核清单:变更上线后重测一个完整窗口,再决定目标值是否要调整。 # 分层样本量低于最小阈值时,该层只观测不设门禁,向上合并到上一层看。

完整版资料清单:本文用到的三类 SLO 目标模板与错误预算复盘清单都整理在里面了,扫码即可获取:

附表 A:关键取舍一览

取舍本文结论判断依据位置
可用性能不能当 AI 应用的唯一目标不能定义域里没有内容对错的判定第一章
质量目标用什么承载可自动判定的分项代理指标质量主观,无法直接定值第二章
拒答率的目标形态区间,不是单边上限升高说明服务在收缩第二章
质量分项要不要合成总分不合成,总分只看板排序合成会抵消、掩盖、破坏归因第二章
首字与端到端能否合成一个目标不能影响因素不同,合成会互相抵消第三章
延迟目标取哪个分位主要取 95 分位样本量与稳定性兼顾第三章
异步任务看请求时长还是完成时长看完成时长,且拆排队与执行请求早已返回,量不到真实等待第三章
成本的定值分母每完成一件任务按次调用会奖励削减单次开销第四章
失败与重试的用量要不要计入分子要不计入会让成本被成功样本稀释第四章
错误预算按百分比还是绝对量管绝对量百分比不告诉你还剩多少第五章
预算趋势要不要接即时通知不要变化慢,进分钟级通道只会变噪声第六章
目标值先拍还是先测先测一个完整窗口再定拍出来的值离基线远,门禁失效第七章
分层样本量不足怎么办只观测不设门禁,向上合并噪声会淹没真实变化第七章
目标值要不要随变更重定要,与变更绑定不绑定一定被跳过第七章

附表 B:术语速查表

术语含义
SLO服务等级目标,一个可测量的服务质量目标值与窗口的组合
代理指标与质量相关、可自动判定、有稳定基线的间接指标,用于发现质量下降
解析成功率返回结果能被下游结构消费的请求占总请求的比例
拒答率明确拒答与转人工的请求占总请求的比例,通常按区间定目标
引用可解析率给出的引用能定位到真实来源的条数占引用总条数的比例
首字延迟从请求发出到用户看到第一个输出片段的时间
端到端延迟从请求发出到任务完成的时间,与首字延迟分开统计
完成时间异步任务从入队到执行结束的时间,通常拆成排队时长与执行时长
错误预算目标值的补集,换算成绝对量后可用于消耗的额度,按滚动窗口回补
烧毁速率当前错误预算消耗速度与允许速度的比值,分短窗与长窗各算一份
发布门禁发布前逐项检查错误预算与目标值的规则集合,读分项不读总分
分层目标按档位、租户或任务类型拆分的独立目标值,样本量不足时向上合并

写在最后:这篇用到的资料

写这篇文章时,我把几个模型的官方文档、参数表和实测记录都对了一遍,顺手整理成几份配套的东西:

  • 大模型学习路线图:从 LLM 基础到 Agent 开发,各阶段该学什么、用什么资料
  • 大模型全套教程:按主题分好的视频与文档清单
  • 大模型实战好书:24 本,附每本适合的阶段

资料是我自己整理的,放在下面这个码上,扫码即可获取:

添加时备注「大模型」,优先通过。

拿到之后建议先看学习路线图那一份,先定位自己在哪个阶段,再决定学什么,比一上来就啃框架效率高得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 5:52:04

贴秋膘别盲目!这份秋季进补小贴士请收好

暑气慢慢褪去&#xff0c;秋风悄然登场&#xff0c;不少朋友已经准备开启贴秋膘模式。但进补可不是大鱼大肉随便吃&#xff0c;讲究循序渐进&#xff0c;吃不对反而给身体添负担✨。经历漫长盛夏&#xff0c;很多人脾胃状态偏弱&#xff0c;骤然大量食用油腻荤食&#xff0c;肠…

作者头像 李华
网站建设 2026/10/8 5:51:50

一个人加三个AI Agent,三周交付企业级项目实战复盘

1. 项目缘起与整体交付思路1.1 一个真实到有点扎心的背景去年年底&#xff0c;我接了一个企业级内部管理系统的项目。客户那边原本的规划是&#xff1a;4 人团队&#xff0c;2 个月工期&#xff0c;预算按人天算得清清楚楚。结果我这边实际投入的&#xff0c;只有我一个人&…

作者头像 李华
网站建设 2026/10/8 5:50:00

java项目-第125期SSM的学习成绩管理系统-java毕业设计

java项目-第125期SSM的学习成绩管理系统-java毕业设计 Hi&#xff0c;大家好&#xff0c;今天分享的源码是《基于SSM的学生成绩管理系统》。 系统分为三个角色,分别是学生,老师,管理员。 管理员可以对学生和老师的信息进行增删改查, 老师可以对学生录入成绩, 学生可以查看自己的…

作者头像 李华
网站建设 2026/10/8 5:49:43

3D-UNet与VNet在脑肿瘤分割中的训练优化与生存预测实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 5:48:46

Claude Code + MCP + Unity:用自然语言快速生成可玩游戏原型

1. 从空文件夹到可玩原型&#xff1a;这套组合到底在做什么一个空文件夹&#xff0c;几段自然语言描述&#xff0c;最后跑起来一个能操控角色移动、能触发碰撞、能播放动画的 Unity 游戏原型——这件事在 2024 年之前听起来像是天方夜谭&#xff0c;但现在确实有人跑通了。核心…

作者头像 李华