15. LLM 应用的 SLO 怎么定?延迟预算怎么在链路里分配?

整理 LLM 应用的 SLO/SLA 设计、延迟预算分解与监控落地。

简单回答

LLM 应用的 SLO 不能照搬传统服务那套"P99 延迟 < 200ms",因为生成耗时天然和输出长度成正比。常见做法是把 SLO 拆成三个独立指标——TTFT(首字延迟,反映 Prefill 体感)、TBT(token 间延迟,反映 Decode 流畅度)、整体可用性(成功率)。延迟预算要按调用链路分摊:Gateway 鉴权和路由、Prompt 组装、可选的 RAG 检索、模型推理、流式回传、后处理(安全过滤、格式校验),每一段都给一个上限,加起来不能超过 SLO。预算超了要么减少环节、要么并行化、要么降级。

详细解释

为什么传统 P99 延迟指标不适用

传统服务的延迟指标是"端到端总耗时"。LLM 应用直接套这个会得到一组没法解释的数字——同一个 API 端点上,请求一个 200 字摘要和请求一篇 3000 字的文章延迟差 30 倍,混在一起算 P99 几乎没有信息量。

更糟的是优化方向也搞不清楚。一次请求 5 秒,到底是 Prefill 慢、Decode 慢、还是 RAG 检索拖后腿?只看总时延做不出判断,没办法定 SLO 也没法定向优化。

业界(Anthropic、OpenAI 的 SLA 文档、SGLang/vLLM 的 benchmark)的共识是把 LLM 服务的延迟拆成三个独立维度看:

TTFT(Time To First Token):从请求发出到收到第一个 token 的时间。反映用户"等多久才看到回复开始"。和 Prompt 长度强相关。

TBT(Time Between Tokens,或叫 ITL = Inter-Token Latency):相邻两个 token 之间的间隔。反映流式生成是否流畅。和 batch 拥塞、并发数强相关。

TPOT(Time Per Output Token):平均每个输出 token 耗时,等价于 1 / Decode 吞吐。

这三个里 TTFT 和 TBT 是面向用户体验的核心指标。TPOT 更多用在内部容量规划。

SLO 怎么定

不同业务对这三个指标的要求差别很大。

实时对话/客服:用户在等回复出现,TTFT 要严,TBT 要稳。典型 SLO:TTFT P99 ≤ 1s,TBT P99 ≤ 80ms(每秒至少 12 token)。

长文档生成/写作:用户能等几秒看到开头,关键是流式不卡。TTFT P99 ≤ 3s,TBT P99 ≤ 100ms。

Agent 任务/工具调用循环:用户根本不期待立即响应,整体完成时间和工具调用成功率更重要。可以放松 TTFT(5-10s),但每步成功率要高(≥ 99.5%)。

离线批处理:吞吐优先,延迟基本不管,SLO 退化成"任务在 X 分钟内完成"。

可用性 SLO 一般独立定,比如成功率 ≥ 99.9%("成功"定义要明确——是 HTTP 200 算成功,还是必须输出非空、内容安全检查通过、格式合法等都算上)。LLM 应用比传统服务更难定义"成功",因为还有内容质量这一维。一些团队会把"高质量回答的比例"作为业务 SLO(通过 LLM judge 或人工抽检测量),独立于可用性 SLO。

延迟预算分解

SLO 定下来后要做 latency budget 分解——把端到端预算切成段,给链路里每个环节分一份。

以一个 RAG 应用为例,TTFT P99 ≤ 1s 的预算可以这样分:

环节预算说明
Gateway 鉴权 / 限流20ms包括 JWT 校验、Redis 计数
请求路由 / 模型选择10ms多模型场景的选路逻辑
RAG 检索(embedding + 向量库 + rerank)200ms这一段是常见瓶颈
Prompt 组装 + 安全前置过滤30ms拼接、长度截断、敏感词过滤
LLM Prefill(直到第一个 token)600ms模型推理本身
流式回传首 token30msTLS、网络、SSE 框架开销
监控/日志旁路写入< 10ms异步即可,不阻塞
合计900ms留 100ms buffer

每段都有清晰的负责团队和优化手段。RAG 200ms 不够就缩小召回数、加缓存、用更快的向量库。Prefill 600ms 不够就上 Chunked Prefill(推理服务专题第 16 篇)、量化、或者切到更小的模型。

不可压缩的部分要识别清楚

延迟预算分解的关键是识别"不可压缩"的部分。Prefill 的耗时主要由 Prompt 长度和模型大小决定,给定模型和 Prompt 后再优化空间有限。RAG 的网络往返也是物理常数。这些是预算下界。

如果不可压缩部分已经超 SLO 了,就要从架构动手而不是调参——换更小的模型、缩短 Prompt(用 Prompt 压缩或更精炼的 System Prompt)、或者把同步链路改成预计算(System Prompt 走 Prompt Caching、RAG 走前置预检索)。

TBT 的预算逻辑不一样

TTFT 是单点延迟可以加法分解,TBT 是稳定性指标——"每个 token 间隔不能超过多少"。它的预算分解是另一套逻辑。

TBT 不达标的常见原因不在调用链路里,而在推理引擎的调度上:batch 太满导致每步算完慢、Continuous Batching 里新请求进来抢资源、KV Cache 满了触发抢占。这些都是推理服务专题里讲的话题。

应对手段是限制 batch size、给关键业务做独立的推理实例(不和长任务混跑)、或者用第 17 篇讲的 Prefill-Decode 分离把 Decode 的尖刺抹平。

监控和告警怎么搭

SLO 必须有监控才能落地。常见的指标采集点:

  • 在 Gateway 层打点 TTFT(请求到第一个 token 的时间)
  • 在流式回传层打点每个 token 的时间戳计算 TBT
  • 按业务、按模型、按用户维度分别聚合,看 SLO 达成率
  • 设错误预算(error budget)告警——SLO 是 99.9%,每月允许 0.1% 不达标,烧完就要冻结发布

更进一步是把延迟指标和业务指标关联——TTFT 升高时用户中止率(在第一个 token 出现前关掉页面)会上升多少,TBT 升高时用户负反馈("卡顿")会上升多少。这是 SRE 那套"以用户体验为锚点定 SLO"思路在 LLM 上的具体落地。

链路追踪要支持流式

LLM 应用的可观测性专题(本专题第 04 篇)讲过 tracing 的重要性。SLO 落地要求 tracing 能精确捕获 TTFT 和 TBT——这意味着每一段(Gateway、Retrieval、Prefill、首 token、流式)都要单独打 span,而且要正确处理"流式响应未结束就要回写 trace"的场景。OpenTelemetry 的 streaming span 支持是必要条件。

面试时可以这样答

LLM 应用的 SLO 不能用传统的端到端 P99 延迟,因为生成耗时和输出长度强相关,混在一起算没法解读。业界通常拆成三个指标——TTFT 反映 Prefill 体感,TBT 反映 Decode 流畅度,可用性反映成功率。

不同业务对这三个指标的权重不一样。实时对话要 TTFT 严、TBT 稳;长文生成放松 TTFT 但 TBT 要稳;Agent 任务整体成功率优先于 TTFT;离线批处理只看完成时间。

SLO 定下来要做延迟预算分解。把端到端预算切成 Gateway 鉴权、路由、RAG 检索、Prompt 组装、LLM Prefill、流式回传等若干段,每段给一个上限。一个 1s TTFT 的预算典型分法是:Gateway 30ms、RAG 200ms、Prompt 组装 30ms、Prefill 600ms、网络 30ms,留 100ms buffer。每段超出预算就有定向优化手段——RAG 慢就缩召回加缓存,Prefill 慢就 Chunked Prefill 或换小模型。

关键是识别不可压缩的部分。Prefill 时间由 Prompt 长度和模型大小决定,再调参也压不下去。如果不可压缩部分已经超 SLO,就得从架构动手——换模型、缩 Prompt、或者把同步链路改预计算。

TBT 的预算逻辑不一样,它是稳定性指标。问题通常不在调用链而在推理引擎调度上——batch 拥塞、抢占。应对是限制 batch、关键业务独立推理实例、PD 分离把 Decode 尖刺抹平。

落地要靠监控。每段单独打 span 算 TTFT 和 TBT,按业务/模型/用户维度聚合,设 error budget。tracing 要支持流式 span,OpenTelemetry 的 streaming 支持是必要条件。

常见追问

  1. TTFT 大头落在 Prefill 但 Prefill 已经做了所有优化还是不达标,怎么办?
  2. 多模型/多 Provider 场景下 SLO 应该按 Provider 单独定还是合一定?
  3. 业务指标(用户中止率、负反馈)和 SLO 怎么关联?怎么用业务指标反推 SLO 阈值?