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 | 模型推理本身 |
| 流式回传首 token | 30ms | TLS、网络、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 支持是必要条件。
常见追问
- TTFT 大头落在 Prefill 但 Prefill 已经做了所有优化还是不达标,怎么办?
- 多模型/多 Provider 场景下 SLO 应该按 Provider 单独定还是合一定?
- 业务指标(用户中止率、负反馈)和 SLO 怎么关联?怎么用业务指标反推 SLO 阈值?