Delta Stream vs Append Stream
Delta Stream 和 Append Stream 表面上都"只返回增量",但增量对象完全不同——Delta 增量的是同一文本字段,Append 增量的是事件日志中的新增记录。
#type / synthesis
#status / evergreen
#tech / ai
#tech / architecture
[!info] related notes
- 所属 MOC: LLM Streaming MOC
- 相关概念: Delta Stream, Append Event Stream, Full State Stream
- 输出模型: LLM 输出四层模型
- 高级组合: Streaming 高级协议模式
Delta Stream vs Append Stream
范围
对比 LLM Streaming 的两种最主流协议模式:Delta Stream(文本增量流)和 Append Event Stream(事件追加流)。它们表面上都”只返回增量”,但增量的对象、前端的消费方式、适用场景完全不同。
为什么要放在一起理解
很多开发者混淆这两种协议,因为它们都”只传增量”。但选错协议会导致:
- 用 Delta Stream 做 Agent 系统 → 无法优雅表达工具调用和结构化数据
- 用 Append Stream 做简单聊天 → 前端 reducer 过度复杂,打字机效果难实现
理解它们的本质区别,才能在正确场景选择正确的协议。
核心区别:增量对象不同
Delta Stream:增量的是 content
// 前端操作
message.content += delta.content
事件示例:
{ "type": "text.delta", "content": "你" }
{ "type": "text.delta", "content": "好" }
{ "type": "text.delta", "content": "世界" }
所有 delta 都在扩展同一段文本。最终结果:
message.content = "你好世界"
Append Stream:增量的是 event
// 前端操作
events.push(event)
事件示例:
{ "type": "message.append", "content": "你好" }
{ "type": "tool_call", "name": "symptom_extract", "args": {...} }
{ "type": "extracted_info", "data": { "symptom": "头痛" } }
{ "type": "message.append", "content": "根据你的描述..." }
每个事件是独立的结构化记录,可能有不同的类型和目标。
一句话判断标准
// 如果前端收到事件后主要做:
currentMessage += content
// → Delta Stream
// 如果前端收到事件后主要做:
switch (event.type) {
case "message.append":
case "tool_call":
case "extracted_info":
case "status":
}
// → Append Stream
对比表
| 对比点 | Delta Stream | Append Stream |
|---|---|---|
| 增量对象 | 同一个文本字段 | 新事件 / 新片段 / 新消息项 |
| 前端操作 | content += delta | events.push(event) 或 reducer 分发 |
| 关注点 | 一条消息怎么逐步生成 | 一个 AI 流程产生了哪些事件 |
| 数据形态 | 偏 text diff | 偏 event log |
| UI 效果 | 打字机输出 | 多步骤状态展示 |
| 典型用途 | ChatGPT 回答生成 | Agent / workflow / tool call |
| 带宽 | ⭐ 最低 | 中 |
| 延迟 | ⭐ 最低 | 中 |
| 前端复杂度 | 中(维护 buffer) | 中(reducer 分发) |
依赖路径 / 演进链
简单聊天 → Delta Stream 就够
↓ 增加 function calling
需要表达工具调用 → 在 Delta 基础上扩展事件类型
↓ 增加结构化提取、多步骤流程
事件类型越来越多 → 自然演进为 Append Stream
↓ 需要统一事件格式
加 Structured Streaming 封装 → 工业级协议
实际系统的做法
大多数生产系统不是纯 Delta 或纯 Append,而是组合使用:
外层用 Append 管理流程,内层用 Delta 管理文本生成。
{ "type": "message.started", "message_id": "m1" } // ← Append
{ "type": "text.delta", "message_id": "m1", "content": "你好" } // ← Delta
{ "type": "tool_call", "name": "symptom_extract" } // ← Append
{ "type": "extracted_info", "data": {...} } // ← Append
{ "type": "text.delta", "message_id": "m1", "content": ",我已经整理了你的症状。" } // ← Delta
{ "type": "message.completed", "message_id": "m1" } // ← Append
易混淆点
- “都是增量”不等于”一样”:Delta 的增量是文本扩展,Append 的增量是事件追加。
- Append 不排斥文本效果:Append Stream 也可以实现打字机效果,只是需要额外处理(比如
message.append事件的 content 字段逐字到达)。 - 选择标准不是”哪个更好”而是”场景需要什么”:只做聊天选 Delta,做 Agent 选 Append,做复杂系统选组合。