跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonNode.jsAI大前端

流式输出技术解析:后端生成与前端渲染

综述由AI生成流式输出原理及前后端实现方案。后端通过 SSE 技术和 HTTP 分块传输实现数据实时推送,涵盖 FastAPI 与 Node.js 代码示例及 Nginx 配置要点。前端采用 Fetch+ReadableStream 或 EventSource 处理流数据,重点解决了 Markdown 渲染性能优化及数据截断缓冲问题,适用于 AI 大模型对话场景。

邪神洛基发布于 2026/4/6更新于 2026/5/2430 浏览

什么是流式输出,后端怎么生成,前端怎么渲染

流式输出(Streaming Output) 就像是在看视频直播,内容是一边产生一边传输给你的,而不是像下载电影那样,必须等整个文件下完才能开始看。

在 AI 领域(比如 ChatGPT),流式输出表现为文字一个接一个地'蹦'出来,而不是转半天圈圈后突然甩出一大段话。


什么是流式输出,有什么特点

1. 它是怎么实现的?

流式输出的核心技术通常是 SSE (Server-Sent Events,服务器发送事件)。

在传统的 HTTP 请求中,模式是'一问一答':客户端发请求,服务器处理完全部逻辑,打成一个大包发回客户端。而在流式输出中,过程如下:

  1. 建立持久连接:客户端发送一个请求,并在 HTTP 头部声明 Accept: text/event-stream。
  2. 分块传输:服务器每生成一个字(或一个 Token),就立即将其封装成一个小数据块发送出去。
  3. 保持连接:直到内容生成完毕,服务器才会发送一个特殊的结束标志(如 [DONE]),随后关闭连接。

2. 流式输出的特点
特点说明
低首字节延迟 (TTFB)用户能瞬间看到反馈,大大缓解了等待焦虑。
实时性适合长文本生成。如果是普通模式,生成 1000 字可能需要 20 秒,流式模式下第 1 秒就开始显示。
单向通讯不同于 WebSocket 的双向奔跑,SSE 主要是服务器向客户端'单向投喂'数据。
资源占用因为要长时间维持一个 HTTP 连接,对服务器的并发处理能力有一定要求。

3. 为什么 AI 必须用它?

大语言模型(LLM)的推理过程是自回归的。简单来说,它每生成一个词,都要基于前面所有的词重新算一遍概率。

P(w_{t+1} | w_1, w_2, ..., w_t)

这个过程本身就很耗时。如果等 2000 个 Token 全部算完再给用户,用户可能以为网页卡死了。流式输出完美契合了模型'一个一个词往外蹦'的运行逻辑。


后端怎么实现

在后端实现流式输出,本质上是打破'处理完全部逻辑再返回'的传统模式,改为利用 HTTP 分块传输(Chunked Transfer Encoding) 持续向客户端推送数据。

最常见的方法是使用 SSE (Server-Sent Events)。下面我以 Python (FastAPI) 和 Node.js (Express) 为例展示核心逻辑。


1. Python 实现 (以 FastAPI 为例)

FastAPI 内置了 StreamingResponse,非常适合配合大模型的生成器(Generator)使用。

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get("/stream")
async def stream():
    async def generate():
        for i in range(10):
            yield f"data: {i}\n\n"
    return StreamingResponse(generate(), media_type="text/event-stream")

2. Node.js 实现 (以 Express 为例)

在 Node.js 中,通过手动设置 HTTP 响应头并使用 res.write() 来持续发送数据。

const express = require('express');
const app = express();

app.get('/stream', (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  let count = 0;
  const interval = setInterval(() => {
    res.write(`data: ${count++}\n\n`);
  }, 1000);
  req.on('close', () => clearInterval(interval));
});

3. 实现的关键要素

要确保后端流式输出成功,必须满足以下几个条件:

  • 正确的 Content-Type: 必须设置为 text/event-stream。
  • 禁用缓冲 (Buffering):
    • 如果你使用了 Nginx 等反向代理,它可能会默认缓存后端的数据,攒够一波再发给前端。
    • 解决方法: 在 Nginx 配置中设置 proxy_buffering off;,或者让后端返回 X-Accel-Buffering: no 响应头。
  • 特定的数据格式:
    • 每条消息必须以 data: 开头。
    • 每条消息必须以两个换行符 \n\n 结尾。

4. 进阶:如何对接大模型 (LLM)

如果你是在调用 OpenAI 或 Anthropic 的 API,它们通常提供 stream=True 参数。你的后端实际上充当了一个中转站(Proxy):

  1. 后端调用 AI API(开启流式)。
  2. 后端迭代接收 AI 返回的每一个 Chunk。
  3. 后端立刻将这个 Chunk 转发给前端。

前端怎么实现

在前端捕获流式数据,主要有两种主流方案:传统的 EventSource 和现代的 fetch + ReadableStream。

由于现在的 AI 接口(如 OpenAI)大多使用 POST 请求,方案二 (fetch) 是目前最通用的做法。


方案一:使用 fetch 结合 ReadableStream (推荐)

fetch API 本身支持流式读取。通过 response.body,你可以获取一个读取器(Reader),逐块解析数据。

const response = await fetch('/api/stream', { method: 'POST' });
const reader = response.body.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(new TextDecoder().decode(value));
}

方案二:使用 EventSource (仅限 GET)

如果你的后端接口支持 GET 请求,EventSource 是最简单的原生实现,它会自动处理重连和心跳。


核心难点:如何优雅地'渲染'?

在处理 AI 流式输出时,你可能会遇到以下两个坑:

  1. Markdown 渲染:数据是一点点出来的,如果你每出一个字就渲染一次 Markdown,性能会炸掉。
    • 对策:使用带缓存的渲染库(如 markdown-it),并限制渲染频率(如 100ms 刷新一次)。
  2. 数据截断:有时候一个 Unicode 字符或者一个 JSON 字符串会被拆分到两个不同的 Data Chunk 中。
    • 对策:在前端维护一个缓冲区(Buffer),将接收到的 value 累加,直到匹配到完整的 \n\n 再进行解析。

目录

  1. 什么是流式输出,后端怎么生成,前端怎么渲染
  2. 什么是流式输出,有什么特点
  3. 1. 它是怎么实现的?
  4. 2. 流式输出的特点
  5. 3. 为什么 AI 必须用它?
  6. 后端怎么实现
  7. 1. Python 实现 (以 FastAPI 为例)
  8. 2. Node.js 实现 (以 Express 为例)
  9. 3. 实现的关键要素
  10. 4. 进阶:如何对接大模型 (LLM)
  11. 前端怎么实现
  12. 方案一:使用 fetch 结合 ReadableStream (推荐)
  13. 方案二:使用 EventSource (仅限 GET)
  14. 核心难点:如何优雅地“渲染”?
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Flutter eth_sig_util 鸿蒙适配:以太坊加密签名核心实现
  • 无人机视角山区泥石流和滑坡图像识别数据集
  • AI 与大模型的核心差异深度解析
  • 2026 年 Web 前端开发的 8 大趋势
  • Kimi K2.5 实测:多模态与编程能力能否兼得
  • Laravel-Markdown 完全指南:在 Laravel 项目中集成 CommonMark 渲染
  • TqSdk与VnPy两款Python量化框架对比
  • MATLAB 时间序列预测方法实战:AR、ARIMA 与 GARCH 模型
  • ROS导航实战:如何用mpc_local_planner让机器人高效避障(附参数调优技巧)
  • 人工智能对上位机系统的全面重塑与影响分析
  • AI 驱动下 Playwright 结合 RobotFramework 的 Web UI 自动化测试
  • AI 智能客服系统构建方案:选型指南与实战避坑
  • Xilinx PCIe IP 核详解、FPGA 实现及仿真全流程 (Virtex-7 Gen3)
  • CarelessWhisper: 将非因果 Whisper 改造为低延迟流式模型
  • Linux 运行 Windows 程序指南:Wine、Proton 与虚拟化方案
  • C++20 概念(Concepts):模板参数的语义约束定义
  • C++ 精灵库相对运动动画演示:葫芦娃飞向太空
  • Java 面试核心考点梳理:基础、并发与容器篇
  • C++ 入门指南:发展历史、命名空间及输入输出
  • C++ STL vector 容器模拟实现及迭代器失效问题详解

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online