报错是这么冒出来的。自建网关统计 gpt-4o 消耗,日志里 completion_tokens 是 380,后台账单显示输出 512,按天累计少算 20%,报表整体偏低。
中间走过弯路,把「被截断的请求按已收到内容估算,没取服务端返回的 usage」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。流式响应的 usage 只出现在最后一个 chunk,中途记的是增量条数。也可能是推理模型的思考 token 计入输出,但不在自己数的字段里。
还有一种情况,缓存命中的输入按折扣价,输出仍全价,两列混在一起算。
上来先在流式请求里打开 usage 统计
python -c "from openai import OpenAI;print([c.usage for c in OpenAI().chat.completions.create(model='gpt-4o-mini',messages=[{'role':'user','content':'hi'}],stream=True,stream_options={'include_usage':True})][-1])"
再往下按落库的原始 usage 求和而不是自己数
python -c "import json;print(sum(json.loads(l)['usage']['completion_tokens'] for l in open('usage.jsonl',encoding='utf-8')))"
手算一次单价与 token 的乘积核对
python -c "print(round(2.5/1e6*512,5))"
剩下的就是用账单接口做一次日汇总比对
curl -s "https://api.openai.com/v1/organization/costs?start_time=1730000000" -H "Authorization: Bearer $OPENAI_API_KEY" | jq '.data[0].results[].amount.value'
别只看报错消失,验证要多做一步。自建日志的 completion_tokens 合计与账单输出相差小于 1%,流式与非流式请求都能取到 usage 字段。
缓存折扣只作用于输入侧,把输出也打折会让成本报表长期偏低,两列必须分开算。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
