Потоковая генерация (streaming)

Как показывать ответ модели по мере генерации, а не ждать его целиком.

Стриминг — режим, при котором ответ приходит маленькими кусочками (чанками) по мере генерации, а не одним блоком в конце.

Зачем это нужно

  • Отзывчивость: пользователь видит текст сразу, как в ChatGPT, а не ждёт 20 секунд пустого экрана.
  • Длинные ответы: при больших max_tokens обычный (нестриминговый) запрос может упереться в таймаут HTTP-соединения. Стриминг держит соединение живым.
  • Ранняя обработка: можно начать обрабатывать/показывать вывод, не дожидаясь конца.

Как это выглядит в коде (Claude)

SDK даёт удобный помощник: вы итерируете по текстовым дельтам и тут же их печатаете.

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Напиши короткий рассказ."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)   # печатаем по кусочкам

    final = stream.get_final_message()    # полный ответ, когда поток закончился
    print("\n\nТокенов на выходе:", final.usage.output_tokens)

А что приходит «по проводу»

Технически это поток событий (Server-Sent Events): начало сообщения, старт блока, дельты текста, конец блока, конец сообщения. SDK скрывает эту механику за text_stream. На низком уровне вы бы перебирали события и собирали текст из дельт сами.

Сборка текста из чанков (запускаемо)

Сымитируем поток дельт и соберём из них итоговый текст — чистый Python, без сети:

deltas = ["Pari", "s — ", "столица ", "Франции."]
buffer = []
for i, d in enumerate(deltas):
    buffer.append(d)
    print(f"чанк {i}: +'{d}' -> текущий текст: '{''.join(buffer)}'")
full = "".join(buffer)
print("Готовый текст:", full)

Вывод:

чанк 0: +'Pari' -> текущий текст: 'Pari'
чанк 1: +'s — ' -> текущий текст: 'Paris — '
чанк 2: +'столица ' -> текущий текст: 'Paris — столица '
чанк 3: +'Франции.' -> текущий текст: 'Paris — столица Франции.'
Готовый текст: Paris — столица Франции.

О чём помнить при стриминге

  • Поток может оборваться на середине — обрабатывайте сетевые ошибки и показывайте частичный текст корректно.
  • Итоговые счётчики токенов и причина остановки приходят в конце (финальное событие).
  • Для больших max_tokens стриминг практически обязателен, иначе риск таймаута.

Итог

  • Стриминг отдаёт ответ кусочками: отзывчивый UX и защита от таймаутов на длинных ответах.
  • SDK даёт text_stream и get_final_message() поверх потока событий.
  • Текст вы накапливаете из дельт; метаданные приходят в финале.
Проверьте себя
1. В чём главное преимущество стриминга для пользователя?
AОтвет становится точнее
BТекст появляется сразу по мере генерации, повышая отзывчивость интерфейса
CЭкономятся токены
DНе нужен ключ API
2. Почему для больших значений max_tokens рекомендуют стриминг?
AОн дешевле обычного запроса
BДолгий нестриминговый запрос может упереться в таймаут HTTP; стриминг держит соединение живым
CБез него нельзя задать max_tokens
DОн отключает rate limits
3. Когда при стриминге приходят итоговые счётчики токенов и причина остановки?
AВ самом первом чанке
BВ финальном событии, когда поток завершился
CОни не приходят при стриминге
DВ каждом чанке отдельно
Поддержать проект