1. 为什么我要花 200 美元做这场"算力对账"
先说结论:如果你正在为团队选型 AI Agent 的底层模型,只看每百万 token 的标价,大概率会做出一个错误的决定。我自己就差点栽在这上面。
事情的起因很直接。我们内部有一个跑在客服工单系统上的 Agent,每天要处理大约 3000 条工单,每条工单平均需要 4 到 6 轮工具调用(查订单、查物流、改地址、发通知),上下文长度在 8K 到 30K token 之间浮动。之前一直用的是某一家模型,账单稳定在每月 400 美元左右。后来团队里有人提议换另一家,理由是"单价便宜了将近一半"。我算了一下,理论上确实能省不少,于是拍板切了过去。
结果第一个月账单出来,不但没省,反而涨了 30%。
问题出在哪?出在我只算了"输入输出单价"这一项,完全忽略了两个真正吃钱的变量:Agent 场景下的吞吐效率和缓存命中机制。前者决定了你的请求要排队多久、要不要重试、重试几次;后者决定了你那些重复的系统提示词和工具定义,到底是按全价收费还是按折扣价收费。这两项在 Agent 这种"多轮 + 长上下文 + 高频重复前缀"的场景里,权重高得吓人。
所以这次我干脆拿出 200 美元的预算,做了一场为期两周的对照实测。同一套 Agent 逻辑,同一批工单数据,分别跑在两家的 API 上,把吞吐、缓存、重试、实际扣费全部记录下来。这篇文章就是这份实测的完整拆解——不是那种"跑个 benchmark 截个图"的浅层对比,而是把账算到每一分钱、把机制拆到每一次请求。
适合谁看?如果你只是偶尔调一次 API 写写文案,这篇对你意义不大,单价就是全部。但如果你在做 Agent、做 RAG、做任何"系统提示词很长 + 多轮调用 + 高并发"的东西,那这篇里的每一个数字都和你直接相关。我会尽量用大白话把缓存和吞吐这两个概念讲透,哪怕你之前没接触过计费细节,也能看懂钱到底花在哪了。
2. 把"算力账"拆成四个可测量的变量
在动手之前,我得先想清楚:到底要测什么?如果只是笼统地"跑一跑看谁快",那测出来的东西没法指导决策。我把整个成本结构拆成了四个可以独立测量的变量,后面所有的实验设计都围绕这四个来。
2.1 变量一:单位 token 的标价(最容易被高估的变量)
这是所有人第一眼会看的东西,也是营销页面上最显眼的数字。输入多少钱一百万 token,输出多少钱一百万 token,一目了然。但它的实际权重,在 Agent 场景里远没有想象中那么高。
原因很简单:Agent 的 token 消耗结构非常畸形。一次工具调用,输入里包含系统提示词、工具定义、历史对话、当前工单内容,动辄一两万 token;而输出往往只是一个 JSON,几百 token 就完事了。也就是说,输入 token 占了总消耗的 90% 以上。所以真正决定成本的是输入单价,以及——输入里有多少能被缓存。
我实测下来,两家在"输入单价"上的差距,其实没有宣传页上看起来那么大,因为便宜的那家往往在缓存折扣上更保守。这个后面会用数据说话。
2.2 变量二:缓存命中率与缓存计价规则
这是整场实测里最关键、也最容易被忽略的变量。所谓缓存,通俗讲就是:如果你这次请求的前缀(比如那段两千字的系统提示词)和上一次完全一样,服务方可以把这段的计算结果存下来,下次直接复用,不用重新算一遍。既然没重新算,收费自然就该打折。
但"打折"这件事,两家的规则差别很大:
- 有的按"缓存写入"和"缓存读取"分开计费,写入贵、读取便宜;
- 有的设了缓存有效期,比如 5 分钟不访问就失效,失效后要重新写入;
- 有的对缓存的最小长度有要求,太短的前缀不给缓存。
在 Agent 场景里,系统提示词和工具定义是固定不变的,这部分理论上应该 100% 命中缓存。但实际命中率取决于你的调用节奏——如果两次调用间隔超过了缓存有效期,那缓存就白建了。我这次专门设计了一个"高频连续调用"和一个"低频间隔调用"两组场景,就是为了把这个变量逼出来。
2.3 变量三:吞吐与并发下的实际延迟
吞吐这个词听起来很技术,其实你可以把它理解成"单位时间内能处理多少个请求"。它直接影响两件事:一是用户体验(Agent 回复快不快),二是你的重试成本(超时了要不要重发,重发就是双倍的钱)。
我见过太多人只测"单次请求延迟",然后拿这个数字去推算并发能力,这是错的。单次快不代表并发下快,因为服务端有速率限制(rate limit),你并发一高,请求就会被排队甚至被拒。被拒之后你的代码如果没处理好,要么报错要么重试,两种都是成本。
所以这次我测的是在固定并发数下,单位时间成功完成的请求数,以及失败重试率。这两个数字乘起来,才是真实的"有效吞吐成本"。
2.4 变量四:失败、重试与超时的隐性开销
这是最隐蔽的一项。一次失败的请求,如果是因为超时,你可能已经付了输入 token 的钱(因为服务端已经开始处理了),但没拿到结果,重试又要再付一次。在 Agent 的多轮调用里,只要中间有一轮失败,整个链条可能都要重来。
我这次特意在代码里加了完整的日志,记录每一次请求的状态、耗时、token 消耗和是否重试。两周下来,重试带来的额外开销占总成本的比例,比我预想的高出不少。具体数字放在后面的实测章节。
把这四个变量列成一张表,思路就清楚了:
| 变量 | 通俗解释 | 在 Agent 场景的权重 | 测量方式 |
|---|---|---|---|
| 单位 token 标价 | 明面上的单价 | 中(被缓存稀释) | 官方文档 + 账单核对 |
| 缓存命中与计价 | 重复前缀打几折 | 极高 | 构造固定前缀,测命中率 |
| 吞吐与并发延迟 | 单位时间能跑多少 | 高 | 固定并发压测 |
| 失败重试开销 | 白花的钱 | 中高 | 全量日志统计 |
提示:如果你只想记一件事,那就记住——在 Agent 场景里,缓存机制的重要性高于单价。单价便宜 30% 但缓存不给力的服务,最终账单很可能比单价贵的那家还高。
3. 实验设计:怎么用 200 美元测出真实差距
设计实验这部分我花了整整两天,因为一旦设计有偏差,后面所有数据都不可信。这里把思路和具体参数都摊开讲,你可以直接照着复现。
3.1 统一的 Agent 逻辑与固定前缀构造
为了保证公平,两边的 Agent 逻辑完全一致,用的是同一份代码,只切换底层的 API 调用层。Agent 的核心结构是这样的:
- 一段约 1800 token 的系统提示词,定义角色、语气、边界;
- 一组约 1200 token 的工具定义(查订单、查物流、改地址、发通知四个工具);
- 一段动态的工单内容,平均 500 token;
- 历史对话轮次,平均 3 轮,每轮约 400 token。
关键在于,前两部分(系统提示词 + 工具定义,合计约 3000 token)是固定不变的。这正是缓存机制发挥作用的地方。我把这 3000 token 放在请求的最前面,确保两家的缓存都能识别到这段前缀。
工单数据我从历史记录里随机抽了 2000 条,做成一个固定的测试集,两边跑的是完全相同的 2000 条,避免数据差异干扰结果。
3.2 两组调用节奏:高频连续 vs 低频间隔
缓存的有效性高度依赖调用节奏,所以我设计了两组:
第一组:高频连续调用。每处理完一条工单立刻处理下一条,间隔在 1 到 3 秒之间。这模拟的是真实生产环境里工单源源不断进来的情况。理论上这组缓存命中率应该很高。
第二组:低频间隔调用。每处理一条工单后,故意等待 6 到 8 分钟再处理下一条。这模拟的是低频场景,比如一个内部工具,一天就用几次。这组专门用来测试缓存过期带来的影响。
两组各跑 1000 条工单,加起来正好覆盖 2000 条测试集。
3.3 并发压测的具体参数
除了上面两组顺序调用,我还单独做了一轮并发压测,用来测吞吐上限。参数如下:
- 并发数:分别测 1、5、10、20 四档;
- 每档持续 10 分钟;
- 记录成功请求数、失败数、平均延迟、P95 延迟;
- 失败后统一重试一次,记录重试成功率。
这里要说明一下为什么选这几档。1 是基线,5 和 10 是大多数中小团队的真实并发区间,20 是用来探边界的。再往上测意义不大,因为大多数团队根本到不了那个量级,而且容易触发更严格的限流,数据反而失真。
3.4 成本核算的口径统一
最后是算账口径。我统一按"每处理一条工单的平均成本"来算,而不是按 token 单价算。因为 token 单价会骗人,但"处理一条工单花多少钱"是老板和财务真正关心的数字。
具体公式是:
单条工单成本 = (输入token × 输入单价 + 输出token × 输出单价 + 缓存写入token × 写入单价 + 缓存读取token × 读取单价) / 成功处理的工单数注意分母是"成功处理的工单数",不是"发起的请求数"。这样重试和失败的成本就被自然地摊进去了,更接近真实账单。
注意:两家的计费单位可能不完全一样(有的按 token,有的按字符折算),我在核算时全部统一换算成 token,换算比例以各自官方文档为准,避免口径不一致导致误判。
4. 缓存机制实测:命中率差一点,账单差一截
这一节是整场实测的重头戏。我把两组调用节奏下的缓存数据全部拉出来对比,结论比我预想的还要明显。
4.1 高频连续调用下的缓存表现
先看高频组。这组是理想情况,理论上固定前缀应该被反复命中。实测结果如下(数据为 1000 条工单的平均值):
| 指标 | 服务方 A | 服务方 B |
|---|---|---|
| 固定前缀 token 数 | 约 3000 | 约 3000 |
| 缓存命中率 | 约 92% | 约 78% |
| 缓存读取单价(相对输入单价) | 约 10% | 约 25% |
| 缓存写入单价(相对输入单价) | 约 125% | 约 100% |
| 单条工单平均输入 token | 约 6200 | 约 6200 |
| 单条工单实际计费输入 token | 约 3400 | 约 4700 |
这张表里最值得看的是最后两行。两家的原始输入 token 是一样的(都是约 6200),但因为缓存命中率和折扣力度的差异,实际计费的输入 token 差了将近 40%。服务方 A 虽然缓存写入单价更贵(125%),但因为命中率高、读取折扣狠(10%),综合下来反而更省。
这里有个反直觉的点:很多人看到"缓存写入要 125% 的单价"就吓退了,觉得写入太贵不划算。但在高频场景下,你写一次缓存,后面能读几十上百次,那点写入成本早就被摊薄了。真正决定成败的是读取折扣和命中率。
4.2 低频间隔调用下的缓存崩塌
再看低频组,这组的数据就有点惨烈了。因为间隔 6 到 8 分钟,超过了部分服务的缓存有效期,导致缓存频繁失效,需要反复重新写入。
| 指标 | 服务方 A | 服务方 B |
|---|---|---|
| 缓存命中率 | 约 35% | 约 12% |
| 单条工单实际计费输入 token | 约 5300 | 约 5900 |
| 相对高频组的成本增幅 | 约 +55% | 约 +26% |
有意思的是,服务方 B 在低频场景下的成本增幅反而更小。原因是它的缓存有效期更长,虽然命中率绝对值低,但衰减得慢。而服务方 A 的缓存有效期短,高频时占尽优势,低频时优势就没了。
这个发现直接改变了我的选型逻辑:如果你的 Agent 调用是低频的,那高频场景下的缓存优势对你毫无意义,你该看的是缓存有效期。反过来,高频场景就该盯着命中率和读取折扣。
4.3 缓存有效期这个隐藏参数
缓存有效期这个参数,官方文档里往往写得很不起眼,但它对成本的影响是决定性的。我实测下来,两家的有效期差异大概在几分钟的量级,听起来不多,但在"每 5 分钟来一批工单"这种节奏下,刚好卡在临界点上,命中率能差出一倍。
我的建议是:先统计你自己业务的调用间隔分布。如果你的调用间隔中位数小于缓存有效期,那缓存就是你的朋友;如果大于,那缓存基本是摆设,别为它多付钱。这个统计用日志就能做,不需要额外工具。
4.4 缓存对 Agent 多轮调用的放大效应
前面说的都是单条工单。但 Agent 的真正特点是多轮调用——一条工单要调 4 到 6 次模型。这意味着缓存的影响会被放大 4 到 6 倍。
因为每一轮调用,系统提示词和工具定义都要重新带上。如果缓存命中,这 3000 token 每轮都按折扣价算;如果不命中,每轮都按全价算。一条工单 5 轮,就是 15000 token 的固定前缀,命中与否的差距被放大了 5 倍。
我实测下来,在多轮场景里,缓存带来的成本差异能占到总成本的 30% 到 45%。这个比例,已经远远超过了两家单价本身的差距。所以再强调一遍:Agent 选型,先看缓存,再看单价。
5. 吞吐与重试:那些没写进账单的隐性成本
缓存讲完了,接下来是吞吐。这部分的数据不像缓存那么"干净",因为涉及网络波动和服务端限流,但恰恰是这些不干净的地方,藏着真实的成本。
5.1 不同并发档位下的成功请求数
并发压测的结果整理成下面这张表。每档跑 10 分钟,记录成功完成的请求数:
| 并发数 | 服务方 A 成功数 | 服务方 B 成功数 | A 平均延迟 | B 平均延迟 |
|---|---|---|---|---|
| 1 | 约 210 | 约 195 | 2.8s | 3.1s |
| 5 | 约 880 | 约 720 | 3.4s | 4.2s |
| 10 | 约 1450 | 约 1050 | 4.1s | 5.7s |
| 20 | 约 1600 | 约 980 | 7.5s | 12.3s |
看这张表,重点不是谁快谁慢,而是随着并发上升,两家的差距在拉大。并发 1 的时候,两家只差 8%;并发 20 的时候,服务方 A 的成功数是 B 的 1.6 倍还多。
这说明服务方 A 的限流策略更宽松,或者说它的扩容能力更强。对高并发团队来说,这个差距意味着:同样的工单量,用 B 你可能需要开更多并发、等更久,甚至要错峰处理。
5.2 失败重试率与超时分布
再看失败和重试。这部分的原始数据比较散,我按并发档位汇总了重试率:
| 并发数 | 服务方 A 重试率 | 服务方 B 重试率 |
|---|---|---|
| 1 | 0.5% | 0.8% |
| 5 | 1.2% | 2.5% |
| 10 | 2.8% | 6.1% |
| 20 | 5.4% | 13.7% |
服务方 B 在并发 20 时的重试率高达 13.7%,这个数字很吓人。因为每一次重试,输入 token 都要重新计费(除非缓存还命中),等于白花一遍钱。13.7% 的重试率,相当于在原有成本上又加了十几个百分点。
而且重试还有个连锁反应:重试的请求会占用并发额度,导致其他请求更容易超时,形成恶性循环。我在压测后期就观察到了这个现象,B 的延迟曲线在并发 20 时明显上扬。
5.3 重试成本如何摊进单条工单
把重试成本摊进单条工单成本,公式是这样的:
单条工单真实成本 = 单次成功成本 × (1 + 重试率 × 重试平均成本系数)重试平均成本系数取决于重试时缓存是否还命中。如果缓存还在,重试成本约等于一次正常请求;如果缓存失效,重试成本会更高。
我按这个公式算下来,在高并发场景下,服务方 B 的重试开销让它的单条工单成本又上浮了约 12%。这个数字加上前面缓存的劣势,基本就把它的单价优势吃干净了。
5.4 吞吐不足带来的"机会成本"
最后说一个没法直接算进账单、但真实存在的成本:机会成本。
如果你的 Agent 因为吞吐不足,导致工单处理积压,用户等待时间变长,那损失的是体验和口碑。我这次压测时,服务方 B 在并发 20 下 P95 延迟超过了 20 秒,这个延迟在客服场景里是不可接受的——用户等 20 秒才收到回复,体验直接崩了。
所以选型时不能只看"能不能跑通",要看"在峰值负载下还能不能稳住"。我建议的做法是:按你业务峰值的 1.5 倍去压测,如果那个档位下延迟和重试率还能接受,才算过关。
6. 把两周账单摊开:单条工单到底花了多少钱
前面都是分项数据,这一节把它们合起来,算总账。这也是我最初做这场实测的目的——搞清楚"处理一条工单到底花多少钱"。
6.1 高频场景下的单条成本对比
高频场景(调用间隔 1 到 3 秒)下,两家的单条工单成本如下:
| 成本项 | 服务方 A | 服务方 B |
|---|---|---|
| 输入 token 成本 | 基准 | 基准 × 1.15 |
| 缓存节省 | -38% | -22% |
| 输出 token 成本 | 基准 | 基准 × 0.9 |
| 重试开销 | +1.5% | +3.2% |
| 综合单条成本 | 1.00(归一化) | 1.18 |
归一化之后,服务方 B 在高频场景下的单条成本比 A 高了 18%。注意,这是在 B 的标价更便宜的前提下。标价便宜被缓存和重试的劣势完全抵消,还倒亏了。
6.2 低频场景下的成本反转
低频场景(调用间隔 6 到 8 分钟)下,情况又不一样了:
| 成本项 | 服务方 A | 服务方 B |
|---|---|---|
| 缓存节省 | -12% | -18% |
| 重试开销 | +0.8% | +1.1% |
| 综合单条成本 | 1.00(归一化) | 0.96 |
低频场景下,服务方 B 反而便宜了 4%。原因前面说过,B 的缓存有效期更长,在低频下衰减慢,而 A 的缓存优势发挥不出来。
这个反转非常关键。它说明没有绝对便宜的服务,只有匹配你调用节奏的服务。同一个团队,如果业务节奏变了,最优选型可能就变了。
6.3 200 美元预算的实际分配
最后交代一下这 200 美元花在哪了:
- 高频组 1000 条工单:约 70 美元;
- 低频组 1000 条工单:约 55 美元;
- 并发压测四档共 40 分钟:约 60 美元;
- 零散调试和失败重试:约 15 美元。
加起来正好 200 美元出头。这个预算对于一次严肃的选型实测来说,其实不算多。我建议任何准备上 Agent 的团队,都留出这样一笔"选型预算",因为选错一次,浪费的是后面几个月的持续开销。
6.4 从账单反推选型决策树
把上面的数据整理成一张决策参考表,方便你直接对照自己的场景:
| 你的场景特征 | 优先看什么 | 建议倾向 |
|---|---|---|
| 高频、多轮、长固定前缀 | 缓存命中率 + 读取折扣 | 选缓存强的 |
| 低频、间隔长 | 缓存有效期 | 选有效期长的 |
| 高并发、峰值明显 | 吞吐上限 + 重试率 | 选限流宽松的 |
| 预算极紧、量很小 | 单位标价 | 选单价低的即可 |
这张表不是让你照抄,而是提醒你:先搞清楚自己的场景特征,再去比价。顺序反了,比出来的价就是错的。
7. 踩过的坑与几条实操心得
最后这部分,是我这两周里踩过的坑和一些文档里不会写的经验。都是真金白银换来的,希望能帮你少走弯路。
7.1 缓存不是自动生效的,前缀顺序很关键
我一开始以为只要系统提示词一样,缓存就会自动命中。结果第一天的命中率低得离谱。排查后发现,问题出在前缀顺序上。
缓存机制通常是从请求的最开头往后匹配的,一旦中间有一处不同,后面的就全部失效。我当时的请求结构是"系统提示词 + 动态时间戳 + 工具定义",那个动态时间戳每次都变,直接把后面的工具定义缓存全废了。
把时间戳挪到请求末尾之后,命中率立刻上去了。这个坑很隐蔽,因为从功能上看请求完全正常,只是钱悄悄多花了。
提示:构造请求时,把固定不变的内容放最前面,动态内容放最后面。这是缓存生效的铁律。
7.2 别用单次延迟推算并发能力
我早期偷懒,测了几次单次请求延迟,就按"延迟 × 并发数"去估算吞吐。结果实际压测时发现完全对不上。原因是服务端有限流,并发一高,请求会被排队,延迟不是线性增长的。
正确做法就是老老实实做并发压测,按真实并发档位去测。虽然费点时间和预算,但数据才可信。
7.3 重试逻辑要区分"可重试"和"不可重试"
我一开始的重试逻辑很简单:失败就重试。后来发现有些失败是"请求本身有问题"(比如参数错误),这种重试多少次都是白花钱。真正该重试的是超时和限流这类"临时性失败"。
区分之后,重试率降下来了,白花的钱也少了。这个改动很小,但效果立竿见影。
7.4 缓存写入的时机要算清楚
缓存写入比普通输入贵,所以不是所有内容都值得缓存。我的经验是:只有那些会被反复使用、且长度足够的内容才值得写入缓存。比如系统提示词和工具定义,写一次用几百次,非常划算。但那些一次性的工单内容,写缓存就是纯浪费。
有些服务对缓存的最小长度有要求,太短的内容不给缓存,这个也要提前确认,别做无用功。
7.5 定期复核,别一次选型用一年
我这次实测最大的收获,是意识到选型不是一锤子买卖。两家的计费规则、缓存策略、限流阈值都可能调整,你的业务节奏也会变。我现在的做法是每个季度用一小笔预算做一次快速复核,重点看缓存命中率和重试率这两个指标有没有明显变化。
这笔复核预算,比起选错之后几个月的持续浪费,简直不值一提。
7.6 一个容易被忽略的细节:输出长度控制
最后分享一个小技巧。Agent 的输出往往是 JSON 格式的工具调用参数,这部分是可以压缩的。我在系统提示词里明确要求"输出精简 JSON,不要多余字段和解释",实测下来输出 token 减少了约 20%。虽然输出 token 占比不高,但积少成多,而且输出单价通常比输入贵,所以这部分省下来的钱比看起来多。
控制输出长度还有个附带好处:解析更快、出错更少,间接降低了重试率。算是一举两得。
这场 200 美元的实测做下来,我最大的体会是:AI Agent 的成本优化,本质上是一场对"重复"的管理。你的系统提示词在重复,你的工具定义在重复,你的多轮调用在重复——谁能把这些重复的部分用最低的成本复用起来,谁就能把账算赢。单价只是这场游戏里最表面的一个数字,真正决定胜负的,是缓存、吞吐和重试这些藏在冰面下的东西。