Skip to content

批量任务别再同步调 API,Batch 接口直接打五折 ​

上周要给几千条用户反馈做分类。同步调 /v1/chat/completions,跑到一半撞了限流,账单还翻倍。

后来换成 Batch API(批量接口)。同样的活,钱直接省一半。

规则很简单:把一堆请求打包成一个 JSONL 文件上传,OpenAI 在后台慢慢跑,24 小时内给结果。代价是输入和输出 token 都打五折(价格 2026-10-09 从官方 pricing 页核实)。我的反馈分类是离线任务,等几个小时完全无所谓。

什么样的任务适合丢进去 ​

判断标准就一条:这次调用不需要立刻拿到结果。

数据标注、评测集打分、语料清洗、文档摘要,全是典型场景。反过来,聊天机器人、搜索补全这种用户在线等的功能,用不了它。

有个容易忽略的用法:构建评测集。我建议每次改 prompt 之前,把新旧两版各跑一遍批量评测,对比分数再决定要不要上线。这个场景不省这五折,评测跑多了心疼钱。

三个硬性限制 ​

先说清楚边界,免得写完代码才发现不合适。

一个批次最多 50,000 条请求,文件最大 200 MB。

完成窗口目前只能填 24h,没有别的选项。

支持的接口有限:/v1/responses、/v1/chat/completions、/v1/embeddings、/v1/completions、/v1/moderations、图像生成和编辑,还有视频。以上数字 2026-10-09 从官方 API reference 核实。

大部分批量任务塞得进这三条线。超了就拆文件,一个批次拆两个。

完整流程 ​

分四步:准备 JSONL、上传、创建批次、轮询取结果。

先写 JSONL。每个请求一行 JSON,带自定义的 custom_id(方便回头对号入座):

json
{"custom_id": "fb-0001", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "把这条反馈归类:bug/建议/咨询/其他。内容:搜索结果排序不对"}]}}

然后上传。用 Files API,purpose 必须是 batch:

python
from openai import OpenAI

client = OpenAI()
f = client.files.create(file=open("batch_input.jsonl", "rb"), purpose="batch")

上传完拿文件 ID 创建批次:

python
batch = client.batches.create(
    input_file_id=f.id,
    endpoint="/v1/chat/completions",
    completion_window="24h",
)
print(batch.id)

最后轮询状态,完成后下载输出文件:

python
import time

while True:
    b = client.batches.retrieve(batch.id)
    if b.status in ("completed", "failed", "expired"):
        break
    time.sleep(60)

out = client.files.content(b.output_file_id)
out.write_to_file("batch_output.jsonl")

输出文件里每行带原样的 custom_id 和模型的响应,按它回写数据库就行。

我踩的两个坑 ​

第一个坑:批次不是全成全败。50,000 条里跑挂了 300 条,批次状态照样是 completed。

失败的请求单独写进 error_file_id 指向的文件。我第一次跑完直接把输出文件当全量结果入库,丢了那 300 条数据,第二天对账才发现。

现在我的下载逻辑是两个文件都拉。error 文件有内容就报警。

第二个坑:注意 expired 状态。批次超过 24 小时没跑完会过期,没执行完的部分作废。

我用 gpt-4o-mini 跑几万条短分类,实际半小时就完了,从来没碰见过过期。但如果你塞大输出、长上下文,或者赶上高峰期排队,就要盯着这个状态,过期了拆小批次重提。

省多少钱,算一笔账 ​

以 gpt-4o-mini 为例,标准价输入 $0.15、输出 $0.60 每百万 token,Batch 价是输入 $0.075、输出 $0.30(2026-10-09 从 pricing 页核实)。10 亿输入 token 的标注任务,同步调要 $150,批量只要 $75。

跑批时的实际速度也超出预期。我那次 3,000 条、每条几百 token 的分类,提交后 25 分钟拿到结果,远不到 24 小时的上限。也就是说,很多「我以为要等一整天」的任务,其实批量和同步的体感差距只有一个午休。

唯一要注意的是 prompt caching(提示缓存)和批量折扣能否叠加的问题。我建议拿一小批任务分别实测账单,别只看文档,价格和折扣规则这种东西变动比代码频繁得多。

下一步 ​

把你手里某个周期性跑的脚本找出来,改成批量版,跑一次对一下账单。改动量不大,也就是把 client.chat.completions.create 的参数挪进 JSONL 里。

最近更新