自己接 AI 流式接口,先把 SSE 事件拼完整
自己接 AI 的 HTTP 流式输出时,如果代码是“收到一块字节,立刻 decode,再 json.loads”,先检查一下分块处理。一次读取可能停在半个中文字符中间,也可能只读到半条事件;一次读到好几条事件也正常。
这里做了个离线回放脚本,把输入故意拆成 每次 1 字节,再组回完整 SSE 事件。Python 3.9+,只用标准库,不需要网络或 API key。
如果你用的是官方 SDK 已经解析好的类型化事件,直接处理 SDK 事件就行。这份材料适合自己接 HTTP body、写代理或排查分块问题时对照。
解压后先跑这几条
python -m zipfile -e sse-replay-kit.zip sse-replay-kit
cd sse-replay-kit
python sse_events.py demo.sse --chunk-size 1
python -m unittest -v test_sse_events.py 样例里有两个本地构造的事件,第一个借用了 response.output_text.delta 这个事件名,只保留 type 和 delta 演示组装,不是完整 API 响应格式,也不是实际抓包:
event: response.output_text.delta
data: {"type":"response.output_text.delta","delta":"你好"}
data: 第一行
data: 第二行
文件末尾保留了结束第二条事件所需的空行。运行后应当输出两条 JSON 记录:第一条的 data 是完整的 JSON 字符串,第二条的 data 是 第一行\n第二行。下面把实际回放输出里的字段展开排版,便于看清内容:
本地从 ZIP 解压后跑过:12 项测试通过,覆盖中文逐字节拆分、CR/LF/CRLF、多条 data、空内容事件、BOM 和截断等情况。这是固定材料的解析测试,没有调用模型。
解析顺序别颠倒
body 字节碎片 → 增量 UTF-8 解码 → 按行处理 → 空行组成完整 SSE 事件
↓
按业务类型决定是否解析 JSON SSE 的 data 可以是普通文本,不要求是 JSON。样例第二条就是用来提醒这一点:即使 SSE 事件已经完整,对它调用 json.loads 仍会报错。
脚本中的 events(chunks) 接受 bytes 迭代器。下面这段可在解压目录的 Bash 里直接运行,展示完整事件之后再读取 JSON 字段:
python - <<'PY'
import json
from pathlib import Path
from sse_events import events
raw = Path("demo.sse").read_bytes()
chunks = (raw[i:i+1] for i in range(len(raw)))
for event in events(chunks):
if event["event"] == "response.output_text.delta":
payload = json.loads(event["data"])
print(payload["delta"])
PY 预期只打印 你好。这里先筛选了样例中约定为 JSON 的事件类型。换成自己的服务时,要用该端点真实的事件名、字段和类型约定,不能把这个简化样例原样当接入代码。
几种结果分别意味着什么
| 现象 | 该怎么判断 |
|---|---|
data:\n\n 得到一个空字符串事件 | 合法,不能因为内容为空就漏掉它 |
文件只有 data: hello\n,没有结束空行 | 不输出这条残留事件;EOF 不能帮它补齐 |
读到 [DONE] | 本脚本当普通 data;通用 SSE 没有规定这个终止标记 |
UnicodeDecodeError | 原始 UTF-8 损坏或末尾字节残缺;合法中文仅仅跨块不会触发它 |
SSE 能组装,但 json.loads 报错 | 回到具体事件的内容格式检查,不能靠 SSE 完整来证明 JSON 合法 |
WHATWG 的 SSE 规则允许 CRLF、LF、CR 行尾,多条 data 用换行连接,空行才派发;末尾未结束的事件丢弃。这个小脚本只做其中的 event/data 组装,忽略 id、retry,没有连接、重连、超时和大小限制。坏 UTF-8 选择直接报错,也比浏览器用替代字符处理更严格。
另外,连接结束不代表模型任务成功。OpenAI Responses 当前有自己的生命周期事件,其他端点也有各自约定;要按对应接口判断完成或失败。
来源:WHATWG《HTML Living Standard》SSE 章节(页面更新日期 2026-10-20);OpenAI《Streaming API responses》(2026-10-22 核对当前文档)。