Multi-channel Stream
LLM Streaming 的高级协议模式——在同一个事件流中通过 channel 字段区分不同类型的输出(text、reasoning、tool、structured),实现输出分流。
#concept
#evergreen
#ai
#architecture
[!info] related notes
- 所属 MOC: LLM Streaming MOC
- 实现层: Semantic Router
- 组合: Structured Streaming, Event Sourcing AI
- 综合: Streaming 高级协议模式
- 基础协议: Delta Stream, Append Event Stream
Multi-channel Stream
一句话定义
Multi-channel Stream 是 LLM Streaming 的高级协议模式——在同一个事件流中通过 channel 字段区分不同类型的输出(文本、推理、工具调用、结构化数据),让不同类型的内容走不同的逻辑通道。
核心机制
解决什么问题
LLM 生成过程中,输出不只是”回答文本”。还有:
- 接口明确提供且允许展示的推理摘要
- 工具调用请求
- 结构化提取结果
- 引用来源
- 流程状态
同一流可以复用连接;type/channel 契约让消费者区分文本、状态和工具相关事件。
协议结构
下面是应用自定义字段示例,不是供应商统一标准;JSONL 每行是一个独立对象:
{ "channel": "text", "delta": "你好" }
{ "channel": "reasoning", "delta": "正在整理协议设计要点。" }
{ "channel": "tool", "name": "search", "args": {} }
{ "channel": "structured", "data": { "symptoms": ["头痛"] } }
{ "channel": "status", "data": { "step": "analyzing" } }
前端消费
// 按 channel 分发到不同的 buffer / 状态
switch (event.channel) {
case "text":
textBuffer += event.delta
break
case "reasoning":
reasoningBuffer += event.delta // 可以隐藏或折叠展示
break
case "tool":
updateToolStatus(event) // UI 投影;执行仍由后端授权
break
case "structured":
updateStructuredData(event.data)
break
}
示例通道定义
| channel | 语义 | 前端处理 |
|---|---|---|
text | 面向用户的回答文本 | 主聊天 UI,打字机效果 |
reasoning | 允许公开的推理摘要 | 按展示策略渲染 |
tool | 工具请求/结果事件 | 工具状态 UI;不是客户端执行授权 |
structured | 结构化数据 | 专用 UI 组件 |
citation | 引用来源 | 引用面板 |
status | 流程状态 | 状态指示器 |
error | 错误/警告 | 错误提示 |
最小场景
{ "channel": "text", "type": "message.delta", "data": { "content": "我帮你查一下天气。" } }
{ "channel": "reasoning", "type": "thinking.delta", "data": { "content": "正在查询天气资料。" } }
{ "channel": "tool", "type": "tool_call.started", "data": { "name": "get_weather" } }
{ "channel": "text", "type": "message.delta", "data": { "content": "今天北京晴,25°C。" } }
这是虚构天气数据的事件形状示例,省略工具结果和终态;data 封装与前面的扁平 delta 示例是两种写法,消费者需选定一种契约。
前端:用户看到”我帮你查一下天气。今天北京晴,25°C。“,允许公开的摘要显示在折叠面板,工具调用显示为一个状态卡片。
与基础协议的关系
Multi-channel 不是 Delta / Append 的替代,而是它们的叠加维度:
- Delta Stream + channel = 带通道的文本增量
- Append Stream + channel = 带通道的事件追加
{
"type": "message.delta",
"channel": "text",
"data": { "content": "你好" }
}
边界与易混淆点
- Multi-channel 不是多条连接:本篇模型在一条 SSE/WebSocket 连接上复用逻辑通道;channel 本身不保证隔离、独立顺序或流量控制。
- channel 和 event type 的区别:
channel是”这个内容给谁用”,type是”这个事件是什么”。一个 channel 可以有多种 type。 - 不需要所有 channel 都用:简单场景只用
text就够了,按需启用其他 channel。 - 可按契约忽略非必要展示事件,但不能随意跳过影响状态一致性的终态/错误事件。
- 发到浏览器的数据即已交付给客户端,隐藏/折叠面板不构成访问控制;不该公开的内容应在服务端过滤。
- 通道仍需关联 message_id/tool_call_id;共享通道中的并发消息不能拼入同一个 buffer。