Потоковая генерация (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В каждом чанке отдельно