内容提要
本文介绍用 Python 标准库处理 Responses API 的 SSE 流式响应,实现增量渲染、超时与取消。核心是仅拼接 response.output_text.delta 事件,设置 30 秒网络超时,用户取消时停止读取并保留已得内容。取消不等于撤销工具动作,需幂等设计;常见错误包括密钥缺失、模型未开放、代理缓冲及线程强杀导致连接泄漏。
延伸解读
取消与超时的边界:网络保护不等于产品 SLA
文中把 30 秒 timeout 定位为网络保护,而非产品 SLA。这意味着它只防止连接无限挂起,不能替代对建连、首 token、总耗时的分别记录。生产环境应根据任务大小由服务端设上限,否则长任务可能被误判为失败。同时,取消是关闭本次 HTTP 读取,不等同于撤销已发出的外部工具动作,涉及发邮件、下单等副作用时,必须在工具端另设幂等键和确认点。
增量渲染的取舍:中间文本有价值,但不可直接落库
文章指出该模式适合聊天、长摘要、代码解释等中间文本也有价值的场景,但不适合把每个 token 直接写入不可逆业务记录,也不适合双向低延迟音频。工程化时应将原始事件与展示文本分开存储,并给事件加 request_id。用户取消后保存 partial 及原因,下次可让用户继续生成,而不是伪装成完整答案。界面还需知道回答是否完成,避免用户复制或点击操作按钮时误用未完成内容。
常见故障排查:认证、模型权限与代理缓冲
文中列出三类常见失败:环境变量为空导致认证失败,本例在发送前就报出可读错误;模型未向账号开放会返回 HTTP 4xx,应换成官方 Models 页可用的 ID;代理缓冲会让流式变成最后一次性输出,需检查反向代理的缓冲设置。另一个隐蔽错误是用线程强杀请求,资源未关闭会导致连接泄漏,with 块和明确返回能保证连接收尾。取消率突然升高可能是模型变慢,也可能是代理开始缓冲。
Q&A
如何用 Python 标准库处理 Responses API 的 SSE 流式响应?
使用 urllib.request 发起 POST 请求,设置 Accept: text/event-stream,然后逐行读取响应,解析以 'data:' 开头的行,将 JSON 事件中 type 为 response.output_text.delta 的 delta 字段拼接起来,即可实现增量渲染。
处理 SSE 流时,超时和取消应该怎么设计?
设置网络超时(如 30 秒)作为保护,但这不是产品 SLA。取消时停止读取并保留已得内容,保存 partial 及原因,以便用户后续继续生成。取消不等于撤销已发出的工具动作,需在工具端设计幂等键和确认点。
SSE 流式响应中常见的错误有哪些?
常见错误包括:环境变量为空导致认证失败;模型未向账号开放返回 HTTP 4xx;代理缓冲导致流式变成一次性输出;用线程强杀请求导致连接泄漏。应检查环境变量、模型 ID、代理缓冲设置,并使用 with 块确保连接关闭。
为什么取消 SSE 流不等于撤销工具动作?
取消只是关闭本次 HTTP 读取,已经发出的外部工具动作(如发邮件、下单、改数据库)不会因此撤销。因此必须在工具端另外设计幂等键和确认点,避免重复执行。
SSE 流式处理适合哪些场景?不适合哪些?
适合聊天、长摘要、代码解释等中间文本也有价值的场景。不适合把每个 token 直接写入不可逆业务记录,也不适合需要双向低延迟音频的实时通话。
工程化时,SSE 流式处理需要注意哪些产品细节?
增量文本不是最终答案,界面应知道回答是否完成;重连需带上已执行动作避免重复;事件流留存要限制期限并脱敏;至少记录创建、首片段、完成或取消原因、输出字符数和 HTTP 状态;取消率突然升高可能意味着模型变慢或代理缓冲。