杰瑞0915头像
AI API费用怎么算?把输入、输出、缓存和重试放进一张账封面图

AI API费用怎么算?把输入、输出、缓存和重试放进一张账

  比较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次的结果判断缓存是否划算。

场景已计费尝试数完成任务数总费用,元每完成一项,元
不使用缓存10100.31000.03100
首次写入,后9次命中10100.12160.01216
同上,另有一次已计费失败尝试11100.12700.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

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--