每请求到底多少钱?把 Token 成本算成可观测指标(C01)

0 阅读6分钟

系列《AI 应用生产化手册》第 14 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/… 从本篇进入模块四:成本工程与 AI 网关——成本算得清,才谈得上优化(C02/C03)和采购治理(C04/C05)

一、先看问题:三个答不上来的问题

AI 应用上线后,老板/财务问的第一批问题,往往一个都答不上来:

  1. "这个月花了多少钱?"——只能翻云账单猜,猜完了也不知道花在哪个功能上。
  2. "每个请求平均多少钱?"——不知道就没法定价、没法判断某个功能"值不值得上"。
  3. "成本突然涨了,涨在哪?"——没有按模型/功能拆解,只能等月底对账,涨完才发现。

解法:成本模型——按模型价格表,从日志里的 token 用量算出每次请求、每个模型的成本,并对预算做告警。

核心认知:成本不是"月底账单",是"实时可观测的指标"。只有拿到「每请求成本」,你才能做三件事:定价(值不值)、优化(C02/C03 省在哪)、控制(预算告警在哪断)。

二、原理

2.1 钱花在哪:四个计费项

计费项说明省钱的切入点
输入 tokenprompt + 上下文提示词精简、缓存(C02)
输出 token模型生成的答案控制 max_tokens、约束输出长度
缓存命中缓存价格更低(部分供应商)精确/语义缓存(C02)
推理模型溢价o1/R1 类按推理 token 额外计费只在真需要推理时用

单次调用成本公式:

成本 = (输入 tokens × 输入单价 + 输出 tokens × 输出单价) / 1_000_000

2.2 一次问答 ≠ 一次调用(Agent 的成本大头)

1 次用户问答
├── 1 次检索(Embedding 调用,小头)
├── 2-3 次 LLM 调用(生成 + 反思/重试,大头)
│    每次调用的 input 都含上下文(系统提示词 + 检索结果)
└── 总计:可能 = 3 × 单次调用成本

关键认知:Agent 应用的成本 ≠ 单次问答 × 单价——是「调用次数 × 每次的上下文长度」。 所以成本工程的重心不是"换个便宜模型",而是"少调用 + 短上下文"——这也是 C 系列后面几篇的主线。

2.3 价格是变量,不是常量

现实应对
模型价格经常变(而且是降价居多)价格表独立维护、可配置(--prices-file)
不同供应商计价方式不同价格表按模型标识配,不按品牌
新模型上线忘记配价格未计价模型按 0 计,但报告里明确列出来(绝不静默)

还有个容易被忽略的坑:日志里记的是逻辑名(chat-strong/chat-cheap),价格表配的是供应商名(deepseek/deepseek-chat)。两者没对齐,成本就全按 0 计——报告看起来"免费",实际钱照烧。

2.4 预算三层防线

① 单请求预算:超限拒绝/降级(和 R04 降级链联动)
② 周期预算:日/月超限告警(cost_model.py --budget)
③ 趋势告警:环比突增(接 O03 的成本指标)

告警设计原则和 E04/O03 一致:阈值 = 基线 + 容差,且告警要能行动——超预算不告诉你"是哪个模型、哪类请求在烧钱",等于没告警。

三、动手:三条命令把成本算出来(免 Key 可跑)

git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
source .venv/bin/activate

# 1. 从结构化日志算成本拆解
python scripts/cost_model.py --log tests/fixtures/sample_structured.log

真实输出(10 次调用的合成样例日志):

===== Token 成本报告 =====
调用次数: 10 | 总 token 入/出: 1360 / 236
总成本: 0.004608 元 | 平均每请求: 0.000461 元
按模型拆解:
  deepseek/deepseek-chat: 10 次 | in 1360 / out 236 | 成本 0.004608 元

注意这里最有用的不是总成本,是最后一个数:平均每请求 0.000461 元——有了它,才谈得上定价和优化。

# 2. 预算告警:超限时退出码 1(可直接接 CI / 定时任务)
python scripts/cost_model.py --log tests/fixtures/sample_structured.log --budget 0.001
echo "exit=$?"

真实结果:

总成本: 0.004608 元 | 平均每请求: 0.000461 元
[BUDGET-ALERT] 总成本 0.004608 元超过预算 0.001 元
exit=1

预算放到 1.0 元,退出码就是 0——告警是"退出码 + stderr",不靠人盯屏,这样它才能进 CI。

未计价模型:成本黑洞预警(必看)

新加一个模型但忘了配价格,会发生什么?造两行日志实测:

# 造两行日志:chat-strong 已配价,gpt-5-mini 没配价
cat > /tmp/unpriced.log <<'LOG'
2026-11-11T10:00:00Z event=llm_call request_id=r1 model=chat-strong in_tokens=820 out_tokens=140 latency_ms=1200
2026-11-11T10:00:05Z event=llm_call request_id=r2 model=gpt-5-mini in_tokens=900 out_tokens=180 latency_ms=1500
LOG

python scripts/cost_model.py --log /tmp/unpriced.log

真实输出:

===== Token 成本报告 =====
调用次数: 2 | 总 token 入/出: 1720 / 320
总成本: 0.00276 元 | 平均每请求: 0.00138 元
按模型拆解:
  chat-strong: 1 次 | in 820 / out 140 | 成本 0.00276 元
  gpt-5-mini: 1 次 | in 900 / out 180 | 成本 0.0 元
⚠️ 未计价模型(成本按 0 计,需补价格表): gpt-5-mini

gpt-5-mini 那次调用成本记成 0,报告"看起来"只花了 0.00276 元——实际成本被低估。工具至少把未计价模型列出来,人不至于完全瞎。

真实数据:50 次调用,0.001 元/请求

有 Key 之后,跑真实链路:10 个评测问题各问 5 遍 → 50 次调用,用真实价格表算 → ≈ 0.001 元/请求(deepseek 档模型,配 R04 的降级链兜底)。这个数就是后面所有成本优化(C02 缓存、C03 路由)的对照基线:没有基线,"省了 40%" 只是感觉。

四、真实踩坑

  1. 价格表不维护:默认价格写着"参考日期",上线不更新 = 报告全错——价格是变量,得有人负责维护
  2. 逻辑名 vs 供应商名没对齐:日志记 chat-strong、价格表配 deepseek/deepseek-chat,成本全按 0 计(本工具已按逻辑名配价兜住,但自研很容易漏)
  3. 未计价模型静默按 0:至少要把未计价模型列出来,否则成本报告是"看起来很美"
  4. 只算总成本不算每请求:没法定价、没法优化——avg_cost_per_request 才是决策指标
  5. 只盯调用次数不看上下文长度:Agent 的成本大头往往是"每次 input 有多大"
  6. 预算告警不带定位入口:超限了只会"哦",不知道砍哪里——告警必须能追到按模型/按功能的拆解
  7. 忘了特殊计价:缓存命中价、推理 token 溢价都和普通 input/output 不同,价格表要按真实计费结构配

五、小结

  • 一个公式:成本 = (in × 单价 + out × 单价) / 1M
  • 一个指标:avg_cost_per_request——定价、优化、告警全靠它
  • 一条纪律:价格表是资产,不是常量;未计价模型必须显式暴露
  • 三层预算:单请求 / 周期 / 趋势,告警用退出码进 CI,不靠人盯

下一篇(C02):《缓存策略》——让"同样的钱只花一遍":精确缓存 + TTL + 命中统计,实测"同一批问题跑第二遍,成本 ≈ 0(全命中)"。 收藏 + 关注,30 篇连载,把 AI 应用从 POC 送到生产。