SSE · 排错

AI API 流式输出中断:SSE、超时与客户端解析排查

更新日期:

流式请求可能先返回 HTTP 200,再在中途出现错误。因此“已经输出几句话”和“整条请求完成”是两个状态。先判断服务端是否发出结束事件,再区分模型输出上限、网络超时与客户端解析。

1. 保存最小复现信息

记录协议、模型 ID、请求时间、请求 ID、收到首个事件的时间,以及最后一个事件类型。不需要公开实际提示词或 Key。先用短消息复现,再与长会话比较。

2. 不同协议怎样结束?

协议 应核对的内容
OpenAI Chat Completions 流 delta、finish_reason,以及该接口的 [DONE] 终止标记
Anthropic Messages 流 内容块增量、message_delta、message_stop 或 error 事件
Gemini 流 该接口的 SSE 格式、候选内容和 finishReason;不能直接套用 OpenAI 解析器

有些 finish_reason 或 stop_reason 表示到达输出上限或转入工具调用,不是网络故障。不能仅靠连接关闭判断回答完整,也不能用 [DONE] 检查所有协议。

3. 网络分块不是完整 SSE 事件

一次读取可能只包含半个 UTF-8 字符,也可能包含多个事件。解析器需要保留跨块缓冲、按空行划分事件,并处理多行 data:。Node.js 示例见fetch 与 SSE 教程,其中包含可离线运行的解析演示。

如果 JSON 在某个读取块中解析失败,先检查是否把网络 chunk 错当成完整事件,不要立即判断服务端返回了损坏数据。

4. 区分代理缓冲与超时

现象 检查方向
等很久后一次显示整段 客户端是否流式读取、代理是否缓冲、响应是否为 SSE
总在接近同一时长停止 客户端总超时、代理读超时和服务端任务限制
只有某个 IDE 或桌面客户端失败 该进程的网络、代理和环境设置
只有长输出失败 输出上限、长时间连接与流内错误
已收到正文后出现错误事件 保留部分结果,将请求标记为未完成

如果是你自己的 Nginx 代理,分别核对流式路由的缓冲与读超时设置;不要把所有路由的超时无限调大。先确认链路中真正关闭连接的是哪个环节。

5. 中断后要不要自动重试?

先检查调用记录和响应状态。客户端没有读到结束标记,不等于服务端没有生成或计费。将未完成输出与完成输出区分;必要时让用户决定继续、重试或保留部分结果,避免静默重复任务。

预算核对可参考Token 计费说明,鉴权错误应按401 指南处理。