事情本身不复杂,线索都在日志里。自研网关转发 OpenAI 的流式响应,Python 客户端逐行 json.loads 时偶尔抛 JSONDecodeError,原文 Expecting value: line 1 column 1 (char 0),把出错的那一行打出来只有一个冒号开头的注释。
第一反应是「一个事件被拆成多行 data 需要先拼接」,验证下来不成立。
排查方向其实有限,先把可能性排一排。冒号开头的注释行不是 JSON。少数情况下是data: 前缀没剥掉就直接解析。
少数情况下是空行被当成一条数据送进解析。
第一件事是把原始字节流落盘看真实行
curl -N https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d @req.json -o stream.txt
再往下按 SSE 规范过滤注释并拼接多行
python sse_parse.py --in stream.txt --skip-comment --join-multi
遇到 DONE 标记立即结束解析
python -c "print('break on [DONE]')"
补一条覆盖心跳行的单测
python -m pytest tests/test_sse.py -q
中途换过一次思路,把范围缩到最小的那一层,反而快了。
恢复的判定其实很直接。同一份流解析零异常,chunk 数与服务端日志一致,末尾能正常收到结束标记。
提醒一点。SSE 不是每行都是 JSON,注释、多行 data、空行都要处理,很多解析错误其实来自心跳。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
