Server-Sent Events (SSE) 流式输出教程

LLM 生成回复需要时间,尤其是生成长文时,首字延迟 (TTFT) 可能只有 0.5 秒,但生成完整内容可能需要 30 秒。

5分钟
2025-12-26
API开发集成Server

Server-Sent Events (SSE) 流式输出教程

当你和 ChatGPT 对话时,字是一个一个蹦出来的,而不是等了几秒钟后整段一起显示。这种“打字机效果”背后的技术就是 SSE (Server-Sent Events)。对于 AI 应用来说,流式输出是提升用户体验的必修课。


1. 为什么 AI 需要流式输出

LLM 生成回复需要时间,尤其是生成长文时,首字延迟 (TTFT) 可能只有 0.5 秒,但生成完整内容可能需要 30 秒。

  • 非流式 (Blocking): 用户请求 -> (等待 30s 空白) -> 啪,显示全文。体验极差。
  • 流式 (Streaming): 用户请求 -> (等待 0.5s) -> 显 -> 示 -> 内 -> 容... 用户感觉系统反应很快。

2. SSE 原理

SSE 是基于 HTTP 的一种单向通信机制。

  • 客户端发送一个普通请求。
  • 服务端保持连接打开,并将 Response Content-Type 设为 text/event-stream
  • 服务端不断发送数据块,每块以 data: 开头,以 \n\n 结尾。

数据格式示例

data: {"content": "你"}

data: {"content": "好"}

data: {"content": ","}

data: [DONE]

3. 实现指南 (Python/FastAPI)

大多数 AI API(OpenAI, Anthropic)都原样提供了 stream=True 参数。你的后端需要做的就是做一个“二传手”,把上游的流转发给前端。

3.1 后端代码 (FastAPI)

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from openai import OpenAI
import asyncio

app = FastAPI()
client = OpenAI()

async def generate_response_stream(prompt: str):
    # 1. 调用上游 API,开启 stream=True
    stream = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}],
        stream=True,
    )

    # 2. 迭代生成器
    for chunk in stream:
        content = chunk.choices[0].delta.content
        if content:
            # 3. 按照 SSE 标准格式 yield 数据
            yield f"data: {content}\n\n"
    
    # 4. 结束标记
    yield "data: [DONE]\n\n"

@app.get("/chat")
async def chat(prompt: str):
    return StreamingResponse(
        generate_response_stream(prompt), 
        media_type="text/event-stream"
    )

3.2 前端代码 (JavaScript)

前端可以使用原生的 EventSource API,或者 fetch API 来处理。

async function fetchStream() {
  const response = await fetch('/chat?prompt=你好');
  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    // 解析数据
    const text = decoder.decode(value);
    // 注意:这里需要处理 TCP 粘包和 SSE 格式解析,实际生产中推荐使用 fetch-event-source 库
    console.log(text); 
    // updateUI(text);
  }
}

4. 常见坑点

  • Nginx 缓冲: 如果你使用了 Nginx 反向代理,默认情况下它会缓存后端响应直到一定大小才发给客户端,这会破坏流式效果。需要关闭 buffering: proxy_buffering off;
  • JSON 解析: 在前端解析时,要注意可能一次收到多条 data: ...,或者一条 data 被切分在两个数据包里。需要编写鲁棒的 parser。

最后更新:2025-12

AI导航助手

Powered by DeepSeek

你好!我是AI导航助手,由DeepSeek驱动。

我可以帮你: • 推荐适合你的AI模型 • 解答AI相关问题 • 直接带你跳转到相关页面

试试点击下方问题,或直接输入你的问题!

快捷提问:

哪个AI模型最好?有免费的AI吗?写代码用哪个?API怎么接入?

点击按钮可直接跳转到相关页面