AI / LLM

大模型 Batch API 打五折,算下来反而比实时调用更贵,成本复盘

1974 字约 7 分钟

摘要批量任务改用 Batch API 后可以享受五折,但输入中有 94% 是固定的系统提示词。这种情况下,不支持上下文缓存的 Batch 比实时调用贵了约 70%。

最近在给招聘监控项目处理 4 万多条历史岗位数据,需要用大模型把格式各异的招聘信息整理成统一的结构化画像。

即使单次调用的价格只有几厘,乘以 4 万之后,账单也不少。

模型厂商提供了 Batch API(离线批处理任务):把请求打包成 jsonl 文件上传,服务端承诺 24 小时内异步完成,输入和输出 Token 的单价都是五折。

什么是 Batch API?

它是 OpenAI、Anthropic、Google 等主流模型服务商提供的批量处理接口,适用于不要求实时返回的离线任务。服务商可以在算力空闲时调度这些任务,因此通常给出 50% 或更大的折扣,代价是延迟从几小时到 24 小时不等。

对于不急于获得结果的离线任务,五折的价格看起来很有吸引力,直觉上应该直接切换到 Batch,预算可以减半。

但在改造后台调度任务之前,我先按实际请求的 Token 结构算了一笔账,结果和直觉不一样。

被忽略的 94%

提取岗位画像时,发给模型的内容不只是几百字的岗位描述。

为了让模型输出结构严谨的 JSON,并把“资深后端”“Golang 架构师”等岗位准确归入统一的行业分类,每个请求开头都要带上一大段系统前缀:输出字段规范、JSON Schema 约束,以及一份几千行的岗位分类字典。

这些内容负责告诉模型“什么是三年经验”“什么是校招”。每次请求真正变化的,只是末尾几十到几百字的岗位详情。

我查看了单次请求的 Token 分布:平均每个请求有 11,400 个输入 Token,其中固定前缀占了 10,700 多个,比例达到 94%。

单次请求的 Token 结构
  • 固定前缀(约 94%): 统一的抽取规则、Schema 校验、完整的分类标准字典
  • 动态内容(约 6%): 当前岗位的标题、职责要求和公司字段
通俗比喻:全场五折的复印店,与只印一次模板的优惠

为什么五折的离线批处理会比平时的实时调用更贵? 假设要印 1000 份合同,每份的前 94 页都是完全相同的通用条款,只有最后 1 页是具体的甲方签字:

  • Batch API(全场五折):相当于复印店说“你把 1000 份合同都交给我,我给你打半价”。但店里每次都要把那 94 页通用条款重新印一遍,共印 1000 次;
  • 实时调用 + 前缀缓存:相当于复印店先把前 94 页做成固定模板,只印一次。之后 999 次直接复用模板,前 94 页只按一折收费,只有最后 1 页需要全价。

只要固定前缀足够长,“复用模板省下的钱”就会超过“整单打半价省下的钱”。

如果使用实时接口,各大厂商目前基本都支持上下文缓存(Context Caching):只要请求开头的内容保持一致,后续请求命中缓存后,前缀部分的输入单价通常只有原价的两折甚至更低。

而 Batch API 虽然标着五折,却不支持前缀缓存。

隐式缓存不稳定,改用显式缓存

在得出结论之前,我需要确认实时调用的缓存收益是真实的,而不只是理论上的。

最初使用的是厂商的隐式缓存,即服务端自动比对请求前缀。但在 1,000 条岗位的试跑中,命中情况很不稳定:总命中率只有 48% 左右,并且波动很大。开始时几个请求能命中 7,800 个 Token,跑着跑着就变成了 0。如果任务中途停顿几分钟,缓存甚至会失效。

隐式缓存与显式缓存的区别
  • 隐式缓存(Implicit Cache): 服务端根据近期请求自动识别相同的前缀,命中规则对开发者不透明,请求稍有波动或并发中断就可能失效;
  • 显式缓存(Explicit Cache): 开发者通过 API 主动声明“这段前缀在显存中保留 N 分钟”,前缀带有明确的缓存键,命中率高且稳定。

于是我把请求改成了显式缓存的模式:固定的 Schema 和分类体系单独抽出来,在末尾加上缓存声明;动态的岗位正文放在最后,前缀中不包含任何时间戳、随机 UUID 或批次 ID。

效果很明显:固定的 10,743 个 Token 在后续请求中几乎每次都能复用。在实际运行中,整批任务的综合缓存命中率达到了 93.8%。

此时比较的对象也发生了变化:不再是“原价与五折”的比较,而是**“全量五折”与“94% 的内容按两到三折计费、6% 按原价计费”之间的比较。**

重新计算成本

我把两种方案换算成每 1,000 条岗位的实际费用:

方案计费方式每千条实际开销
实时调用 + 显式缓存约 94% 的输入按缓存价计费,仅 6% 按原价计费0.81 元
Batch API100% 的输入统一打五折1.37 元

标着“五折”的 Batch API,实际花费比实时接口高出近 70%。

计算过程并不复杂。假设一个请求有 100 个 Token,其中 94 个是固定的 Prompt:

  • Batch 方案: 100 个 Token 全部按 50% 计费;
  • 实时缓存方案: 94 个 Token 按 10% 到 20% 的缓存价计费,只有 6 个动态 Token 按全价计费。

Batch 的五折看起来很诱人,但实时缓存方案中需要全价的部分非常少。

评估成本时不要只看折扣

评估大模型接口的成本时,不能只看标价上的折扣。应该先分析 Prompt 的结构:动态内容占多少,固定的规则、Few-shot 示例和知识库又占多少。

工程维护成本也需要考虑

成本差距已经足以排除 Batch 方案。工程维护的成本也让这个决定更加明确。

如果使用实时接口,代码可以直接沿用现有的消息队列、重试机制、并发控制和结果入库逻辑,几乎不需要额外的改动。

如果改用 Batch,就需要新建一套离线流程:写入本地文件,调用 API 上传,提交 Batch 任务,由 Worker 定时轮询状态,任务结束后下载结果文件,逐行反序列化,再按外部 ID 映射回数据库。这不仅要多花一两天的开发时间,结果返回的延迟也会更长。

那 Batch API 什么时候更合适?

Batch 并非没有价值。对于长文档的批量翻译、长篇小说摘要,或者每次输入都完全不同、没有公共前缀的离线评测任务,Batch 的五折优势就会体现出来。按照当时的计费公式推算,只有当请求的前缀缓存命中率低于 40% 时,Batch 才会比实时调用更划算。

最终的方案很简单:继续使用实时接口,加上显式前缀缓存,并将并发任务拆分为均匀的小批次持续发送。这样既能保证缓存的有效期,也能把账单压到较低的水平。

很多时候,云厂商在价格页面上用醒目字样标注的“五折”只是表面数字。对于依赖固定业务规范和复杂 Schema 的抽取任务,单价打折的效果通常不如提高缓存命中率。

评论