推理:成本建模与 SLO 设计

推理:成本建模与 SLO 设计

Charles Lv7

推理系统上线后,技术讨论很快会落到两个现实问题:服务到底贵不贵,多快才算足够快。前者对应成本建模,后者对应 SLO。没有成本模型,团队很难判断量化、缓存、路由、蒸馏是否带来净收益;没有 SLO,优化会陷入无限追求更低时延,却不清楚哪些改动值得做。

初学者先抓住

成本模型回答“这次优化省了多少钱”,SLO 回答“服务体验最低要守住什么线”。没有这两者,推理优化很容易变成单纯追求更快,但不知道是否值得。

有趣例子:外卖配送

不同餐厅可以承诺不同送达时间,但承诺必须和骑手数量、距离、餐品准备时间匹配。推理服务也是这样:SLO 不能脱离模型大小、上下文长度、GPU 资源和缓存命中率。

SLO 是决策约束

SLO 不是“越快越好”,而是明确的服务目标,例如:

  1. P95 首 token 延迟低于 2 秒;
  2. P99 请求成功率高于 99.5%;
  3. 普通问答平均成本低于某阈值;
  4. agent 任务完成率高于某水平;
  5. 高风险任务必须触发工具校验或人工审核。

SLO 的价值是把优化目标变成可决策的约束条件。不同业务的 SLO 不同:企业问答更重正确率和引用证据,屏幕 agent 更重交互延迟,批处理文档分析更重吞吐和成本。

成本组成

单位时间总成本可粗略表示为:

Ctotal=Ccompute+Cmemory+Cstorage+Cnetwork+CopsC_{\text{total}} = C_{\text{compute}} +C_{\text{memory}} +C_{\text{storage}} +C_{\text{network}} +C_{\text{ops}}

换成单请求视角:

CreqCprefill(Lin)+Cdecode(Lout)+Ctool+CoverheadC_{\text{req}} \approx C_{\text{prefill}}(L_{\text{in}}) +C_{\text{decode}}(L_{\text{out}}) +C_{\text{tool}} +C_{\text{overhead}}

单位 token 成本可近似为:

Cost/token=Ch3600Θ\text{Cost/token} = \frac{C_h}{3600\cdot \Theta}

其中 ChC_h 是集群每小时成本,Θ\Theta 是 token/s 吞吐。但这只是平均数。真实系统中,不同请求长度、路由、缓存命中和工具调用会让成本波动很大。

Prefill 与 Decode 的经济学

Prefill 和 decode 的资源画像不同。长上下文请求主要成本在 prefill 和 KV 显存;长答案请求主要成本在 decode;agent 可能成本在多轮工具调用和等待。

因此成本建模要按请求桶拆:

请求桶 主要成本 常见优化
短问答 queue、launch、模型常驻 小模型、batching、prefix cache
长文档 prefill、KV、检索 上下文压缩、检索裁剪、分离式 prefill
长生成 decode、KV 生命周期 speculative、输出策略、draft
多工具 agent 工具延迟、轮次、状态 工具缓存、流程压缩、异步
多模态 视觉编码、跨模态 token 图像裁剪、视觉缓存、模型路由

用一个统一“每 token 成本”概括,会误导优化方向。

端到端成本账:同一个请求怎么估

为了避免成本建模停在抽象公式,可以固定一个请求形态来算:用户带一段文档问问题,输入上下文为 LinL_{\text{in}},输出为 512 token,服务目标是 P95 TTFT < 2s、TPOT < 60ms/token。同一个请求在不同 context、KV、batch 和量化策略下,成本结构会完全不同。

一个可落地的估算顺序是:

  1. 先估 prefill:输入 token 越长,prefill 计算和写入 KV 的成本越高。
  2. 再估 KV:KV 显存大致随层数、KV head、head dim、上下文长度、batch 和 dtype 线性增长。
  3. 再估 decode:输出越长,逐 token 读取 KV 和权重的时间越长。
  4. 最后估系统项:排队、cache hit/miss、路由、工具、网络和重试。

KV cache 可先用这个粗式子做数量级判断:

MKV2×Llayers×B×Lctx×Hkv×Dhead×bytesM_{\text{KV}} \approx 2 \times L_{\text{layers}} \times B \times L_{\text{ctx}} \times H_{\text{kv}} \times D_{\text{head}} \times \text{bytes}

其中前面的 2 分别对应 K 和 V。它不是精确容量模型,但足够帮助判断“长上下文 + 大 batch + 高精 KV”为什么会快速吃掉显存。

方案 Context / KV / Batch / 量化 主要收益 主要代价 适合判断
A. 4k + FP16 KV + 小 batch + FP16 权重 短上下文、低并发、质量保守 实现简单,TTFT 稳 单请求成本高,显存利用差 适合高价值、低并发、质量优先请求
B. 32k + FP16 KV + 中 batch + W8A8 长文档,权重降带宽 权重显存和带宽下降 KV 仍是大头,长 prefill 昂贵 若 TTFT 主要被 prefill 卡住,还要配合 prefix cache / prefill 分离
C. 32k + KV INT8 + 中 batch + W4A16 同等上下文提高并发 KV 和权重都省显存 需要专门评测长尾质量、dequant 和 kernel 支持 适合并发受 KV 水位限制的服务
D. 128k + KV INT8/FP8 + 分离 prefill + 分桶 batch 超长上下文和高复用 长请求可运营,短请求不被拖死 架构复杂,KV 转移和状态一致性要算进成本 适合企业文档、代码库问答、长记忆 agent

更实用的成本账不是问“每 token 多少钱”,而是问:

问题 需要记录的量 决策含义
Context 变长后贵在哪里 prefill time、KV 显存、prefix hit、压缩耗时 决定做上下文裁剪、prefill 分离还是 KV 量化
Batch 变大后是否划算 queue time、实际 batch、TTFT、tokens/s 决定按吞吐池和交互池分队列
KV 量化是否真省 KV 水位、eviction、长任务质量、decode TPOT 决定 KV dtype 和敏感任务回退
权重量化是否真快 权重显存、dequant time、kernel hit、质量掉点 决定 W8A8、W4A16、FP8 或混合精度
Cache 是否可信 hit rate、saved prefill tokens、miss penalty 决定 prompt 模板、prefix 规范和 cache 生命周期

因此同一个请求的端到端估算可以写成:

CreqCqueue+Cprefill(Lin,qw,qa)+CKV(Lctx,B,qkv)+LoutCdecode-step(B,qw,qkv)+Ctool/retryC_{\text{req}} \approx C_{\text{queue}} + C_{\text{prefill}}(L_{\text{in}}, q_w, q_a) + C_{\text{KV}}(L_{\text{ctx}}, B, q_{\text{kv}}) + L_{\text{out}}\cdot C_{\text{decode-step}}(B, q_w, q_{\text{kv}}) + C_{\text{tool/retry}}

这里的 qwq_wqaq_aqkvq_{\text{kv}} 分别表示权重、激活和 KV 的精度策略。上线前最好把这张账按请求桶落到 trace:短问答、长文档、长输出、多工具 agent、多模态和 VLA 闭环不应共用一个平均成本。

质量、成本、延迟三角

很多优化都在三角关系中权衡:

  1. 大模型质量更好,但更贵更慢;
  2. aggressive batching 吞吐更高,但 TTFT 可能变差;
  3. 低比特量化更便宜,但可能损失质量;
  4. 更强检索提高正确率,但链路更长;
  5. 级联路由省成本,但失败升级会增加尾延迟。

可以把决策写成:

maxUtility=αQβCγL\max \text{Utility} = \alpha Q-\beta C-\gamma L

其中 QQ 是质量,CC 是成本,LL 是延迟。不同业务中 α,β,γ\alpha,\beta,\gamma 完全不同。

分层 SLO

成熟系统常有多层 SLO:

层级 指标
平台层 可用性、错误率、资源利用、排队时延
模型层 TTFT、TPOT、上下文上限、质量代理指标
产品层 任务完成率、人工接管率、用户满意度
业务层 工单关闭时间、转化率、成本预算

若只设平台 SLO,可能把一个快速但胡说的系统误判为健康。质量必须进入 SLO 讨论。

尾延迟尤其关键。用户不会因为 P50 漂亮而接受频繁 P99 超时;多步 agent 的尾延迟还会层层叠加。

降级与预算控制

资源紧张时,系统不应一起变慢。更好的做法是按优先级降级:

  1. 免费用户切到小模型;
  2. 长上下文请求限制最大长度;
  3. 低优先级批处理延后;
  4. 关闭二次重排、多样本采样或高成本工具;
  5. 高风险任务保留强模型和校验;
  6. 超预算租户限流或排队。

降级策略应在成本模型中预先设计,而不是高峰期临时拍脑袋。否则优化会变成一堆不可复现的特判。

建模与复盘清单

成本和 SLO 设计至少要记录:

  1. 输入/输出长度分布;
  2. 模型路由分布;
  3. cache 命中率;
  4. 工具调用轮次和耗时;
  5. p50/p95/p99 延迟;
  6. 错误率、超时率、降级率;
  7. 每请求成本、每 token 成本、每任务成功成本;
  8. 不同请求桶的质量指标。

每次优化都要回答:它降低了哪个请求桶的成本,是否伤害质量或尾延迟,峰值流量下是否仍成立,回退路径是否清楚。成本模型和 SLO 的目标不是做漂亮报表,而是让团队知道哪些优化值得做、哪些成本应该被接受、哪些流量必须被降级。

成本模型还应定期用真实账单和 trace 校准。GPU 单价、实例利用率、缓存命中、模型路由和外部工具价格都会变化;如果模型不更新,容量规划会逐渐变成过期假设。

实践中建议每次发布后做一次成本复盘:对比发布前估算和发布后真实成本,拆出哪些变化来自请求分布,哪些来自模型版本,哪些来自调度或缓存。长期看,这比单次优化更重要,因为它能让团队的容量估算越来越接近真实生产负载。

如果一个优化只降低平均成本,却让高价值请求的尾延迟或失败率变差,它不应被视为成功。成本建模必须始终和 SLO 绑定,否则团队会把系统优化成“账面更便宜、体验更不可控”的状态。

  • Title: 推理:成本建模与 SLO 设计
  • Author: Charles
  • Created at : 2025-07-27 09:00:00
  • Updated at : 2025-07-27 09:00:00
  • Link: https://charles2530.github.io/2025/07/27/ai-files-inference-cost-modeling-and-slo-design/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments