AI 对话的流式输出详解——不止于SSE

常规的 HTTP 请求采用"一问一答"的同步交互模式。但实际场景中,"一问多答"(客户端单次请求,服务端分批次返回响应)甚至全双工交互(客户端与服务端双向实时通信)的需求长期存在。

一、主流的流式输出技术

在 HTML5 普及初期,最常见的解决方案是 Websocket。Websocket 基于 TCP 协议,实现了客户端与服务端的全双工通信,适用于需要高频交互的场景(如在线聊天、实时监控)。
但 LLM 普及后,行业几乎清一色选择了 SSE(Server-Sent Events)。核心原因在于,LLM 的回答过程本身就是:"逐字生成返回",恰好匹配 SSE"一问多答"的特性,无需 Websocket 那样的双向连接,降低了开发和资源消耗。

二、原理:基于 HTTP 的流式传输

SSE 的本质是基于 HTTP 协议的流式传输,依托 ReadableStream实现。ReadableStream 允许服务端将响应数据拆分为多个"chunk",分批次发送给客户端,客户端无需等待完整响应,即可逐块接收并渲染,这也是 AI 对话"边思考边输出"效果的核心实现方式。

2.1 HTTP 1.1 中的流式传输

在 HTTP 1.1 协议中,服务端会在响应头中添加 Transfer-Encoding: chunked 字段,用于标记当前响应为"流式返回"。
客户端(如浏览器)识别到该字段后,会按照逐块读取服务端推送的数据;当服务端完成所有数据推送后,会返回一个空chunk,告知客户端"流已结束"。

2.2 HTTP 2 中的流式传输

HTTP 2 中禁用了 Transfer-Encoding: chunked 字段,通过 header 中的 Content-Length 字段识别流式返回:若该字段为空,说明响应为流式返回(服务端无法提前确定总响应长度);

三、常见的流式 Content-Type 类型及说明

不同的 Content-Type 对应不同的流式场景:

  • text/event-stream:SSE 标准流式类型,也是主流大模型采用的类型;
  • application/*json:泛 JSON 流式类型,其中 * 代表不同的扩展标识(如 KIMI 对话使用 application/connect+json,其他场景常用 application/x-ndjson、application/json),核心特点是"每一个数据块都是一个完整的 JSON 对象",适用于需要结构化数据的流式场景;
  • application/octet-stream:通用二进制流式类型(如文件分片下载);
  • video/、audio/、image/*:媒体类天然流式类型,如视频、音频、图片的渐进式加载;
  • multipart/x-mixed-replace:多用于实时图像流场景(如摄像头监控、实时截图),可实现"替换式"流式推送,新数据块会覆盖旧数据块。

四、客户端 API

针对 SSE 流式输出,客户端(主要是浏览器)有两种常用的读取方式:

  1. ReadableStream API:通用的流式读取 API,支持所有 HTTP 流式类型(包括 text/event-stream、application/*json 等),灵活性高;
javascript 复制代码
// 简化版:ReadableStream 读取 HTTP 1.1 流式数据(适配AI对话场景)
const streamChat = async () => {
    const response = await fetch('https://your-llm-api.com/chat', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ prompt: '请解释SSE的原理', history: [] })
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder('utf-8');
    let fullContent = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      const chunk = decoder.decode(value, { stream: true });
      fullContent += chunk;
      document.getElementById('chat-container').innerText = fullContent;
    }

    console.log('流式传输结束,完整内容:', fullContent);
};
  1. EventSource API :浏览器对 SSE(text/event-stream 类型)的原生封装,使用简单,无需手动解析流数据,会自动将服务端推送的内容封装为message 事件。但存在明显局限------仅支持 GET 请求,且没有结束事件的回调。
javascript 复制代码
// EventSource 仅支持 GET 请求,服务端需返回 Content-Type: text/event-stream
const eventSource = new EventSource('https://your-llm-api.com/chat?prompt=请解释SSE的原理');

// 监听服务端推送的消息(流式数据)
eventSource.onmessage = (e) => {
  // e.data 即为服务端推送的单个数据块
  console.log('流式接收数据:', e.data);
  document.getElementById('chat-container').innerText += e.data;
};

五、总结

AI 对话的流式输出,核心是通过 SSE 基于 HTTP 流式传输实现,本质是利用 ReadableStream 将 LLM 生成的内容分批次推送至客户端。
与常规 HTTP 请求相比,SSE 完美匹配 LLM "一问多答"的响应模式。其中,text/event-stream 作为 SSE 标准类型,是主流大模型的首选,而 ReadableStream API 和 EventSource API 则是客户端处理流式数据的工具 API。

相关推荐
fthux2 小时前
RenoPit 能为普通业主做什么?看懂图纸、审查合同,提前发现装修坑
javascript·人工智能·ai·开源·github·chrome扩展·open source·edge扩展·firefox扩展
仿生狮子4 小时前
✂️ Nuxt 最简单的字体裁剪工具:Fontize
javascript·vue.js·nuxt.js
哥不是小萝莉4 小时前
AI 应用落地:原理、架构与工程实践
ai
_itgo5 小时前
LangGraph 主要3 种核心模式
ai·langchain·langgraph
魔力女仆7 小时前
分享一个 JS 鼠标跟随贪吃蛇背景库
开发语言·javascript·计算机外设
Muscleheng7 小时前
SpringBoot 集成 DeepSeek 实现 RAG 文档问答
java·spring boot·ai·springai
别惊醒渔人8 小时前
Vue3 Diff 优化:最长递增子序列 LIS
前端·javascript·vue.js
Larcher9 小时前
从“加载模型”界面到端侧推理:拆解一个 React + WebGPU 大模型 Demo
javascript·后端
桦说编程9 小时前
炮轰SDD:Spec驱动开发为何不适合绝大多数项目
llm·ai编程·代码规范
Larcher9 小时前
从状态快照到惰性初始化:读懂 React useState 的三个关键场景
javascript·人工智能·后端