用 AI 聊天时你一定见过那个画面:回答不是「唰」地整段跳出来,而是像有人在打字一样,一个字一个字往外蹦。很多人以为这是故意做的打字机特效——其实不是。这叫流式输出(Streaming),是模型和接口层面的真实工作方式。这篇就把它的原理、怎么开启、以及什么时候该关掉,一次讲清楚。
先搞懂:非流式和流式,差在哪
一次对话请求,模型其实分两步干活:先把你的问题读一遍,再一个字一个字地「预测」下一个词。关键在于——第二步本来就是一个个词生成的,模型并没有「整段想好、再一次说完」的能力。所谓非流式,只是服务端替你把词都攒齐了才交给你。
- 非流式(stream 为 false):等所有内容生成完,攒成一个完整答案再一次性返回。等待期间,你屏幕上什么都没有。
- 流式(stream 为 true):每生成一小段就立刻推给你。你不用等它想完,可以边看边读。
- 两者的总耗时几乎一样,差的是「第一个字出现的时间」:非流式可能要 8 秒才见到结果,流式 1 秒内就开始蹦字了。
类比:非流式像点一份现炒的菜,厨师全部做完才端上桌;流式像自助餐,炒好一盘就先端一盘。总时长一样,但后者你不用饿着等。
怎么在 API 里开流式:只需一个 stream 参数
接口地址是 https://api.aigcbreeze.cn/v1,OpenAI 兼容格式。开流式不用换接口,加一个参数就行:"stream": true。
curl https://api.aigcbreeze.cn/v1/chat/completions \
-H "Authorization: Bearer sk-你的密钥" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"stream": true,
"messages": [{"role": "user", "content": "用三句话解释什么是流式输出"}]
}'
开启之后,返回的就不再是一份完整 JSON,而是一串 SSE(Server-Sent Events)事件流。拆开看,每个小包长这样:
data: {"choices":[{"delta":{"content":"流"}}]}
data: {"choices":[{"delta":{"content":"式"}}]}
data: [DONE]
- 字段名从 message 变成了 delta:非流式返回完整内容,流式只返回「这一包新增的那点字」,需要你自己拼接。
- 每条以 data: 开头、两条之间空一行;最后一包固定是 data: [DONE],收到它就说明说完了。
- 计费按最终生成的 token 总量算,开不开流式不影响价格,只是把「一次返回」拆成了「很多次返回」。
顺带说一句用量统计:如果需要在结尾拿到本次消耗的 token 数,可以在请求里加上 "stream_options": {"include_usage": true},用量会随最后一个数据包一起返回;不支持这个字段的接口会直接忽略它,不会报错。
开了流式却没效果?多半是这三处
代码里明明写了流式开关,界面上却还是转半天圈才一次性出结果,常见原因就这三个:
- 链路中间有反向代理在缓冲。Nginx、CDN 这类组件默认会把响应攒够一批再转发。要关掉缓冲,例如在 Nginx 里配置 proxy_buffering off;,或给响应加上 X-Accel-Buffering: no 响应头。
- 客户端把流重新拼完才渲染。有些库默认帮你把流「收尾」成一个完整字符串再显示,等于白开,去客户端里找找单独的流式渲染开关。
- 转发层对响应做了聚合处理。部分网关或框架会把小包合并成大批次再下发,同样会破坏事件流,只能从链路两端逐段排查。
排查口诀:先用 curl 直连看是否逐包往外打印,确认服务端真在「边生成边推」;再顺着链路一段段找,看是谁在中途囤货。
什么情况反而该关掉流式
流式不是万能的。有三类场景老老实实用非流式,代码更简单,也更稳:
- 要用程序解析完整 JSON。让模型输出结构化数据再交给下游处理时,一次拿到完整结果,解析逻辑最省心。
- 内容要过质检再展示。比如生成后需要做一遍格式校验或敏感词检查,边生成边显示就没法在中间拦下来。
- 后台批量跑任务。几百条请求无人值守地跑,流式省下的等待时间没有意义,反而多出一堆拼接代码。
常见问题
流式会不会更容易「说到一半卡住」?
会。流式把一次响应拆成了很多小包,链路上任何一段网络抖动都可能让连接提前断开。非流式其实也会失败,只不过失败发生在你还没看到任何内容的时候,感觉上没那么糟。稳妥做法是给请求设好超时,已经收到内容却被中断时再补跑一次——注意这会导致重复生成,也就意味着可能重复计费,心里要有数。
首字延迟能优化吗?
能,但幅度有限。换推理更快的模型(比如 qwen3.7-plus、glm-5.3 这类轻量档,或者试试 kimi-k3)、把提示词写短、限制输出长度,都能让第一个字更快出现。真正的瓶颈在模型本身,参数层面能挤出的时间通常也就几百毫秒。
为什么有些模型蹦字一卡一卡的?
因为推给你的是「词」不是「字」。模型按 token 输出,一个 token 可能是半个词,也可能是一个词组,再加上网络传输的间隔,视觉上就会忽快忽慢。另外,推理型模型有的会在正式回答前先走一段思考过程,那段时间屏幕上是安静的,属于正常现象。