先看现象。调用流式接口时加了 stream=True,首字延迟仍是 8 秒,和不开完全一样,抓包发现客户端在等整个响应结束,代码里最后一行用的是 response.text。
把日志和配置对完,能解释这个现象的基本就这几处。取 text 或 json 会强制读完整段。少数情况下是iter_lines 有默认缓冲 需要指定 chunk_size。
不容易想到的是,中间层开了 gzip 数据攒够才解压。
还有一种情况,连接池复用了上一次没读完的响应。
先改成逐行迭代并打印首包时间
python -c "import time,requests;t=time.time();r=requests.post('https://api.openai.com/v1/chat/completions',headers={'Authorization':'Bearer $KEY'},json={'model':'gpt-4o-mini','stream':True,'messages':[{'role':'user','content':'hi'}]},stream=True);print(time.time()-t)"
控制读取粒度并只看首条增量
python stream_client.py --chunk-size 1 --show-first-token
随后关掉压缩再测一次首包
curl -N https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d @req.json
末了用上下文管理器确保响应及时关闭
python -c "print('use context manager')"
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
恢复的判定其实很直接。首包时间降到 1 秒以内,回调能实时打印每一段,连接池里没有悬挂响应。
开了 stream 只是不立即下载全部内容,取 text 等于白开,读取方式要一起改。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
