OpenAI Batch显示completed,按custom_id核对output和error
同时读取output与error,按唯一custom_id恢复对应关系,将HTTP失败、缺失记录和内容解析分别处理。
Batch已经显示 completed,下载的output文件却少了几行;应用按输入顺序拼接结果,缺失那几行的位置反而出现了其他回答。先检查 output_file_id 和 error_file_id,再用 custom_id 对账。
批次状态完成,不代表每条请求都成功,也不保证输出行顺序与输入相同。若用较短的响应数组直接与输入配对,可能错位;一些语言的向量循环或回收规则还会把缺失结果填成别人的回答。
两份文件都要检查
Batch对象有 output_file_id 时,读取成功结果文件;有 error_file_id 时,也读取错误文件。字段为空与下载失败需要分别记录,不能因为某个文件ID没有值就把整批结果当作正常空列表。
保留输入中每条请求的唯一 custom_id。结果中的这个字段负责把请求和响应关联起来,行号、文件顺序和内部 batch_req_* ID都不能替代它。
例如输入ID是 request-a、request-b、request-c,output先返回c再返回a,error包含b,这是一份可以按ID复原的结果。不能把output第二行直接标成b,也不能把两行响应循环使用来凑足三行。
对账先于业务解析
可以在已经下载的本地JSONL文件上建立结果表,不需要重新提交付费请求。对每一行先解析外层JSON并取出ID,记录它来自哪个文件、error、response.status_code 和请求关联信息,再进入具体端点的内容解析。
对账时至少检查重复ID、未知ID和缺失ID。同一ID同时出现在两份文件中,应作为冲突保留,而不是“后面的覆盖前面的”。结果行没有可用ID,或者外层JSON本身损坏时,保留行位置和错误,不能猜它对应哪个输入。
输入ID全集应等于正常识别的结果ID全集,且每个输入只对应一条结果。不能只比较总行数:重复一条、漏掉一条时,行数仍可能相同。批次中的完成、失败和总计也可参与核对,但最终还要看逐项结果,不能用面板统计覆盖已下载的错误内容。
外层JSONL有效,内容仍可能不能用
JSONL一行能解析,说明响应封套有效,不代表模型的业务内容符合预期。Chat Completions的结构化内容、Responses的输出、embedding数组应按各自接口读取,不能给所有端点套同一个 choices[0].message.content 路径。
检查HTTP状态和逐项错误之后,再判断业务输出是否完整、是否拒绝、是否符合字段与类型约束。error: null 也不能替代响应状态检查;例如错误文件里出现状态0、空body时,应保留为无法确认成功的结果,不要改写成一个假想的HTTP500。
对于要求JSON的聊天内容,外层一行合法而里面的字符串是空值或不完整JSON,属于内容解析失败。应该只给这个ID标记失败,保留其他已核对结果。不要用正则“修好”缺失值后当成成功。具体解析与字段验证可以对照JSON语法、形状和流式完成检查。
只重试已经查明的失败项
先恢复ID对应关系,再决定重试范围。鉴权、模型访问、端点或输入不合格的问题要先修正;暂时性的请求失败也应有限重试。缺失ID尚未查清时,先核对文件是否下载完整和批次对象状态,不要直接重跑整批。
重试台账应关联原批次、原ID和新尝试,保留原成功结果,避免重复下游写入。若状态实际是 expired 或 cancelled,按那种状态重新核对已完成和未完成请求,不能与 completed 混在一起解释。
验收除了“有一张结果表”,还要确认每个输入ID有唯一、可追溯的状态,成功内容来自自己的响应,解析失败没有被填成别人的答案。Agent下一轮历史中缺工具结果则是另一种ID配对,可以按工具请求与结果的连续分组检查,不能拿Batch文件的排序规则代替消息协议。


