一句话解释:什么是大模型 API 的流式输出?

大模型 API 的流式输出,简单说就是:模型在生成回答时,不会等整段答案全部写完再返回,而是先生成一部分,就先把这一部分发给客户端。用户看到的效果很像 AI 在“边打字边回答”,内容会逐字、逐词,或者一小段一小段地显示出来。

在实际调用大模型 API 时,流式输出通常通过某个请求参数打开。比如很多兼容 OpenAI 格式的接口,会使用 stream=true。开启之后,接口返回的就不再是一个完整答案,而是一连串增量数据片段,也就是大家经常说的 chunk。

这里有个点需要先说清楚:流式输出改变的是“答案怎么返回”,不是模型本身怎么变强。它通常不会让模型更快生成完整答案,也不会直接提升回答质量。它真正改善的是用户的等待感——用户不用一直盯着空白页面,而是可以更早看到第一段内容。

一句话概括就是:

流式输出的重点不是让模型“生成得更快”,而是让用户“更早看到结果”。

流式输出和非流式输出有什么区别?

非流式输出比较像传统接口请求:客户端发起请求后,服务端等大模型把完整答案生成完,再一次性返回给客户端。

流式输出就不一样了。模型一边生成,服务端一边把已经生成的片段返回给客户端;客户端则一边接收、一边拼接、一边展示。

对比项流式输出非流式输出
返回方式多个 chunk 逐步返回完整结果一次性返回
用户感知很快就能看到内容要等完整答案生成完
首 token 延迟通常更低通常更高
总生成耗时不一定更短不一定更长
前端实现需要拼接、渲染、处理结束状态直接展示完整文本即可
后端实现需要长连接、流式转发、处理断连普通请求响应就够了
适合场景聊天、长文、代码、Agent 过程展示分类、打标、批处理、结构化结果
错误处理可能返回半截答案成功或失败的边界更清楚
Token 统计可能在最后 chunk 或额外事件里返回通常在完整响应中返回
用户取消很适合中途停止生成取消带来的体验提升不明显

所以,流式输出并不是要把非流式输出全部替代掉。它更适合那些面向用户、需要实时反馈的交互场景;而非流式输出则更适合短任务、后台任务,以及必须拿到完整结果后再校验的任务。
在这里插入图片描述

大模型 API 流式输出的工作原理

大模型生成文本时,可以粗略理解为逐 token 或逐小段生成。非流式 API 会等这些片段全部生成完成,再拼成一段完整答案返回。流式 API 则是在生成过程中,把已经生成好的部分不断推送给调用方。

一个简化后的过程大概是这样:

用户请求:请介绍流式输出

chunk 1:流式
chunk 2:输出是指
chunk 3:模型边生成边返回
chunk 4:[DONE]

实际接入时,开发者通常会经历这样几个步骤:

第一,请求大模型 API 时设置 stream=true。

第二,服务端通过 HTTP stream、SSE,或者类似机制持续返回数据。

然后,客户端一块一块读取响应内容。

接下来,客户端把每次收到的增量片段拼接起来,逐渐形成完整答案。

等收到 [DONE]、finish_reason,或者其他结束事件后,再停止读取,并把最终内容保存下来。

这也是很多人第一次接入流式输出时容易踩坑的地方:流式返回的每一段都不是完整答案,甚至有些片段里根本没有可以直接展示的文本。

典型返回格式:chunk、delta、data 和 [DONE] 分别是什么?

不少大模型 API 的流式输出会采用 SSE,也就是 Server-Sent Events。常见返回形式大概长这样:

data: {"choices":[{"delta":{"content":"你好"}}]}

data: {"choices":[{"delta":{"content":",有什么可以帮你?"}}]}

data: [DONE]

这里有几个概念很常见,最好提前理解一下。

data: 是 SSE 里常见的数据行格式。每一段 data: 后面可能是一段 JSON,也可能是一个结束标记。

chunk 指的是一次增量返回的数据块。它不一定只包含文本,也可能包含角色信息、状态、结束原因,或者用量统计。

delta.content 通常表示这一次新增的文本内容。客户端要把多次返回的 delta.content 拼接起来,才能得到最终回答。

[DONE] 一般表示流式输出结束。不过不同平台的做法并不完全一样,有的平台可能用 finish_reason=stop,有的用结束事件,还有的会通过最后一个 chunk 来表达结束。

usage 通常表示 Token 用量。有些平台会在最后一个 chunk 里返回,有些需要额外参数开启,也有一些平台会通过单独字段或事件返回。这个不能凭经验猜,最好以对应平台的文档为准。

另外还要注意,推理类模型有时会返回 reasoning_content、工具调用片段,或者其他特殊字段。不要默认每个 chunk 都有 content,也不要默认每个 chunk 都是完整词语、完整句子,更不要把每个片段都当成合法 JSON 来处理。

流式输出适合哪些应用场景?

说到“流式输出应用场景”,不能简单理解成“只要实时交互就适合”。在大模型 API 里,真正适合流式输出的场景,通常有一个共同特点:用户正在等结果,而且输出内容可能比较长。

AI 聊天机器人和智能客服

AI 聊天机器人、智能客服,可以说是最典型的流式输出场景。用户发出问题后,如果页面很久没有任何动静,很容易觉得系统是不是卡住了,甚至会直接退出。

流式输出可以让回答更早出现,明显降低等待焦虑,也更接近真实对话里“逐步回应”的感觉。放在客服产品里,还可以配合“停止生成”“重新生成”“继续追问”等交互,让用户更有掌控感。

不过客服类产品也有一些麻烦点,比如用户中途关闭页面、切换会话、重复提问等。后端最好能在客户端断开后,及时关闭上游请求,避免模型还在继续生成,白白消耗资源。

长文本生成:文章、报告、方案、邮件

文章、报告、营销文案、工作总结、邮件草稿这类长文本生成,输出通常都不短。如果使用非流式输出,用户可能要等十几秒,甚至更久,才能看到完整内容。

用流式输出的话,用户可以边看边判断方向对不对。如果一开头就明显跑偏,用户可以直接停止生成,不用等整篇内容都写完。

这类场景还要特别注意最终内容的保存。前端展示时看到的是一个个增量片段,但真正入库时,应该保存拼接后的完整文本,并记录生成状态。否则一刷新页面,很可能只剩下半截内容,体验会很糟糕。

代码生成和代码解释

代码生成、代码解释、SQL 生成、正则表达式解释等开发者工具,也很适合流式输出。开发者可以更早看到函数结构、注释、实现思路,从而判断模型是不是在朝预期方向生成。

但代码类内容有一个常见问题:它经常包含 Markdown 代码块,而流式输出可能会把代码块拆开。比如前一个 chunk 只返回了 ```js,后一个 chunk 才开始输出真正的代码。如果前端实时渲染 Markdown,就要处理未闭合代码块、语法高亮抖动、页面频繁重排等问题。

比较稳妥的做法是控制渲染频率。比如按固定时间间隔刷新,或者累计到一定字符量再更新 UI,而不是每收到一个特别小的片段就立刻重渲染。

Agent 执行过程和工具调用展示

在 Agent 场景里,用户关心的往往不只是最后答案,还会想知道系统现在到底在干什么:是在搜索资料,还是在调用工具?是在读取文件,还是在整理结果?

流式输出可以把这些“正在执行”的状态展示出来,让整个过程更透明。比如:

正在检索相关资料...
正在调用知识库...
正在整理答案...

不过,这类信息不一定都是模型生成的文本,也可能来自后端任务状态。设计时最好把“过程状态”和“最终回答”区分开,不要把内部工具日志原封不动暴露给用户。否则既影响体验,也可能带来安全和隐私风险。

教育辅导和解题讲解

教育辅导、题目解析、语言学习这类场景,也很适合逐步展示内容。相比一次性把完整答案丢给学生,流式输出可以让学生跟着步骤慢慢理解,更符合学习节奏。

但这里要注意推理展示的边界。并不是所有模型内部推理都适合直接展示出来,尤其是考试、合规、安全要求比较高的场景。更合适的方式,是展示经过整理后的解题过程,而不是不受控制地输出模型内部思考内容。

语音助手和实时字幕

语音助手、实时字幕、AI 口播等场景,也常常会用到流式输出。文本片段先返回,就能更早送进 TTS 或字幕模块,从而降低整体交互延迟。

不过语音场景对稳定性和分句要求更高。太碎的 chunk 并不适合直接拿去合成语音,听起来会很不自然。通常需要按标点、语义片段,或者一定长度先做缓冲,再交给下游语音系统处理。

哪些场景不建议优先使用流式输出?

流式输出并不是所有大模型 API 调用的最佳选择。很多任务用非流式反而更简单,也更稳定。

短结果任务:分类、打标签、意图识别

如果结果只是“是/否”、一个分类标签,或者一个意图名称,那流式输出的收益其实很小。用户不会因为提前看到半个标签就觉得体验更好,但工程实现却会复杂不少。

这类任务通常直接用非流式输出就可以了。

批量离线任务

批量摘要、批量质检、数据清洗、离线打标这类任务,用户通常并不需要实时看每一条结果是怎么生成的。更合适的方案往往是任务队列、异步处理、状态查询,或者回调通知。

流式输出更适合“有人正在页面前等待”的场景,不太适合把所有后台任务都改成长连接。

严格结构化 JSON 输出

如果业务要求模型返回严格 JSON,那使用流式输出就要格外小心。因为流式过程中的片段往往不是完整 JSON,前端不能每收到一段就直接对完整业务对象做 JSON.parse。

更稳妥的方式是:先完整接收所有片段并拼接起来,等流结束后,再做 JSON 解析、Schema 校验和业务校验。

当然,复杂场景下也可以使用专门的增量 JSON 解析方案,但实现成本会明显更高,不一定值得。

需要完整审核后才能展示的内容

在内容安全要求比较高的业务里,如果必须先审核完整回答,再展示给用户,那流式输出会让事情变复杂。因为内容是边生成边展示的,未审核的片段可能已经出现在页面上了。

可选方案包括非流式输出、延迟展示、分段审核、安全模型过滤等。不过这些都会增加系统复杂度,具体怎么选,还是要看业务风险和合规要求。

接入大模型 API 流式输出时要注意什么?

接入流式输出,不只是加一个 stream=true 这么简单。真正上线时,前端、后端、网关、日志、安全策略都要一起配合。

前端要处理实时追加文本、自动滚动到底部、停止生成、异常提示和渲染性能。尤其要注意,不要每收到一个很小的 chunk 就高频更新复杂组件。长文本生成时,这样很容易造成页面卡顿。

后端要负责调用上游大模型 API、转发流、鉴权、限流、日志记录、内容入库和异常处理。客户端断开后,后端也应该尽量关闭上游请求,避免模型继续生成,造成不必要的浪费。

网关和代理同样关键。很多团队明明设置了 stream=true,但前端还是一次性看到完整结果。常见原因包括 Nginx buffering、CDN 缓冲、框架没有及时 flush、后端先把上游完整读完再返回,或者前端根本没有按流读取。这类“伪流式”问题,最好在联调阶段就重点排查。

另外,Token 统计和内容安全也不能忽略。有些平台的用量信息只会在最后返回,如果用户中途断开,统计逻辑就需要有兜底方案。涉及敏感内容时,也要提前明确:是流式前审核、流式中分段审核,还是生成结束后再统一处理。

SSE、WebSocket、Fetch Stream 怎么选?

大模型 API 的流式输出有几种常见接入方式,不同方案适合的场景不太一样。

方案适合场景优点注意点
SSE服务端向浏览器单向推送简单,适合文本流原生 EventSource 主要使用 GET
Fetch ReadableStream前端通过 POST 调用并读取流现代 Web 项目常用,比较灵活需要手动解析流
WebSocket双向实时通信适合语音、协作、实时控制实现和连接管理更复杂
非流式 HTTP短任务、后台任务简单稳定用户等待感更强

对大多数网页聊天机器人来说,比较常见的做法是:后端调用大模型 API 时读取 HTTP stream,前端再通过 Fetch ReadableStream 或 SSE 展示文本。

只有在需要强双向实时交互时,比如语音对话、多人协作、多 Agent 控制,才更适合优先考虑 WebSocket。

如果使用第三方 Claude API 兼容接入服务平台,比如 ClaudeAPI 这类非 Anthropic 官方的平台,也要以它们的最新文档为准。需要确认是否支持流式输出、字段格式是什么、线路怎么选,以及企业充值、开票、技术协助等服务边界,避免直接照搬某一家厂商的格式,最后接入时被细节卡住。

常见误区:流式输出是不是一定更快、更省资源?

关于流式输出,最常见的误区就是:把“更早看到内容”理解成“模型生成更快”。实际上,它主要降低的是首 token 延迟和用户感知上的等待时间,完整答案生成完的总耗时不一定会变短。

还有人会觉得流式输出一定更省服务器资源,这也不一定。流式请求会让连接保持更久,后端还要处理长连接、超时、断连、转发、代理缓冲和并发管理。系统复杂度往往会更高。

另一个常见问题,是把每个 chunk 都当成一句完整的话。实际返回里,一个 chunk 可能只有一个字、半个词、一个空字段,甚至只包含结束状态。

也不要以为所有平台的返回格式都一样。不同大模型 API 在 delta.content、finish_reason、usage、工具调用、推理内容字段上都可能有差异。接入时一定要看当前平台的文档,而不是只凭某个接口的经验来写死逻辑。

最后还有一个误区:以为开启 stream=true 就等于完成了流式体验。其实真正好的流式体验,还包括停止生成、异常恢复、内容保存、滚动控制、渲染性能和安全处理。少了这些,用户体验未必真的好。

总结:什么情况下应该开启 stream=true?

如果用户正在页面上等待结果,输出内容比较长,过程可见能明显改善体验,或者用户需要中途停止生成,那么大模型 API 的流式输出通常就值得开启。典型场景包括 AI 聊天机器人、智能客服、长文本生成、代码生成、Agent 执行过程展示、教育辅导和语音助手。

如果输出很短、任务是在后台批量执行、结果必须完整校验、内容必须先审核再展示,或者团队暂时还没有能力处理断连、拼接、日志、Token 统计和异常恢复,那非流式输出往往更合适。

接入前,可以用下面这份清单快速检查一下:

  • 是否已经设置 stream=true
  • 是否能正确解析 SSE 或响应流
  • 是否处理了 [DONE] 或 finish_reason
  • 是否会拼接完整内容
  • 是否兼容空 chunk 和非文本 chunk
  • 是否支持用户取消生成
  • 是否在断连时关闭上游请求
  • 是否关闭或绕开代理缓冲
  • 是否保存最终完整输出
  • 是否统计 Token 用量
  • 是否处理敏感内容和安全审核
  • 是否对结构化输出做完整性校验

流式输出不是大模型 API 的“高级开关”,而是一种产品体验和工程实现之间的取舍。用在合适的场景里,它能显著改善用户等待体验;但如果场景不合适,它只会让系统变得更复杂。

更多推荐