Потоковый ответ

Чему научитесь

Видео 8:23 и текст урока

К концу урока вы сможете:

Видео и текст урока.

Смотреть урок на Skilljar Response streaming · 8:23

В чат-приложениях на Claude есть серьёзная проблема пользовательского опыта: ответ может генерироваться 10–30 секунд, и всё это время пользователь смотрит на индикатор загрузки. Решение — потоковая передача ответа (streaming): пользователь видит, как текст появляется кусок за куском по мере генерации, и приложение ощущается гораздо отзывчивее.

Чат отправляет вопрос на сервер, сервер передаёт его Claude и получает сообщение assistant.
Чат отправляет «What is quantum computing?» на наш сервер, сервер передаёт вопрос Claude и получает ответ ассистента.

Проблема обычных ответов

В типичной схеме сервер отправляет сообщение пользователя Claude и ждёт полного ответа, прежде чем что-то вернуть клиенту. Возникает неловкая пауза, во время которой пользователь не видит никаких признаков, что что-то происходит.

Ответ Claude может занять 10–30 секунд, а в чате всё это время три точки.
Генерация может занять 10–30 секунд, а в чате всё это время только три точки.

Как работает поток

Со включённым потоком Claude сразу присылает начальный ответ: запрос получен, генерация началась. Затем приходит серия событий, и в каждом — небольшой кусок общего ответа.

Claude отвечает начальным ответом, затем событиями «Quantum», «computing», «is».
Сначала начальный ответ, затем события с кусками текста: «Quantum», «computing», «is»…

Сервер может пересылать эти куски клиентскому приложению по мере поступления, и пользователь видит, как ответ складывается слово за словом. Все эти события — части одного запроса к Claude.

События потока

Со включённым потоком Claude присылает события нескольких типов:

Типы событий потока по порядку; ContentBlockDelta повторяется три раза и содержит сгенерированный текст.
События приходят от Claude по порядку; сам сгенерированный текст — в повторяющихся ContentBlockDelta.

Именно события ContentBlockDelta содержат сгенерированный текст, который вы будете показывать пользователям.

Простая реализация потока

Чтобы включить поток, добавьте stream=True в вызов messages.create:

messages = []
add_user_message(messages, "Write a 1 sentence description of a fake database")

stream = client.messages.create(
    model=model,
    max_tokens=1000,
    messages=messages,
    stream=True
)

for event in stream:
    print(event)
Вывод ноутбука для кода выше: RawMessageStartEvent, затем RawContentBlockStartEvent.
Вывод ноутбука: сначала RawMessageStartEvent, затем RawContentBlockStartEvent и дальше по списку.

Упрощённый поток текста

Вместо того чтобы разбирать события вручную, можно воспользоваться упрощённым интерфейсом потока в SDK, который достаёт только текст:

with client.messages.stream(
    model=model,
    max_tokens=1000,
    messages=messages
) as stream:
    for text in stream.text_stream:
        print(text, end="")

Этот способ автоматически отбрасывает всё, кроме текста, — обычно именно это и нужно, чтобы показывать ответ пользователю.

Получаем сообщение целиком

Поток по кускам хорош для пользователя, но часто нужно и полное сообщение — чтобы сохранить или обработать дальше. Когда поток закончился, можно получить собранное итоговое сообщение:

with client.messages.stream(
    model=model,
    max_tokens=1000,
    messages=messages
) as stream:
    for text in stream.text_stream:
        # Send each chunk to your client
        pass

    # Get the complete message for database storage
    final_message = stream.get_final_message()

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

Дальше

Следующий урок — как получать ответ без пояснений вокруг: чистый JSON или другой структурированный кусок.

Оригинал урока: Response streaming.