比较AI API费用,不能只看输入token单价。同一个摘要任务,缓存是否命中、输出多长、失败后重试几次,都会改变最后的支出。先把每次尝试记全,再计算完成一个任务花了多少钱。

先把token分成互不重叠的几项
下面用同一份说明文档的摘要任务演示:固定资料12000 token,每次新增问题1000 token,回答500 token。所有单价和用量都是教学假设,不对应任何服务的当前报价或真实账单。
| 计费项 | 假设单价,元/百万token | 在例子中代表什么 |
|---|---|---|
| 普通输入 | 2.00 | 未进入缓存读写的输入 |
| 输出 | 10.00 | 本次生成的回答 |
| 缓存写入 | 2.50 | 首次写入的固定资料 |
| 缓存读取 | 0.20 | 后续命中的固定资料 |
这个模型里,同一个输入token只归入普通输入、缓存写入、缓存读取中的一项。实际服务的usage字段口径可能不同:有的总输入已经包含缓存部分。应先按对应文档拆分,不能把总输入完整计价后,再加一遍缓存费用。
单次费用 = 普通输入token × 普通输入单价 / 1000000
+ 缓存写入token × 写入单价 / 1000000
+ 缓存读取token × 读取单价 / 1000000
+ 输出token × 输出单价 / 1000000
同样完成10个任务,三种账怎么算
不使用缓存时,每次输入13000 token,输出500 token。一次费用是13000×2/1000000+500×10/1000000=0.0310元,10次合计0.3100元。
使用缓存时,假设首次把12000 token固定资料写入缓存,另外1000 token按普通输入计费。第一次为0.0300+0.0020+0.0050=0.0370元,反而高于无缓存的单次费用。
后续9次假设全部命中、缓存仍有效,每次为0.0024+0.0020+0.0050=0.0094元。合计是0.0370+9×0.0094=0.1216元。如果只调用一次,就不能拿这组10次的结果判断缓存是否划算。
| 场景 | 已计费尝试数 | 完成任务数 | 总费用,元 | 每完成一项,元 |
|---|---|---|---|---|
| 不使用缓存 | 10 | 10 | 0.3100 | 0.03100 |
| 首次写入,后9次命中 | 10 | 10 | 0.1216 | 0.01216 |
| 同上,另有一次已计费失败尝试 | 11 | 10 | 0.1270 | 0.01270 |
第三行假设额外失败尝试读取12000 token缓存、输入1000 token,已经生成100 token后才被判断为不合格。它的费用是0.0024+0.0020+0.0010=0.0054元。因此不能把“最终只留下10份摘要”误当成“只产生10次费用”。
失败是否计费、如何计费,要看服务规则和usage记录。这里演示的是已经产生计费用量的失败尝试,不是所有网络错误都会产生同样费用。
时间戳为什么可能影响缓存
Anthropic的《Tokenomics on AWS》课程约37分钟处,展示了一个每次都把长资料按全价输入计算的案例:变化的时间戳放在提示开头,而且没有标记缓存。它同时涉及输入排列和缓存配置,不能简化成“把时间戳移走就一定省钱”。
不利于复用相同前缀的排列:
[每次变化的时间戳] [固定规则] [固定资料] [本次问题]
便于组织稳定前缀的排列:
[固定规则] [固定资料] [每次变化的时间戳] [本次问题]
对于按相同前缀匹配的缓存机制,稳定内容放在前面有助于复用。能否真正命中,还取决于服务支持、缓存设置、最小长度、有效期和实际输入是否相同。切换模型或路由也可能失去原有缓存,需要结合新单价、命中情况和任务结果重新算账。
用Python复算这三笔账
下面只做本地计算,不发送API请求。单价单位仍为元/百万token,四个输入桶互不重叠。修改单价时,应先按所用服务的usage口径拆好各类token。
from decimal import Decimal as D
prices = tuple(map(D, ("2", "2.5", "0.2", "10")))
def fee(ordinary, write, read, output):
return sum(D(n) * p for n, p in
zip((ordinary, write, read, output), prices)) / D(1000000)
uncached = 10 * fee(13000, 0, 0, 500)
cached = fee(1000, 12000, 0, 500) + 9 * fee(1000, 0, 12000, 500)
with_retry = cached + fee(1000, 0, 12000, 100)
for name, total in (("uncached", uncached),
("cached", cached), ("with_retry", with_retry)):
print(name, f"{total:.4f}", f"{total / 10:.5f}")
这个假设算例的输出依次为:uncached 0.3100 0.03100、cached 0.1216 0.01216、with_retry 0.1270 0.01270。每行最后一项都是每个完成任务的费用;缓存组是否划算,仍取决于真实命中次数和对应单价。
把算例换成自己的账
每次尝试保存任务编号、尝试编号、模型与渠道、各类计费token、适用单价、是否成功。重新发送完整上下文时,要按这一请求实际报告的输入统计,不能只记录新增加的一句话。
先按尝试汇总费用,再按任务汇总成功数。比较不同方案时,使用同一组输入和同一套结果要求;某个方案便宜但摘要不合格,后续人工修订和再次调用都可能改变选择。
上面只是token费用模型。工具调用、文件存储或其他独立收费项如果存在,应另列一项。判断哪个方案更省,要用同口径总费用除以真正完成的任务数,而不是停在价目表里最小的那个数字上。
参考文档:AWS官方《Amazon Bedrock提示缓存》;课程案例:Anthropic《Tokenomics on AWS》,约37分钟。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2301_76711398/article/details/169357413




