Перейти до основного вмісту

Потокова передача + розбиття на фрагменти

OpenClaw має два окремі рівні потокової передачі:
  • Блокова потокова передача (канали): надсилає завершені блоки, поки асистент пише. Це звичайні повідомлення каналу (не дельти токенів).
  • Потокова передача попереднього перегляду (Telegram/Discord/Slack): оновлює тимчасове повідомлення попереднього перегляду під час генерації.
Справжньої потокової передачі дельт токенів у повідомлення каналу наразі немає. Потокова передача попереднього перегляду базується на повідомленнях (надсилання + редагування/додавання).

Блокова потокова передача (повідомлення каналу)

Блокова потокова передача надсилає вихідні дані асистента великими фрагментами в міру їхньої доступності.
Вихід моделі
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker надсилає блоки в міру зростання буфера
       └─ (blockStreamingBreak=message_end)
            └─ chunker скидає дані на 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) розбиває високі відповіді, щоб уникнути обрізання в інтерфейсі.
Семантика меж:
  • text_end: передавати блоки в потоці, щойно chunker їх видає; скидати на кожному text_end.
  • message_end: чекати, поки повідомлення асистента завершиться, а потім скидати буферизований вміст.
message_end усе одно використовує chunker, якщо буферизований текст перевищує maxChars, тому наприкінці він може видати кілька фрагментів.

Алгоритм розбиття на фрагменти (нижня/верхня межа)

Розбиття блоків реалізоване в EmbeddedBlockChunker:
  • Нижня межа: не надсилати, доки буфер < minChars (якщо не примусово).
  • Верхня межа: віддавати перевагу розривам до maxChars; якщо примусово, розривати на maxChars.
  • Пріоритет розривів: paragraphnewlinesentencewhitespace → жорсткий розрив.
  • Блоки коду: ніколи не розривати всередині блоків; якщо примусово розривати на maxChars, закривати й знову відкривати блок, щоб зберегти коректність Markdown.
maxChars обмежується значенням textChunkLimit каналу, тому перевищити ліміти конкретного каналу неможливо.

Об’єднання (злиття потокових блоків)

Коли блокова потокова передача ввімкнена, OpenClaw може об’єднувати послідовні блокові фрагменти перед їхнім надсиланням. Це зменшує «спам з одного рядка», водночас зберігаючи поступове виведення.
  • Об’єднання чекає пауз простою (idleMs) перед скиданням.
  • Буфери обмежуються maxChars і будуть скинуті, якщо перевищать це значення.
  • minChars не дає надсилати надто дрібні фрагменти, доки не накопичиться достатньо тексту (остаточне скидання завжди надсилає залишковий текст).
  • Роздільник визначається з blockStreamingChunk.breakPreference (paragraph\n\n, newline\n, sentence → пробіл).
  • Перевизначення для каналів доступні через *.blockStreamingCoalesce (зокрема для конфігурацій окремих акаунтів).
  • Типове значення minChars для об’єднання підвищується до 1500 для Signal/Slack/Discord, якщо його не перевизначено.

Людиноподібні паузи між блоками

Коли блокова потокова передача ввімкнена, можна додати випадкову паузу між блоковими відповідями (після першого блоку). Це робить відповіді з кількох бульбашок природнішими.
  • Конфігурація: agents.defaults.humanDelay (перевизначення для агента через agents.list[].humanDelay).
  • Режими: off (типово), natural (800–2500мс), custom (minMs/maxMs).
  • Застосовується лише до блокових відповідей, а не до фінальних відповідей чи підсумків інструментів.

«Передавати фрагменти в потоці чи все цілком»

Це відповідає таким варіантам:
  • Передавати фрагменти в потоці: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (надсилати в міру готовності). Для каналів, відмінних від Telegram, також потрібне *.blockStreaming: true.
  • Передати все наприкінці: blockStreamingBreak: "message_end" (одноразове скидання, можливо, кількома фрагментами, якщо відповідь дуже довга).
  • Без блокової потокової передачі: blockStreamingDefault: "off" (лише фінальна відповідь).
Примітка щодо каналів: Блокова потокова передача вимкнена, доки *.blockStreaming явно не встановлено в true. Канали можуть передавати живий попередній перегляд (channels.<channel>.streaming) без блокових відповідей. Нагадування про розташування конфігурації: типові значення blockStreaming* розміщені в agents.defaults, а не в кореневій конфігурації.

Режими потокової передачі попереднього перегляду

Канонічний ключ: channels.<channel>.streaming Режими:
  • off: вимкнути потокову передачу попереднього перегляду.
  • partial: один попередній перегляд, який замінюється найновішим текстом.
  • block: попередній перегляд оновлюється кроками з розбиттям на фрагменти/додаванням.
  • progress: попередній перегляд прогресу/статусу під час генерації, фінальна відповідь після завершення.

Відповідність каналів

Каналoffpartialblockprogress
Telegramзіставляється з partial
Discordзіставляється з partial
Slack
Mattermost
Лише для Slack:
  • channels.slack.streaming.nativeTransport перемикає виклики рідного API потокової передачі Slack, коли channels.slack.streaming.mode="partial" (типово: true).
  • Рідна потокова передача Slack і статус потоку помічника Slack потребують цільового потоку відповідей; DM верхнього рівня не показують такий попередній перегляд у стилі потоку.
Міграція застарілих ключів:
  • Telegram: streamMode + булеве streaming автоматично мігрують у enum streaming.
  • Discord: streamMode + булеве streaming автоматично мігрують у enum streaming.
  • Slack: streamMode автоматично мігрує в streaming.mode; булеве streaming автоматично мігрує в streaming.mode плюс streaming.nativeTransport; застаріле nativeStreaming автоматично мігрує в streaming.nativeTransport.

Поведінка під час виконання

Telegram:
  • Використовує оновлення попереднього перегляду через sendMessage + editMessageText у DM, групах і темах.
  • Потокова передача попереднього перегляду пропускається, коли блокова потокова передача Telegram явно ввімкнена (щоб уникнути подвійної потокової передачі).
  • /reasoning stream може записувати міркування в попередній перегляд.
Discord:
  • Використовує надсилання + редагування повідомлень попереднього перегляду.
  • Режим block використовує розбиття чернетки (draftChunk).
  • Потокова передача попереднього перегляду пропускається, коли блокова потокова передача Discord явно ввімкнена.
  • Фінальні медіа, помилки та явні корисні навантаження відповіді скасовують відкладені попередні перегляди без скидання нової чернетки, а потім використовують звичайне доставлення.
Slack:
  • partial може використовувати рідну потокову передачу Slack (chat.startStream/append/stop), коли вона доступна.
  • block використовує попередні перегляди чернеток у стилі додавання.
  • progress використовує текст попереднього перегляду статусу, а потім фінальну відповідь.
  • Фінальні корисні навантаження медіа/помилки та фінали прогресу не створюють тимчасових повідомлень-чернеток; лише текстові/блокові фінали, які можуть редагувати попередній перегляд, скидають відкладений текст чернетки.
Mattermost:
  • Передає міркування, активність інструментів і частковий текст відповіді в одному чернетковому повідомленні попереднього перегляду, яке фіналізується на місці, коли фінальну відповідь безпечно надсилати.
  • Повертається до надсилання нового фінального повідомлення, якщо повідомлення попереднього перегляду було видалено або воно інакше недоступне під час фіналізації.
  • Фінальні корисні навантаження медіа/помилки скасовують відкладені оновлення попереднього перегляду перед звичайним доставленням замість скидання тимчасового повідомлення попереднього перегляду.
Matrix:
  • Попередні перегляди чернеток фіналізуються на місці, коли фінальний текст може повторно використати подію попереднього перегляду.
  • Фінали лише з медіа, помилки та фінали з невідповідністю цільової відповіді скасовують відкладені оновлення попереднього перегляду перед звичайним доставленням; уже видимий застарілий попередній перегляд редагується.

Оновлення попереднього перегляду прогресу інструментів

Потокова передача попереднього перегляду також може включати оновлення прогресу інструментів — короткі рядки статусу на кшталт «пошук у вебі», «читання файлу» або «виклик інструмента», які з’являються в тому самому повідомленні попереднього перегляду під час роботи інструментів, ще до фінальної відповіді. Це робить багатоетапні ходи з інструментами візуально живими, а не мовчазними між першим попереднім переглядом міркування та фінальною відповіддю. Підтримувані поверхні:
  • Discord, Slack і Telegram передають прогрес інструментів у живе редагування попереднього перегляду.
  • Mattermost уже вбудовує активність інструментів у своє єдине чернеткове повідомлення попереднього перегляду (див. вище).
  • Редагування прогресу інструментів дотримуються активного режиму потокової передачі попереднього перегляду; вони пропускаються, коли потокову передачу попереднього перегляду встановлено в off або коли блокова потокова передача вже перебрала керування повідомленням.

Пов’язане

  • Повідомлення — життєвий цикл повідомлень і доставлення
  • Повторна спроба — поведінка повторних спроб у разі помилки доставлення
  • Канали — підтримка потокової передачі для окремих каналів