Token 成本与延迟观测
难度:⭐⭐ | 高频指数:🔥🔥 | 应用岗相关度:★★★
面试回答
常见问法
- 你们 LLM 应用上线后,第一波要打的指标是哪几个?
- Token 成本和延迟具体怎么埋点?埋在哪一层?
- 一次请求的延迟拆开看,分别是哪些部分?
- 线上成本突然涨了一倍,你怎么定位?
- 怎么算 cost-per-conversation?为什么不是 cost-per-token?
- 什么时候该上 Prompt Caching、模型路由、蒸馏?怎么判断 ROI?
回答
Token 成本和延迟是 LLM 应用第一阶段就必须打通的两个指标,比离线评测还优先——因为它们直接决定项目能不能继续做下去。
工程上要拆清楚两件事:成本不是一个数字,延迟也不是一个数字。成本至少要拆到 输入 token / 输出 token / Prompt Cache 命中 / 嵌入调用 / Rerank 调用 这五类;延迟至少要拆到 TTFT(首 token 时间)/ TPS(每秒输出 token)/ 端到端 RT 这三层。只看「总 token」「总延迟」会让你完全看不到优化空间在哪。
埋点位置上,统一放在 LLM Gateway 层——所有出向调用都过这一层,做调用、计费、Trace、采样统一处理。如果埋在业务代码里,会出现「换了个模型 SDK 就丢一半字段」的情况。
线上要按 用户 / 用例 / 模型 / Prompt 版本 / Tenant 多维切片,单看总账只能告诉你「贵了」,切片才能告诉你「贵在哪一块」。面试官真正想问的是:你有没有把成本/延迟当成一等公民的工程指标,而不是事后报表。
追问
- TTFT 和 TPS 各自反映什么?哪个对用户体感影响更大?
- Prompt Cache 命中率怎么统计?为什么不是越高越好?
- 同一个请求换模型后成本怎么对齐?
- 流式输出场景下的延迟怎么采集?
- 怎么识别「单用户成本异常」?做配额还是做限流?
- 模型路由(用便宜模型处理简单 query)怎么算 ROI?什么时候得不偿失?
原理展开
1. 为什么 Token 成本是第一阶段就要打的指标
很多团队第一版上线先做功能,再考虑监控,这套思路放在 LLM 应用上是反的。
LLM 调用的边际成本远高于传统服务——一次普通 API 请求可能 0.001 元,一次 GPT-4 调用可能 0.1 元,差两个数量级。一旦放量,没有 token 监控的系统会在 24 小时内烧出预算缺口,等你看到账单已经晚了。
工程上的判断标准是:只要你的应用要上线给真实用户用,token 成本观测必须和功能同步上线——这是底线,不是加分项。优先级甚至高于离线评测,因为评测做错了可以回滚,钱烧出去拿不回来。
2. 成本构成:拆到五类才能讲清楚
总成本表面上是「token 数 × 单价」,但工程上要拆到:
| 成本项 | 占比典型值 | 优化手段 |
|---|---|---|
| 输入 token | 50%~70% | Prompt 精简、上下文压缩、Cache |
| 输出 token | 20%~40% | max_tokens 限制、结构化输出 |
| Prompt Cache hit | 折扣 50%~90% | 静态 prefix 前置 |
| Embedding | 1%~5% | 复用 / 离线建库 |
| Rerank | 5%~10% | 限定候选集大小 |
输入 token 通常是大头,原因是 System Prompt + Few-shot + RAG 上下文都计费,而用户那句话往往很短。所以优化先动输入侧——把 System Prompt 抽成 Cache prefix、把 RAG 拼接控制在 N 个 chunk 内、把 Few-shot 蒸馏到更小的模型。
判断手段是看「输入/输出比」,比值越高说明上下文越冗余,优化空间越大。
3. 延迟构成:TTFT、TPS、端到端
延迟不能只看「总耗时」,对话场景下用户感知主要由两个指标决定:
- TTFT(Time-To-First-Token):用户按下回车到第一个字出现的时间。这是体感关键,超过 2s 用户就会怀疑「卡了吗」。
- TPS(Tokens Per Second,吐字速度):影响阅读流畅度。低于 20 tok/s 会有明显停顿感。
- 端到端 RT:完整生成结束的时间,对非流式 API、批处理场景重要。
工程拆解一次 RAG 请求的延迟构成:
用户请求
├─ 鉴权/路由 ~5ms
├─ Query 改写 ~200ms (一次小模型调用)
├─ Embedding ~50ms
├─ 向量检索 ~30ms
├─ Rerank ~150ms
├─ Prompt 拼接 ~5ms
├─ LLM TTFT ~800ms ← 用户开始看到字
└─ LLM 全部输出 ~3000ms ← 端到端结束
TTFT 才是用户体感的瓶颈——如果 LLM 之前的所有步骤加起来超过 1s,再快的吐字也救不回来。优化优先级永远是「先优化 TTFT 前置链路,再优化生成本身」。
4. 埋点应该埋在哪一层
埋点位置直接决定数据质量。常见错误是「在业务代码里埋」——业务有 N 个,每个都漏字段,最后数据对不齐。
正确做法是统一 LLM Gateway:
业务A ──┐
业务B ──┼──► LLM Gateway ──► OpenAI/Anthropic/自研推理
业务C ──┘ │
├─ 统计 token / 计费
├─ 写 Trace(OTel)
├─ 采样落盘(Prompt + Response)
└─ Cache 命中标记
Gateway 强制要求所有出向调用都过它,字段一处定义,全局一致。即使业务侧换 SDK、换模型也不影响监控数据。
埋点要采集的最小字段集:
trace_id, span_id, parent_span_id
user_id, tenant_id, use_case, prompt_version
model, model_version
prompt_tokens, completion_tokens, cache_read_tokens, cache_write_tokens
ttft_ms, total_ms, tps
cost_usd ← Gateway 直接算出来,不要业务算
status, error_code
5. 按维度切片:总账只能告诉你贵了
聚合维度决定了排查效率。线上至少要支持这五个维度的切片:
- 按用户 / Tenant:识别异常大户、薅羊毛、滥用
- 按用例(chat / summarize / agent / search):哪类业务在烧钱
- 按模型:换模型前后的成本对比
- 按 Prompt 版本:新 Prompt 是不是把 token 写长了
- 按时间:突增定位发布窗口
实战里最常见的告警场景:单用户成本突刺——某个 user_id 一小时打了 10 万 token,多半是脚本攻击或者循环死锁。这种用「总账」绝对发现不了,必须做 per-user p99 监控。
6. cost-per-conversation:业务侧的真口径
技术侧讲 token 单价,业务侧关心「每个对话花多少钱」。两者口径完全不同:
cost_per_conversation
= Σ(每轮的 input_cost + output_cost + cache_cost)
+ Σ(辅助调用:embed、rerank、query改写、judge)
+ Σ(工具调用本身的费用)
关键点:多轮对话的 token 是滚雪球的——第 5 轮的输入要带上前 4 轮的历史,单轮看不出问题,整条会话才暴露成本。所以聚合一定要按 conversation_id 汇总,不是按 request_id。
业务方拿到这个数后,会反过来推「这个功能的客单价能不能 cover 成本」——这是 LLM 应用商业化绕不开的对账。
7. 降本的判断时机:Cache、路由、蒸馏
不是一上来就优化,要先有数据再决定动哪里:
Prompt Caching 适用条件:System Prompt 长且固定(>1k tokens)、调用频率高、Cache 命中折扣 > 改造成本。命中率到 70% 以上才有显著收益。
模型路由适用条件:流量里有明显的「简单 query」长尾(如 FAQ、闲聊),可以用 Haiku/GPT-4o-mini 接住,复杂的留给大模型。关键是路由本身的判断成本不能反客为主——如果用大模型做路由判断,那就是负优化。
蒸馏适用条件:调用量大、Prompt 稳定、对延迟敏感。用大模型生成数据训小模型,前期投入大,后期 ROI 高,适合 1 年以上稳定运营的场景。
判断流程:
Cache 命中率 < 30%? → 重排 Prompt 结构,把静态部分前置
单次调用 > 5k tokens? → 上下文压缩、RAG 减 chunk
简单 query 占比 > 50%?→ 上模型路由
单一场景调用 > 100w/天?→ 评估蒸馏
8. 和「线上指标与 Tracing」的关系
这两块是同一套观测体系的不同视角,不要重复埋点,要分层:
- 本节(成本/延迟):聚焦在数字指标——多少钱、多少毫秒,按维度聚合做 dashboard 和告警
- Tracing:聚焦在因果链路——一次请求经过哪些 span,每个 span 出了什么问题
实战里两者共享 trace_id,但服务的问题不同:成本观测回答「贵不贵」,Tracing 回答「为什么贵 / 为什么慢」。先看成本 dashboard 发现异常,再下钻到 Tracing 查具体 case——这是标准排查路径。
对比总结
| 指标 | 反映什么 | 采集位置 | 典型告警阈值 |
|---|---|---|---|
| TTFT p95 | 体感首字延迟 | Gateway / 流式回调 | > 2000ms |
| 端到端 RT p99 | 完整生成时间 | Gateway | > 10s |
| TPS | 吐字速度 | 流式回调 | < 20 tok/s |
| 输入 token 均值 | Prompt 是否冗余 | Gateway | 环比 +30% |
| 输出 token 均值 | 模型啰嗦程度 | Gateway | 环比 +30% |
| Cache 命中率 | 优化是否生效 | Gateway | < 50% |
| cost-per-conversation | 业务单价 | 聚合层 | 超预算 |
| 单用户成本 p99 | 异常滥用 | 聚合层 | 突刺告警 |
易错点
- 只记
total_tokens不拆输入输出——成本算不准,优化没方向 - 忘记记录模型版本——上游静默升级后回归对比直接断档
- 流式场景只统计总时延——TTFT 这个最重要的体感指标完全丢失
- 埋点埋在业务代码里——字段不一致,换 SDK 就漏数据
- 只看总账不切片——单用户突刺、单 Prompt 版本回退都看不见
- Cache 命中率没单独统计——优化做了没做、效果好不好都说不清
- 按 request 聚合而不是按 conversation——多轮场景的真实成本被低估
记忆技巧
记三组锚点:
- 延迟三件套:TTFT(体感)/ TPS(流畅度)/ 端到端(完整)
- 成本五要素:输入 / 输出 / Cache / Embed / Rerank
- 切片五维度:用户 / 用例 / 模型 / Prompt 版本 / Tenant
一句话:总账只能告诉你贵了,切片才能告诉你贵在哪。
面试速答版
Token 成本和延迟是 LLM 应用第一阶段就要打通的指标,比离线评测优先级还高,因为它直接决定项目能不能继续做下去。
工程上要拆清楚:成本至少分输入/输出/Cache/Embed/Rerank 五类,延迟至少分 TTFT/TPS/端到端三层,只看总账完全看不到优化空间。埋点统一放在 LLM Gateway 层,所有出向调用过这一层,字段一处定义。
线上必须按用户、用例、模型、Prompt 版本、Tenant 多维切片,最常用的是单用户 p99 异常告警——薅羊毛、脚本攻击、循环死锁全靠这个发现。聚合口径上业务侧关心 cost-per-conversation,按 conversation_id 汇总,不是 request_id。
面试加分版
- TTFT 比端到端 RT 更影响体感——流式场景下用户感知是「第一个字什么时候出来」,不是「全部生成完什么时候结束」。优化优先级永远是先优化前置链路(Embed / Rerank / Query 改写),再优化生成本身
- Prompt Caching 命中率不是越高越好——命中率 99% 可能说明 Prompt 几乎全静态,业务灵活度不够;30%~70% 是健康区间
- 模型路由的判断成本不能反客为主——用大模型做小模型的路由判断属于负优化,要么用规则路由,要么用极小模型做分类
- 成本观测和 Tracing 是同一套体系的两个视角——成本回答「贵不贵」,Tracing 回答「为什么贵」,共享 trace_id 但服务不同问题