admin管理员组

文章数量:1130349

当大模型的回答从漫长的等待变成实时的文字涌流,开发者与最终用户的交互体验被彻底重塑。Streaming 模式让客户端在服务器仍在推理时就能持续收到增量 token,显著降低首字节延迟,同时也带来资源控制、安全管线和 UI 设计的新挑战。下文以 DeepSeek 与 ChatGPT 两条主流 API 为核心,解剖其流式原理、协议实现、最佳实践与风险治理,并给出完整可运行的示例代码,帮助读者快速掌握这一现代 AI 基础设施。

背景:为何需要 Streaming

  • 大模型一次推理往往包含上百甚至上千个 token,如果等待完整响应再渲染,用户将感受到明显卡顿;流式返回则可把等待拆分为细粒度传输,显著提升体验。OpenAI 在其官方示例中将 stream 参数置为 true,即可按 SSE 事件源逐段推送数据 (OpenAI Cookbook)。

  • DeepSeek 在文档中指出,同样的 stream 布尔位可切换为流式输出,且 Curl / Python / NodeJS 均已内置示例 (DeepSeek API Docs)。

  • 行业博客与社区在性能测试中发现,开启流式后首字节延迟可降低 50% 以上,而带宽占用与非流式几乎持平 (OpenFaaS, Stackademic)。

核心协议与传输机制

HTTP 持久连接与 Chunked Encoding

ChatGPT 与 DeepSeek 均基于标准 HTTP/1.1 长连接;服务器通过 Transfer-Encoding: chunked 将响应拆分为若干帧,每帧前置十六进制长度,客户端即时解码并渲染 (Stackademic)。该机制兼容绝大多数反向代理与 CDN,部署成本低。

Server-Sent Events(SSE)

更高级的实现使用 text/event-stream MIME 类型,借助 data: 前缀与 \n\n 事件分隔符,让浏览器原生 EventSource 即可消费。OpenAI Cookbook 与 DeepSeek 示例均采用 SSE,事件载荷是 JSON 字符串,其中 choices[0].delta 存放增量 token (OpenAI Cookbook, DeepSeek API Docs)。

WebSocket 适用场景

当需要双工交互(如实时协同编辑、多模态上传)时,SSE 无法满足上传通道,必须改用 WebSocket。然而 SSE 具备断点自动重连、HTTP/2 原生多路复用等优势,社区在对比中普遍建议文本生成场景优先选择 SSE (Reddit)。

DeepSeek API Streaming 细节

参数含义典型值
model选用模型,如 deepseek-chat必填
stream是否开启流式true
messages聊天历史数组

DeepSeek 版本与 OpenAI 近乎同构,但在 reasoning 模型系列(R1)里还会回传推理链,可配合可视化工具实时调试 (Medium, Financial Times)。注意 R1 的思考片段默认输出在 role:assistant,需要在前端做过滤或高亮。

ChatGPT API Streaming 细节

ChatGPT 的 v1/chat/completions 接口在流式时持续推送形如:

data: {"id":"...","choices":[{"delta":{"content":"字"}}]}

最后以 data: [DONE] 结束流。官方指南强调:务必使用 delta 字段拼接完整内容,切勿直接取 message,否则会丢失中间片段 (OpenAI Cookbook, OpenAI Platform)。

端到端示例(Node.js + SSE)

import express from 'express';
import fetch from 'node-fetch';

const app = express();
app.use(express.json());

app.post('/chat', async (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.flushHeaders(); // 立即推送 HTTP 头

  const upstream = await fetch('https://api.openai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gpt-4o-mini',
      stream: true,
      messages: [{ role: 'user', content: req.body.prompt }]
    })
  });

  for await (const chunk of upstream.body) {
    res.write(chunk); // 直接转发给浏览器 EventSource
  }
  res.end();
});

app.listen(3000);

以上代码仅使用单引号避免双引号冲突,也展示了如何把 OpenAI 的 SSE 流原样透传给前端。若要对 delta 做二次加工,可解析 JSON 并重新封装 data: 事件。

前端消费示例(浏览器原生)

<script>
const es = new EventSource('/chat', { withCredentials: true });
let buffer = '';
es.onmessage = (e) => {
  if (e.data === '[DONE]') es.close();
  else {
    const json = JSON.parse(e.data);
    buffer += json.choices[0].delta.content || '';
    document.querySelector('#out').textContent = buffer;
  }
};
</script>
<pre id="out"></pre>

流式模式下的资源管理

  • 并发连接数:SSE 基于浏览器单域 6 条并发限制,需做好请求队列。

  • 超时与中断:务必在后端设置 read_timeout,避免前端离线时僵尸连接占用 GPU 卡。

  • 速率限制:OpenAI 与 DeepSeek 对流式调用同样计费,且有 max_requests_per_minute 限制;合理使用排队或令牌桶。官方论坛提供了 NodeJS 按 chunk 读取并统计 token 的范例 (OpenAI Community)。

UI 设计要点

  • 令牌流入时立即追加文本,模拟打字动画可提升沉浸感。

  • 若模型输出 thoughts 或推理链,需要分区渲染或折叠面板,避免信息洪流淹没主回答。Apidog 的可视化调试给出了灵感 (Medium)。

  • 对移动端建议自动滚动到可视区域底部,同时提供暂停按钮,让用户随时停止生成。

风控与安全

  • 由于客户端能看到未过滤的增量 token,必须在服务器流出之前完成合规检查。常见做法是把生成放进隔离沙箱,先收集一小段缓冲,再做关键字审查后推流。

  • 对可解释性要求较高的业务(医疗、法律)可以通过 max_tokens 限制回答长度,降低暴露概率。

深入阅读推荐

  1. OpenFAAS 的 SSE 教程深入演示了 Lambda 场景下的流式代理 (OpenFaaS)。

  2. David Richards Medium 文章详述了在前后端双向链路中如何安全地进行 SSE 转发 (Medium)。

  3. Swift 社区的实践说明了在 iOS 端解析 chunked 的细节,为移动开发者提供了借鉴 (Stackademic)。

结语

流式传输把大模型推理过程拆解为细水长流的 token,打破了请求-等待-渲染的陈旧范式。掌握 SSE / Chunked Encoding 的底层逻辑、理解 DeepSeek 与 ChatGPT 在语义封装上的微差,并在 UI 与安全层面做足功课,才能真正释放流式的价值。希望本文的理论拆解与示例代码能成为你构建实时 AI 体验的跳板。

当大模型的回答从漫长的等待变成实时的文字涌流,开发者与最终用户的交互体验被彻底重塑。Streaming 模式让客户端在服务器仍在推理时就能持续收到增量 token,显著降低首字节延迟,同时也带来资源控制、安全管线和 UI 设计的新挑战。下文以 DeepSeek 与 ChatGPT 两条主流 API 为核心,解剖其流式原理、协议实现、最佳实践与风险治理,并给出完整可运行的示例代码,帮助读者快速掌握这一现代 AI 基础设施。

背景:为何需要 Streaming

  • 大模型一次推理往往包含上百甚至上千个 token,如果等待完整响应再渲染,用户将感受到明显卡顿;流式返回则可把等待拆分为细粒度传输,显著提升体验。OpenAI 在其官方示例中将 stream 参数置为 true,即可按 SSE 事件源逐段推送数据 (OpenAI Cookbook)。

  • DeepSeek 在文档中指出,同样的 stream 布尔位可切换为流式输出,且 Curl / Python / NodeJS 均已内置示例 (DeepSeek API Docs)。

  • 行业博客与社区在性能测试中发现,开启流式后首字节延迟可降低 50% 以上,而带宽占用与非流式几乎持平 (OpenFaaS, Stackademic)。

核心协议与传输机制

HTTP 持久连接与 Chunked Encoding

ChatGPT 与 DeepSeek 均基于标准 HTTP/1.1 长连接;服务器通过 Transfer-Encoding: chunked 将响应拆分为若干帧,每帧前置十六进制长度,客户端即时解码并渲染 (Stackademic)。该机制兼容绝大多数反向代理与 CDN,部署成本低。

Server-Sent Events(SSE)

更高级的实现使用 text/event-stream MIME 类型,借助 data: 前缀与 \n\n 事件分隔符,让浏览器原生 EventSource 即可消费。OpenAI Cookbook 与 DeepSeek 示例均采用 SSE,事件载荷是 JSON 字符串,其中 choices[0].delta 存放增量 token (OpenAI Cookbook, DeepSeek API Docs)。

WebSocket 适用场景

当需要双工交互(如实时协同编辑、多模态上传)时,SSE 无法满足上传通道,必须改用 WebSocket。然而 SSE 具备断点自动重连、HTTP/2 原生多路复用等优势,社区在对比中普遍建议文本生成场景优先选择 SSE (Reddit)。

DeepSeek API Streaming 细节

参数含义典型值
model选用模型,如 deepseek-chat必填
stream是否开启流式true
messages聊天历史数组

DeepSeek 版本与 OpenAI 近乎同构,但在 reasoning 模型系列(R1)里还会回传推理链,可配合可视化工具实时调试 (Medium, Financial Times)。注意 R1 的思考片段默认输出在 role:assistant,需要在前端做过滤或高亮。

ChatGPT API Streaming 细节

ChatGPT 的 v1/chat/completions 接口在流式时持续推送形如:

data: {"id":"...","choices":[{"delta":{"content":"字"}}]}

最后以 data: [DONE] 结束流。官方指南强调:务必使用 delta 字段拼接完整内容,切勿直接取 message,否则会丢失中间片段 (OpenAI Cookbook, OpenAI Platform)。

端到端示例(Node.js + SSE)

import express from 'express';
import fetch from 'node-fetch';

const app = express();
app.use(express.json());

app.post('/chat', async (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.flushHeaders(); // 立即推送 HTTP 头

  const upstream = await fetch('https://api.openai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gpt-4o-mini',
      stream: true,
      messages: [{ role: 'user', content: req.body.prompt }]
    })
  });

  for await (const chunk of upstream.body) {
    res.write(chunk); // 直接转发给浏览器 EventSource
  }
  res.end();
});

app.listen(3000);

以上代码仅使用单引号避免双引号冲突,也展示了如何把 OpenAI 的 SSE 流原样透传给前端。若要对 delta 做二次加工,可解析 JSON 并重新封装 data: 事件。

前端消费示例(浏览器原生)

<script>
const es = new EventSource('/chat', { withCredentials: true });
let buffer = '';
es.onmessage = (e) => {
  if (e.data === '[DONE]') es.close();
  else {
    const json = JSON.parse(e.data);
    buffer += json.choices[0].delta.content || '';
    document.querySelector('#out').textContent = buffer;
  }
};
</script>
<pre id="out"></pre>

流式模式下的资源管理

  • 并发连接数:SSE 基于浏览器单域 6 条并发限制,需做好请求队列。

  • 超时与中断:务必在后端设置 read_timeout,避免前端离线时僵尸连接占用 GPU 卡。

  • 速率限制:OpenAI 与 DeepSeek 对流式调用同样计费,且有 max_requests_per_minute 限制;合理使用排队或令牌桶。官方论坛提供了 NodeJS 按 chunk 读取并统计 token 的范例 (OpenAI Community)。

UI 设计要点

  • 令牌流入时立即追加文本,模拟打字动画可提升沉浸感。

  • 若模型输出 thoughts 或推理链,需要分区渲染或折叠面板,避免信息洪流淹没主回答。Apidog 的可视化调试给出了灵感 (Medium)。

  • 对移动端建议自动滚动到可视区域底部,同时提供暂停按钮,让用户随时停止生成。

风控与安全

  • 由于客户端能看到未过滤的增量 token,必须在服务器流出之前完成合规检查。常见做法是把生成放进隔离沙箱,先收集一小段缓冲,再做关键字审查后推流。

  • 对可解释性要求较高的业务(医疗、法律)可以通过 max_tokens 限制回答长度,降低暴露概率。

深入阅读推荐

  1. OpenFAAS 的 SSE 教程深入演示了 Lambda 场景下的流式代理 (OpenFaaS)。

  2. David Richards Medium 文章详述了在前后端双向链路中如何安全地进行 SSE 转发 (Medium)。

  3. Swift 社区的实践说明了在 iOS 端解析 chunked 的细节,为移动开发者提供了借鉴 (Stackademic)。

结语

流式传输把大模型推理过程拆解为细水长流的 token,打破了请求-等待-渲染的陈旧范式。掌握 SSE / Chunked Encoding 的底层逻辑、理解 DeepSeek 与 ChatGPT 在语义封装上的微差,并在 UI 与安全层面做足功课,才能真正释放流式的价值。希望本文的理论拆解与示例代码能成为你构建实时 AI 体验的跳板。

本文标签: 全景脉搏流式streamingChatGpt