Streaming + chunking

Streaming + chunking

适用范围

在以下情况使用此页面:

  • 解释流式传输或分块如何在通道上工作
  • 更改块流式传输或通道分块行为
  • 调试重复/早期块回复或草稿流式传输

Moltbot 有两个独立的"流式传输"层:

  • 块流式传输(通道):在助手写入时发出已完成的。这些是正常的通道消息(不是令牌增量)。
  • 类令牌流式传输(仅 Telegram):在生成时使用部分文本更新草稿气泡;最终消息在最后发送。

目前没有真正的令牌流式传输到外部通道消息。Telegram 草稿流式传输是唯一的部分流式表面。

块流式传输(通道消息)

块流式传输在粗略块中可用时发送助手输出。

Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker emits blocks as buffer grows
       └─ (blockStreamingBreak=message_end)
            └─ chunker flushes at message_end
                   └─ channel send (block replies)

图例:

  • text_delta/events:模型流式事件(对于非流式模型可能稀疏)。
  • chunkerEmbeddedBlockChunker 应用最小/最大边界 + 中断偏好。
  • channel send:实际出站消息(块回复)。

控制:

  • agents.defaults.blockStreamingDefault"on"/"off"(默认关闭)。
  • 通道覆盖:*.blockStreaming(和每帐户变体)以强制每个通道 "on"/"off"
  • agents.defaults.blockStreamingBreak"text_end""message_end"
  • agents.defaults.blockStreamingChunk{ minChars, maxChars, breakPreference? }
  • agents.defaults.blockStreamingCoalesce{ minChars?, maxChars?, idleMs? }(在发送前合并流式块)。
  • 通道硬上限:*.textChunkLimit(例如 channels.whatsapp.textChunkLimit)。
  • 通道分块模式:*.chunkModelength 默认,newline 在长度分块之前在空行(段落边界)上分割)。
  • Discord 软上限:channels.discord.maxLinesPerMessage(默认 17)分割高大的回复以避免 UI 剪裁。

边界语义:

  • text_end:在块发出器发出时立即流式传输块;在每个 text_end 上刷新。
  • message_end:等待助手消息完成,然后刷新缓冲的输出。

message_end 如果缓冲的文本超过 maxChars 仍使用块,因此它可以在最后发出多个块。

分块算法(低/高边界)

块分块由 EmbeddedBlockChunker 实现:

  • 低边界:在缓冲区 >= minChars 之前不发出(除非强制)。
  • 高边界:在 maxChars 之前首选分割;如果强制,在 maxChars 处分割。
  • 中断偏好paragraphnewlinesentencewhitespace → 硬中断。
  • 代码围栏:永不在围栏内分割;在 maxChars 处强制时,关闭 + 重新打开围栏以保持 Markdown 有效。

maxChars 被钳位到通道 textChunkLimit,因此您不能超过每通道上限。

合并(合并流式块)

当启用块流式传输时,Moltbot 可以在发送之前合并连续的块块。这减少了"单行垃圾邮件",同时仍提供渐进式输出。

  • 合并在刷新之前等待空闲间隙idleMs)。
  • 缓冲区被 maxChars 限制,如果超过它将刷新。
  • minChars 防止在累积足够文本之前发送小片段(最后刷新始终发送剩余文本)。
  • 连接器派生自 blockStreamingChunk.breakPreferenceparagraph\n\nnewline\nsentence → 空格)。
  • 通道覆盖可通过 *.blockStreamingCoalesce 获得(包括每帐户配置)。
  • 默认合并 minChars 对于 Signal/Slack/Discord 增加到 1500,除非覆盖。

块之间的类似人类的节奏

当启用块流式传输时,您可以在块回复之间添加随机暂停(在第一个块之后)。这使得多气泡响应感觉更自然。

  • 配置:agents.defaults.humanDelay(通过 agents.list[].humanDelay 每个代理覆盖)。
  • 模式:off(默认)、natural(800–2500ms)、customminMs/maxMs)。
  • 仅适用于块回复,不适用于最终回复或工具摘要。

“流式传输块或所有内容”

这映射到:

  • 流式传输块blockStreamingDefault: "on" + blockStreamingBreak: "text_end"(边走边发)。非 Telegram 通道还需要 *.blockStreaming: true
  • 在最后流式传输所有内容blockStreamingBreak: "message_end"(刷新一次,如果非常长可能是多个块)。
  • 无块流式传输blockStreamingDefault: "off"(仅最终回复)。

通道注意:对于非 Telegram 通道,块流式传输关闭,除非 *.blockStreaming 显式设置为 true。Telegram 可以流式传输草稿(channels.telegram.streamMode)而无需块回复。

配置位置提醒:blockStreaming* 默认值位于 agents.defaults 下,而不是根配置。

Telegram 草稿流式传输(类令牌)

Telegram 是唯一具有草稿流式传输的通道:

  • 带主题的私人聊天中使用 Bot API sendMessageDraft
  • channels.telegram.streamMode: "partial" | "block" | "off"
    • partial:使用最新流式文本更新草稿。
    • block:在分块块中更新草稿(相同的块规则)。
    • off:无草稿流式传输。
  • 草稿块配置(仅适用于 streamMode: "block"):channels.telegram.draftChunk(默认:minChars: 200maxChars: 800)。
  • 草稿流式传输与块流式传输分开;块回复默认关闭,仅在非 Telegram 通道上通过 *.blockStreaming: true 启用。
  • 最终回复仍然是正常消息。
  • /reasoning stream 将推理写入草稿气泡(仅 Telegram)。

当草稿流式传输处于活动状态时,Moltbot 为该回复禁用块流式传输以避免双重流式传输。

Telegram (private + topics)
  └─ sendMessageDraft (draft bubble)
       ├─ streamMode=partial → update latest text
       └─ streamMode=block   → chunker updates draft
  └─ final reply → normal message

图例:

  • sendMessageDraft:Telegram 草稿气泡(不是真实消息)。
  • final reply:正常 Telegram 消息发送。