![token 计量抽象示意](https://blog.kbmp.club/upload/token.jpg) 接大模型 API 之前,大部分人只看一眼单价,跑起来才发现账单比估算高出一截。问题通常不在单价,而在没搞清三件事:token 怎么数、上下文怎么计费、缓存怎么用。 这篇把这三件事讲清楚。**具体单价各家常变,以官方定价页为准**,这里讲的是结构,结构几年内不会变。 ## token 不是字 模型处理文本的最小单位是 token,不是字符也不是词。经验值: - 英文大约 1 个 token ≈ 4 个字符,或 ≈ 0.75 个单词; - 中文通常 **1 个字 ≈ 1 到 2 个 token**(取决于分词器,这是中文比英文贵的主要原因)。 所以别用「字数 × 单价」估算,误差能到一倍。正确做法是**在代码里直接读 API 返回的 usage 字段**,那个才是计费依据。 ## 输入和输出分开计价,输出贵得多 这是第二容易踩的坑。一次调用的费用是: ``` 费用 = 输入 token × 输入单价 + 输出 token × 输出单价 ``` 输出单价通常是输入的 3 到 5 倍——因为生成是逐 token 的串行过程,占用算力的时间远长于一次性读入。 直接影响决策: - 让模型「简要回答」不只是风格问题,是省钱; - 要求输出 JSON 时,**键名也算输出 token**,能短则短; - 长文档摘要比长文档问答贵。 ## 真正的杀手:上下文是累计计费的 模型本身没有记忆。多轮对话之所以「记得」,是因为客户端每轮都把**完整历史重新发一遍**。 假设每轮新增 500 token,聊 20 轮: ``` 第 1 轮发送: 500 第 2 轮发送: 1000 ... 第 20 轮发送: 10000 总计输入: 约 10.5 万 token ``` **成本随轮次大致呈平方增长**,而用户感受只是「多聊了几句」。这就是为什么一个看起来很轻量的对话机器人,账单能翻着涨。 对应的办法: - **滑动窗口**:只保留最近 N 轮; - **历史摘要**:超过阈值就把前面的对话压缩成一段摘要再塞回去; - **无状态设计**:能单轮解决的任务就不要维护会话。 ## 缓存:前缀命中能省一大截 主流 API 都提供 prompt caching:如果本次请求的前缀与前一次一致,命中部分按折扣价计(通常便宜不少,具体倍数看各家文档)。 要让缓存真的命中,前提是**前缀必须逐字节相同**。实践中要注意: - 系统提示词要放最前面,且**不要塞时间戳、随机数**进去; - 工具定义、few-shot 样例这些固定内容放在前半部分; - 变化的内容(用户输入、检索结果)放在最后。 顺序一乱,缓存就全失效。这一条的收益在长系统提示的场景下非常明显。 另外,对时效性不敏感的任务用 **Batch API**(异步批量)通常有对折优惠,适合离线批处理。 ## 三条马上能做的 1. **记日志**:每次调用把 input/output token 打进日志,别等到账单出来才知道; 2. **设上限**:给每个用户/任务设 token 预算,超限就降级到小模型或直接拒绝; 3. **分级路由**:不是所有请求都需要最强的模型。分类、抽取、简单摘要用便宜的小模型,复杂推理才上旗舰——这一条通常能省掉一半以上成本。 ## 小结 算 API 的账,记住三句话:**token 不等于字数;输出比输入贵;上下文是每轮重发的。** 把这三件事想明白,再加上缓存和分级路由,成本基本就可控了。剩下的就是持续监控——跟服务器资源一样,不测量的东西一定会失控。 --- **说明**:本文为通用技术实践整理,涉及的具体价格、折扣倍数与缓存策略以各厂商官方定价页与文档为准。