Token 管理与成本控制完全指南:别让 AI 账单悄悄长成事故

做 AI 产品时,成本失控往往不是一夜之间发生的,而是被长上下文、重复调用、无效输出和缺少观测一点点堆出来的。本文系统讲清 token 预算、计费估算、上下文裁剪、缓存复用、模型分层与成本告警。

17 分钟阅读
小明

Token 管理与成本控制完全指南:别让 AI 账单悄悄长成事故

AI 产品早期有一种很容易让人上头的错觉:

  • 一个请求也就几分钱
  • 用户还没那么多
  • 先把体验做出来,成本以后再说

这句话在 demo 阶段没问题。

一旦功能开始被真实用户持续使用,成本会以一种很不戏剧化、但很致命的方式上涨:

  • prompt 越写越长
  • 上下文一轮轮累加
  • 同一个用户问题反复重试
  • 输出明明只用 100 字,却让模型生成 800 字
  • 分类、总结、改写、抽取分别调了四次模型
  • 没人看 token 用量,也没人知道钱到底花在哪

最后到月底,财务给你发一张账单,大家才第一次认真打开监控后台。

这时候往往已经不是“优化一下就好”的程度,而是:

AI 成本开始反噬产品模型。

所以 Token 管理和成本控制,不是上线后的收尾工作,而是 AI 工程的核心部分。

这篇文章就围绕这个主题展开:

  1. token 成本为什么总比团队预估高
  2. 怎样建立单位请求、单位用户、单位功能的成本视角
  3. 如何通过上下文裁剪、缓存复用、模型分层和输出约束降低成本
  4. 怎样做预算、告警和成本归因
  5. 什么时候该追求更低成本,什么时候不该为了省钱把体验做坏

如果你已经开始做 AI 功能,这篇越早看越值钱。


一、先认清现实:AI 成本失控,大多不是因为模型贵,而是因为调用方式浪费

很多团队第一次看到账单,第一反应是:

  • 这个模型太贵了
  • 换便宜模型吧

模型单价当然重要,但多数成本问题,真正的源头是:

  • 不必要的上下文太长
  • 重复调用太多
  • 输出太啰嗦
  • 没有做结果复用
  • 没有分场景选模型

1.1 一个很典型的浪费例子

假设用户想要一个 3 行摘要,但你的系统做了这些事:

  1. 把最近 20 条历史对话都带上
  2. 再附上大段系统说明
  3. 输出要求没限制,模型生成 700 token
  4. 结果格式不稳定,又重试一次

最后为了一个很简单的功能,成本可能放大到原本的 5~10 倍。

1.2 成本问题的本质

成本控制最核心的不是“省钱”本身,而是:

让每一份 token 支出都对应到真实业务价值。

如果某个功能很贵,但能显著提高转化或续费,它未必有问题。

真正有问题的是:

  • 花了很多 token
  • 用户没有明显感知
  • 业务结果没有改善
  • 团队还不知道钱花去了哪里

二、先建立单位成本视角:不要只看月账单

月账单是结果,不是分析入口。

更有用的做法,是把成本拆到多个粒度:

2.1 四层成本视角

粒度要回答的问题
单次调用一个请求多少钱
单个功能总结、问答、抽取分别多少钱
单用户一个活跃用户平均消耗多少
单业务结果每完成一次转化或一次成功任务,成本是多少

2.2 为什么这很重要

因为只有这样你才能判断:

  • 哪个功能最烧钱
  • 哪类用户最贵
  • 是输入成本高,还是输出成本高
  • 某次版本更新是否让成本突然上涨

2.3 一个简单的成本估算函数

type Usage = {
  promptTokens: number
  completionTokens: number
}

type Pricing = {
  inputPer1k: number
  outputPer1k: number
}

export function estimateCost(usage: Usage, pricing: Pricing) {
  return (
    (usage.promptTokens / 1000) * pricing.inputPer1k +
    (usage.completionTokens / 1000) * pricing.outputPer1k
  )
}

这个函数不复杂,但非常值得统一收口到调用层。因为后面所有的预算、归因、告警,都是从这里长出来的。


三、你真正要盯的,不只是 token 总量,而是 token 结构

一个请求贵,可能贵在完全不同的地方。

3.1 常见的四种成本结构

A. 输入太长

最常见原因:

  • 把整段上下文原样传给模型
  • 系统提示写得又长又重复
  • 历史会话不做裁剪

B. 输出太长

很多场景其实只要:

  • 分类标签
  • 3 条摘要
  • 一段简短回复

结果系统没有约束,模型就会“热情发挥”。

C. 同一请求被多次调用

例如:

  • 失败重试
  • 流式中断后重新发起
  • 前端重复提交
  • 后端多个模块分别调模型做相似任务

D. 同一结果没有复用

像:

  • 热门内容摘要
  • 公共问答结果
  • 标准化标签提取

这些结果如果每次都重算,成本会平白增加。

3.2 一个更有意义的观测表

指标含义
平均输入 tokenprompt 是否膨胀
平均输出 token输出是否失控
单次请求重试率稳定性是否拖累成本
缓存命中率是否复用已有结果
长上下文请求占比是否需要上下文治理

这组指标通常比“本月花了多少钱”更能指导优化动作。


四、最值钱的降本手段,通常不是换模型,而是少传、少调、少生成

4.1 上下文裁剪:第一优先级

绝大多数 AI 成本优化,最先该做的是上下文治理。

常见做法

  • 只保留最近 N 轮对话
  • 对历史对话做摘要压缩
  • 把系统提示拆成固定模板和场景变量
  • 删除与当前任务无关的信息

4.2 一个简单的消息裁剪示例

type Message = { role: 'system' | 'user' | 'assistant'; content: string }

export function trimMessages(messages: Message[], maxChars = 8000) {
  const reversed = [...messages].reverse()
  const kept: Message[] = []
  let total = 0

  for (const msg of reversed) {
    total += msg.content.length
    if (total > maxChars) break
    kept.push(msg)
  }

  return kept.reverse()
}

这当然不是严格 token 级裁剪,但能说明一个核心原则:

上下文不是越多越好,而是越相关越好。

4.3 输出约束:第二优先级

很多团队认真管输入,却不管输出。结果模型生成了大量业务并不需要的文字。

更好的写法是明确限制:

  • 最多 3 条要点
  • 每条不超过 40 字
  • 只输出 JSON
  • 不要解释推理过程

输出越受控,越省钱,也越稳定。


五、模型分层:把“贵模型”用在最值钱的地方

这是非常实用的工程策略。

5.1 不同任务,配不同模型

例如:

任务推荐策略
分类、抽取用轻量模型
标题生成、短摘要默认模型
高价值复杂问答强模型
fallback备用便宜模型或规则兜底

5.2 为什么这比统一换便宜模型更稳

因为用户真正感知的,不是“你整体用了哪个模型”,而是:

  • 关键任务质量够不够
  • 响应快不快
  • 错误多不多

一刀切换便宜模型,可能省了账单,却把转化和留存打掉。

5.3 一个路由示例

export function chooseModel(task: 'classify' | 'summary' | 'qa') {
  switch (task) {
    case 'classify':
      return 'small-fast-model'
    case 'summary':
      return 'balanced-model'
    case 'qa':
      return 'strong-reasoning-model'
    default:
      return 'balanced-model'
  }
}

真正成熟的系统,做的是任务路由,不是“全站统一一个模型名”。


六、缓存复用:不是所有请求都值得重新生成

很多 AI 场景有天然复用价值,但团队经常忽略。

6.1 适合缓存的 AI 结果

  • 热门文章摘要
  • 常见 FAQ 问答
  • 商品卖点提炼
  • 标签生成结果
  • 内容审核初筛结果

6.2 不适合直接缓存的场景

  • 强个性化对话
  • 高时效信息
  • 依赖实时上下文的回答

6.3 一个简单的缓存思路

import crypto from 'crypto'

export function makePromptCacheKey(task: string, input: string, version: string) {
  const hash = crypto
    .createHash('sha256')
    .update(`${task}:${version}:${input}`)
    .digest('hex')

  return `llm:${task}:${version}:${hash}`
}

这里的关键点是把:

  • 任务类型
  • prompt 版本
  • 输入内容

都纳入 key。否则 prompt 改了,旧结果还会继续污染新逻辑。


七、限制重试和重复调用:很多钱不是花在“回答”,而是花在“重新回答”

7.1 常见重复调用来源

  • 前端按钮重复点击
  • SSE 中断后直接重放整次请求
  • 后端超时阈值太短,导致误判失败再重试
  • 一个页面多个模块对同一文本各调一次模型

7.2 两个实用手段

A. 请求去重

同一用户、同一输入、短时间内相同请求,可以复用结果或合并中间态。

B. 幂等 key

对关键调用增加幂等标识,避免链路重复提交。

export function makeIdempotencyKey(userId: string, action: string, payload: string) {
  return `${userId}:${action}:${payload}`
}

这不是 AI 特有问题,但在 AI 场景里,因为调用成本更高,所以收益特别明显。


八、预算与告警:不要等月底才知道超支

8.1 至少做三层预算

层级作用
日预算及时发现异常放量
功能预算看哪个模块在失控
用户 / 租户预算控制大客户或异常行为

8.2 一个实用告警方式

  • 当日成本达到预算的 70%:提醒
  • 达到 90%:通知 owner
  • 达到 100%:触发限流、切模型或关闭非核心功能

8.3 为什么预算不是财务动作,而是系统保护动作

因为当成本失控时,背后往往对应:

  • 异常重试
  • 用户滥用
  • prompt 膨胀
  • 某次发布带来了额外调用

预算报警,很多时候就是异常检测。


九、怎样做成本归因:不然你永远不知道该先优化哪

很多团队知道“本月花了很多”,但不知道:

  • 花在哪个产品功能上
  • 哪个模型贡献最多
  • 哪个租户最贵
  • 是输入贵还是输出贵

9.1 建议最少记录这些维度

  • featureName
  • taskType
  • model
  • promptVersion
  • tenantId / userSegment
  • promptTokens
  • completionTokens
  • estimatedCost

9.2 一个记录示例

logger.info('llm.usage', {
  featureName: 'ticket_summary',
  taskType: 'summary',
  model: 'balanced-model',
  promptVersion: 'v3',
  tenantId: 'tenant_42',
  promptTokens: 820,
  completionTokens: 140,
  estimatedCost: 0.0042,
})

有了这组信息后,你才能真正回答:

  • 该优化哪一条 prompt
  • 哪个功能需要缓存
  • 哪个租户需要配额
  • 哪个模型是否该降级替换

十、什么时候不该一味省 token

这点很重要。

不是所有降本都值得做。

10.1 不值得过度压缩的情况

  • 高价值用户的关键问答
  • 结果质量直接影响转化
  • 复杂推理场景本来就需要更多上下文
  • 过度缩短输出会让结果不可用

10.2 一个成熟团队会这样看成本

不是只看“每月花多少钱”,而是看:

这笔成本和获得的业务价值是否匹配。

如果一个 AI 功能:

  • 提升了留存
  • 节省了人工审核
  • 降低了客服成本
  • 提高了付费转化

那它贵一点也可能是划算的。

真正糟糕的是:

  • 成本高
  • 用户感知弱
  • 指标无提升
  • 团队还说不清原因

十一、一套可执行的 AI 成本治理顺序

第 1 步:先打 usage 日志

没有 usage,后面所有优化都是猜。

第 2 步:看输入、输出和重试结构

先确认钱到底花在哪。

第 3 步:先做上下文裁剪和输出约束

这是最便宜、收益最高的优化。

第 4 步:再做模型分层和缓存复用

把高成本调用放到最有价值的地方。

第 5 步:最后补预算和自动保护

让成本异常能自动被发现,必要时自动限流或降级。


十二、给团队的 Token 管理检查清单

观测层

  • 是否记录了输入、输出 token 和估算成本
  • 是否能按功能、模型、租户做归因
  • 是否有日级和周级趋势图

优化层

  • 是否裁剪历史上下文
  • 是否限制输出长度和结构
  • 是否避免无意义重试
  • 是否对高复用结果做缓存
  • 是否按任务类型做模型分层

保护层

  • 是否有预算告警
  • 是否有超预算时的降级策略
  • 是否有限流或配额控制
  • 是否能快速定位异常成本上涨的版本或功能

总结

把 Token 管理与成本控制讲透,可以收敛成 5 句话:

  1. 多数 AI 成本问题,根源不是模型贵,而是调用方式浪费。
  2. 先建立单次、单功能、单用户的成本视角,再谈优化。
  3. 最值钱的降本手段通常是裁剪上下文、约束输出、减少重复调用。
  4. 模型分层和缓存复用,是让成本和体验同时可控的关键。
  5. 预算、告警、归因必须上线前就准备,不要等账单教育团队。

如果你只记住一句话,我希望是这一句:

成本控制不是把 AI 变便宜,而是让每一个 token 都花在真正值钱的地方。

否则产品上线得越顺,月底最先变得不顺的通常不是接口,而是——

财务同学的表情。