Обновить

В Bot API 10.3 появилась остановка генерации. Но LLM-запрос придётся отменять самому

24 августа вышел Telegram Bot API 10.3. В нём появилась полезная функция для AI-ботов: пользователь может остановить генерацию ответа штатной кнопкой Telegram.

В методы sendMessageDraft и sendRichMessageDraft, которые позволяют показывать черновик ответа в личном чате, добавили два параметра:

  • can_stop=True — показывает кнопку остановки;

  • keep_on_stop=True — временно оставляет уже сгенерированную часть ответа в чате.

Когда пользователь нажимает кнопку, бот получает обновление stopped_message_generation. В нём есть chat, message_thread_id и draft_id, поэтому событие можно связать с конкретной генерацией.

Если вы явно задаёте allowed_updates, новый тип обновления нужно добавить туда. Иначе нажатие кнопки просто не попадёт в обработчик.

Но Telegram останавливает только показ черновика. Запрос к LLM на стороне бота продолжит выполняться, пока разработчик сам его не отменит.

Например, можно хранить задачи по ключу из идентификаторов чата, темы и черновика:

key = (chat_id, message_thread_id, draft_id)

active_generations[key] = asyncio.create_task(
    generate_answer()
)

При получении stopped_message_generation находим задачу и отменяем её:

event = update.stopped_message_generation
key = (event.chat.id, event.message_thread_id, event.draft_id)

task = active_generations.pop(key, None)

if task is not None:
    task.cancel()

    try:
        await task
    except asyncio.CancelledError:
        pass

Это упрощённый пример: конкретный обработчик зависит от используемого фреймворка.

Одного task.cancel() тоже не всегда достаточно. Отмена в asyncio кооперативная: задача остановится только тогда, когда управление вернётся в event loop. Если внутри работает синхронный код или отдельный поток, он может продолжить работу.

Нужно также закрыть потоковое HTTP-соединение с провайдером модели. А если провайдер поддерживает отдельный API отмены, вызвать и его. Иначе модель может продолжить генерацию — вместе с расходом токенов — даже после закрытия соединения.

По сути, здесь есть три независимых действия:

  • Telegram прекращает показывать черновик;

  • бэкенд отменяет локальную задачу и закрывает соединение;

  • провайдер модели останавливает генерацию, если умеет это делать.

Ещё один нюанс касается keep_on_stop=True. Остановленный черновик не превращается в обычное сообщение. Он исчезнет после следующего сообщения в чате или примерно через 30 секунд.

Если частичный ответ нужно сохранить, его придётся отдельно отправить через sendMessage или sendRichMessage.

В многопроцессной системе обычного словаря тоже будет недостаточно: событие остановки может попасть не в тот процесс, где выполняется генерация. Тогда понадобится общая маршрутизация или канал отмены через Redis, брокер сообщений либо другой внешний сервис.

Telegram добавил удобный интерфейс, но жизненный цикл генерации всё равно остаётся на стороне разработчика.

Вопрос: что вы бы делали после остановки: сохраняли частичный ответ, удаляли его или показывали кнопку «Продолжить», которая запускает новый запрос с уже полученным текстом?

Теги:
+3
Комментарии0

Как Telegram удалил 800 ГБ моих данных и причем тут орфография

После очередного запуска компьютера привычные программы одна за другой перестали открываться. В папке C:\custom остались в основном пустые каталоги: исчезли проекты, программы и другие данные общим объёмом около 800 ГБ.

Я начал запускать приложения по одному и смотреть, после какого действия пропадают файлы. След привёл к Telegram Desktop — мессенджер, установленный в другой папке, при каждом запуске рекурсивно очищал C:\custom.

Дальше были Process Monitor, стеки вызовов, issue на GitHub и неожиданная причина в проверке орфографии.

Как Telegram удалил 800 ГБ моих данных и причем тут орфография

Публикации