现场是这样的。周五下班前提交了 4 万条离线请求,选的是 24 小时完成窗口,周一回来看到 status=expired,只有三分之一进了 output_file,其余请求既没有报错也没有结果。

中间走过弯路,把「过期请求的输入 token 仍可能计费,折扣只对完成的部分生效」当成主因,改完现象没变。

这类报错背后常见的原因有几处,逐个排除就行。24 小时窗口按创建时间算硬上限,排队太久的请求直接作废;批次规模超过了队列消化能力,排到窗口结束还没轮到;客户端没保存 batch id,过期后无法判断哪些还需要补跑。

先查任务状态与请求计数

curl -s https://api.openai.com/v1/batches/batch_abc -H "Authorization: Bearer $OPENAI_API_KEY" | jq '{status,request_counts}'

然后把已完成的结果文件下载保底

curl -s https://api.openai.com/v1/files/$OUT/content -H "Authorization: Bearer $OPENAI_API_KEY" -o out.jsonl

接着统计已经拿到结果的 custom_id 数量

python -c "import json;print(len({json.loads(l)['custom_id'] for l in open('out.jsonl')}))"

剩余请求切成小批重新提交

python split_jsonl.py --input rest.jsonl --size 5000

怎么算真的好了,看的是同一批现象。新提交的小批次在窗口内全部变成 completed,request_counts.completed 等于提交条数,输出文件行数与输入去重后的 custom_id 数一致。

这里还有个坑。过期不是失败,接口不会给逐条错误,只能靠 custom_id 做差集补跑,所以提交前就得把批次清单落盘,别只留一个 batch id。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189