事情本身不复杂,线索都在日志里。openai 1.55 的 responses.stream 里循环只打印出 response.created 一条事件,后面 output_text 的增量一条都没收到,最后停在 response.in_progress,同一个 key 换 chat.completions 流式又完全正常。

第一反应是「增量文本挂在事件对象的 delta 字段上,不在 content 里」,验证下来不成立。

原因不止一个,得分开看。代码还在判断 choices[0].delta.content,这是 chat 的字段,responses 的事件名完全不同。另一种情况是SDK 版本低于 1.40,不认识 response.output_text.delta 这类事件。

不容易想到的是,中间网关把 text/event-stream 缓冲成一整包,增量被合并到结束才吐。

先把所有事件类型完整打出来看一遍

python -c "from openai import OpenAI;[print(e.type) for e in OpenAI().responses.stream(model='gpt-4o-mini',input='hi')]"

只取 output_text.delta 的 delta 字段拼接

python -c "from openai import OpenAI;print(''.join(e.delta for e in OpenAI().responses.stream(model='gpt-4o-mini',input='hi') if e.type=='response.output_text.delta'))"

再往下用 curl 直连看原始 SSE 帧的字段名

curl -N --no-buffer https://api.openai.com/v1/responses -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"model":"gpt-4o-mini","input":"hi","stream":true}'

末了关掉代理层缓冲后重跑同一条命令

curl -N --no-buffer -H "Accept: text/event-stream" https://api.openai.com/v1/responses -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"model":"gpt-4o-mini","input":"hi","stream":true}' | head -40

怎么算真的好了,看的是同一批现象。控制台按行滚出多条 response.output_text.delta,拼出来的整句与一次性非流式请求的 output 文本一致,结束事件是 response.completed。

responses 的事件是铺平的 JSON 而不是 chat 那种嵌套 delta,解析层最好先按 type 做一次白名单过滤,未知事件直接丢,别让 KeyError 把整个流打断。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189