🧠AI Eval 与观测

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 数 × 单价」,但工程上要拆到:

成本项占比典型值优化手段
输入 token50%~70%Prompt 精简、上下文压缩、Cache
输出 token20%~40%max_tokens 限制、结构化输出
Prompt Cache hit折扣 50%~90%静态 prefix 前置
Embedding1%~5%复用 / 离线建库
Rerank5%~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——多轮场景的真实成本被低估

记忆技巧

记三组锚点:

  1. 延迟三件套:TTFT(体感)/ TPS(流畅度)/ 端到端(完整)
  2. 成本五要素:输入 / 输出 / Cache / Embed / Rerank
  3. 切片五维度:用户 / 用例 / 模型 / 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 但服务不同问题
Related · Eval 与观测