验证流式输出时 curl 加 -N 能一路收到 data 块,换成 SDK 开 stream=True 直接 400,提示 stream_options 字段非法,服务是自建兼容网关。
原因不止一个,得分开看。SDK 在流式时会自动追加 stream_options,网关不认;SDK 发送 Accept 为 text/event-stream,网关按普通 JSON 处理;超时设置不同,流式长连接被客户端先掐断;重试逻辑对已开始输出的流再次发起,产生重复请求。
上来先看 SDK 加的参数能不能手动去掉
python -c "import openai;c=openai.OpenAI(base_url='http://127.0.0.1:8000/v1',api_key='x');print(c.base_url)"
接着用 curl 复刻 stream 参数对比
curl -sS -N http://127.0.0.1:8000/v1/chat/completions -H 'content-type: application/json' -d '{"model":"qwen2.5-7b","stream":true,"messages":[{"role":"user","content":"hi"}]}'
随后关掉自动重试避免重复流
python -c "import openai;c=openai.OpenAI(base_url='http://127.0.0.1:8000/v1',api_key='x',max_retries=0);print('ok')"
剩下的就是确认网关对 SSE 的分块转发设置
grep -rn proxy_buffering /etc/nginx/
排查用的命令都是临时敲的,没有写成脚本,事后才整理。
手上没有现成的复现脚本,就照着线上请求手工拼了一个。
别只看报错消失,验证要多做一步。SDK 流式请求返回 200 并能逐块打印内容,与 curl 的输出块数量一致,400 不再出现。
补一句。兼容网关通常只实现主流程,SDK 自带的附加参数最容易踩雷,先用 curl 定基线再怀疑客户端。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
