LLM Streaming 分层架构

生产级 LLM Streaming 系统的五层架构:Token Stream → Chunk Aggregator → Semantic Router → Event Bus → Frontend State Manager,各层职责清晰,可独立演进。

#type / synthesis #status / evergreen #tech / ai #tech / architecture

[!info] related notes

LLM Streaming 分层架构

范围

描述生产级 LLM Streaming 系统的完整分层架构,从模型 token 输出到前端 UI 渲染的全链路。

为什么要分层

一个简单的 SSE demo 可以不做分层——直接把 LLM token 透传给前端。但生产系统需要:

  • 聚合:token 太细,需要聚合成语义 chunk
  • 分流:输出不只有文本,还有工具调用、结构化数据、推理过程
  • 统一协议:前端、日志、监控、回放系统需要统一的事件格式
  • 状态管理:前端需要集中管理流式状态,而不是散落在各组件

五层架构

┌─────────────────────────────────┐
│  ① Token Stream Layer           │  模型层:接收原始 token
│     (OpenAI / Claude / Qwen)    │
└──────────────┬──────────────────┘

┌─────────────────────────────────┐
│  ② Chunk Aggregator             │  聚合层:token → 语义 chunk
│     (按标点/Markdown/tool边界)    │
└──────────────┬──────────────────┘

┌─────────────────────────────────┐
│  ③ Semantic Router              │  路由层:按类型分流输出
│     (text/tool/thinking/cite)   │
└──────────────┬──────────────────┘

┌─────────────────────────────────┐
│  ④ Event Bus (SSE/WebSocket)    │  传输层:统一协议输出
│     (Structured Event Stream)   │
└──────────────┬──────────────────┘

┌─────────────────────────────────┐
│  ⑤ Frontend State Manager       │  状态层:管理 UI 状态
│     (Zustand / Redux / XState)  │
└─────────────────────────────────┘

各层职责详解

① Token Stream Layer(模型层)

职责:接收 LLM Provider 的原始 token 流。

输入:OpenAI / Claude / Qwen 等 provider 的 streaming API

输出

token: "你"
token: "好"

关键点

  • 不同 provider 的 token 粒度不同
  • 有些 provider 已经做了初步聚合
  • 这一层通常由 LLM Provider SDK 封装

② Chunk Aggregator(聚合层)

职责:将 token 聚合为更有语义意义的 chunk。

聚合策略

  • 按标点(句号、换行)
  • 按 Markdown 块(代码块、列表)
  • 按 function call boundary
  • 按时间窗口(每 N ms 发送一次)
  • 按长度(累积 N 个字符后发送)

输出

chunk: "你好世界。"

详见 Chunk Aggregator

③ Semantic Router(路由层)

职责:根据内容类型将输出分流到不同处理通道。

分流目标

通道目标
text主聊天 UI
tool后端执行器 + 工具状态 UI
thinking隐藏面板(可展开)
citation引用面板
structured专用 UI 组件

详见 Semantic Router

④ Event Bus(传输层)

职责:通过 SSE / WebSocket 输出统一格式的事件。

协议格式(推荐 Structured Streaming):

{ "type": "message.delta", "channel": "text", "data": { "content": "你好" } }
{ "type": "tool_call.started", "channel": "tool", "data": { "name": "search" } }
{ "type": "message.completed", "channel": "text", "data": { "message_id": "m1" } }

传输方式选择

方式适用场景
SSE单向推送,HTTP 兼容,最常用
WebSocket双向通信,需要客户端发送控制信号
HTTP Streamingfetch + ReadableStream,灵活控制

⑤ Frontend State Manager(状态层)

职责:集中管理流式状态,供 UI 组件消费。

状态结构

{
  messages: Message[],           // 消息列表
  streamingBuffer: string,       // 当前正在生成的文本 buffer
  toolCalls: ToolCall[],         // 工具调用列表
  extractedInfo: object,         // 结构化提取信息
  status: "idle" | "streaming" | "error"  // 流状态
}

推荐工具

  • Zustand(轻量,适合中小项目)
  • Redux Toolkit(成熟,适合大型项目)
  • XState(状态机,适合复杂状态流转)

依赖路径

Token Stream → Chunk Aggregator → Semantic Router → Event Bus → Frontend State Manager
     ↑                ↑                  ↑               ↑              ↑
  LLM Provider    聚合策略          分流规则         传输协议        状态模型

每层可以独立演进:

  • 换 LLM Provider → 只改第 ① 层
  • 优化聚合策略 → 只改第 ② 层
  • 增加新的输出类型 → 改第 ③ 层 + 前端 reducer
  • 从 SSE 切到 WebSocket → 只改第 ④ 层
  • 换状态管理库 → 只改第 ⑤ 层

对比与易混淆点

  • 分层不是必须的:简单场景可以跳过某些层(比如不需要 Semantic Router,直接透传 text)。
  • 层与层之间不是严格串行:有些事件可能跳过 Chunk Aggregator 直接到 Semantic Router(比如 tool_call 事件)。
  • Chunk Aggregator 是最容易被忽视的层:很多系统直接透传 token,导致 char-level split 问题。
  • Event Bus 不只是 SSE:SSE 只是传输方式,Event Bus 还需要处理事件格式化、错误处理、重连逻辑。
创建于 2026/6/29 更新于 2026/7/15