---
read_when:
  - 解释流式传输或分块在渠道上如何工作
  - 更改分块流式传输或渠道分块行为
  - 调试重复/提前的块回复或草稿流式传输
summary: 流式传输 + 分块行为（块回复、草稿流式传输、限制）
title: 流式传输和分块
x-i18n:
  generated_at: "2026-02-03T10:05:41Z"
  model: claude-opus-4-5
  provider: pi
  source_hash: f014eb1898c4351b1d6b812223226d91324701e3e809cd0f3faf6679841bc353
  source_path: concepts/streaming.md
  workflow: 15
---

# 流式传输 + 分块

Fased 有两个独立的"流式传输"层：

- **分块流式传输（渠道）：** 在助手写入时发出已完成的**块**。这些是普通的渠道消息（不是令牌增量）。
- **类令牌流式传输（仅限 Telegram）：** 在生成时用部分文本更新**草稿气泡**；最终消息在结束时发送。

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

## 分块流式传输（渠道消息）

分块流式传输在助手输出可用时以粗粒度块发送。

```
模型输出
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ 分块器在缓冲区增长时发出块
       └─ (blockStreamingBreak=message_end)
            └─ 分块器在 message_end 时刷新
                   └─ 渠道发送（块回复）
```

图例：

- `text_delta/events`：模型流事件（对于非流式模型可能稀疏）。
- `chunker`：应用最小/最大边界 + 断点偏好的 `EmbeddedBlockChunker`。
- `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`）。
- 渠道分块模式：`*.chunkMode`（默认 `length`，`newline` 在长度分块之前按空行（段落边界）分割）。
- Discord 软上限：`channels.discord.maxLinesPerMessage`（默认 17）分割高度较大的回复以避免 UI 裁剪。

**边界语义：**

- `text_end`：分块器发出时立即流式传输块；在每个 `text_end` 时刷新。
- `message_end`：等到助手消息完成，然后刷新缓冲的输出。

如果缓冲文本超过 `maxChars`，`message_end` 仍然使用分块器，因此可能在最后发出多个块。

## 分块算法（低/高边界）

块分块由 `EmbeddedBlockChunker` 实现：

- **低边界：** 在缓冲区 >= `minChars` 之前不发出（除非强制）。
- **高边界：** 优先在 `maxChars` 之前分割；如果强制，则在 `maxChars` 处分割。
- **断点偏好：** `paragraph` → `newline` → `sentence` → `whitespace` → 硬断点。
- **代码围栏：** 从不在围栏内分割；当在 `maxChars` 处强制分割时，关闭 + 重新打开围栏以保持 Markdown 有效。

`maxChars` 被限制在渠道 `textChunkLimit` 内，因此你无法超过每渠道的上限。

## 合并（合并流式块）

启用分块流式传输时，Fased 可以在发送前**合并连续的块分块**。这减少了"单行刷屏"，同时仍提供渐进式输出。

- 合并在**空闲间隙**（`idleMs`）后刷新。
- 缓冲区受 `maxChars` 限制，超过时将刷新。
- `minChars` 防止微小片段发送，直到累积足够文本（最终刷新始终发送剩余文本）。
- 连接符从 `blockStreamingChunk.breakPreference` 派生（`paragraph` → `\n\n`，`newline` → `\n`，`sentence` → 空格）。
- 渠道覆盖通过 `*.blockStreamingCoalesce` 可用（包括每账户配置）。
- 除非覆盖，Signal/Slack/Discord 的默认合并 `minChars` 提高到 1500。

## 块之间的类人节奏

启用分块流式传输时，你可以在块回复之间添加**随机暂停**（在第一个块之后）。这使多气泡响应感觉更自然。

- 配置：`agents.defaults.humanDelay`（通过 `agents.list[].humanDelay` 按智能体覆盖）。
- 模式：`off`（默认）、`natural`（800–2500ms）、`custom`（`minMs`/`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: 200`，`maxChars: 800`）。
- 草稿流式传输与分块流式传输分开；块回复默认关闭，仅在非 Telegram 渠道上通过 `*.blockStreaming: true` 启用。
- 最终回复仍然是普通消息。
- `/reasoning stream` 将推理写入草稿气泡（仅限 Telegram）。

当草稿流式传输活跃时，Fased 会为该回复禁用分块流式传输以避免双重流式传输。

```
Telegram（私聊 + 主题）
  └─ sendMessageDraft（草稿气泡）
       ├─ streamMode=partial → 更新最新文本
       └─ streamMode=block   → 分块器更新草稿
  └─ 最终回复 → 普通消息
```

图例：

- `sendMessageDraft`：Telegram 草稿气泡（不是真正的消息）。
- `final reply`：普通 Telegram 消息发送。
