Перейти к основному содержанию
Когда вы запрашиваете ответ обычным способом, клиент ждёт, пока модель допишет последнее слово, и только потом показывает результат. На длинном ответе это секунды тишины. Потоковый режим (streaming) отдаёт текст по кусочкам, прямо во время генерации — пользователь видит, как ответ печатается, и воспринимаемая задержка падает почти до нуля. Технически это не магия: вместо одного JSON-ответа сервер открывает поток Server-Sent Events (SSE) и шлёт по нему мелкие фрагменты (chunks). Включается это одним флагом — stream=True.
Streaming работает на том же OpenAI-совместимом эндпоинте, что и обычные запросы. Меняется только флаг stream и способ чтения ответа. base_url остаётся прежним: https://www.ruapi.ai/v1.

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

Вместо одного объекта response вы получаете итератор. На каждой итерации приходит chunk, а полезный текст лежит в chunk.choices[0].delta.content. Его нужно дописывать к выводу по мере поступления.
from openai import OpenAI

client = OpenAI(
    api_key="sk-ВАШ_КЛЮЧ",
    base_url="https://www.ruapi.ai/v1",
)

stream = client.chat.completions.create(
    model="claude-opus-4-8",  # точные имена — на странице цен основного сайта
    messages=[{"role": "user", "content": "Расскажи короткую историю про кота."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:  # в последнем chunk content бывает None — пропускаем
        print(delta, end="", flush=True)
print()
В curl ответ приходит как поток строк data: {...}, каждая со своим фрагментом. Признак конца — строка data: [DONE].

Смена модели

Как и в обычных запросах, для переключения модели меняется только поле model — код стриминга остаётся тем же. Например, gpt-5, gemini-3.5-flash или deepseek-v3:
model="gpt-5"            # вместо claude-opus-4-8
Полный список доступных имён — на странице «Цены» основного сайта.

Стриминг по протоколу Anthropic

Если вы работаете через нативный протокол Anthropic (Claude Code, Anthropic SDK), стриминг тоже поддерживается — через client.messages.stream(...). Адрес здесь без /v1:
import anthropic

client = anthropic.Anthropic(
    api_key="sk-ВАШ_КЛЮЧ",
    base_url="https://www.ruapi.ai",  # для Anthropic — без /v1
)

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)
print()
Подробнее про два протокола и базовые адреса — в справочнике API.

Подводные камни

Финальный фрагмент потока обычно несёт служебную информацию (например, finish_reason), а не текст — поэтому delta.content там None (в Node.js — undefined). Всегда проверяйте значение перед тем, как его выводить или склеивать, иначе получите TypeError при попытке конкатенации.
По умолчанию итоговая статистика (usage) в потоке не приходит. Чтобы её получить, добавьте в запрос параметр stream_options:
stream = client.chat.completions.create(
    model="claude-opus-4-8",
    messages=[{"role": "user", "content": "Привет!"}],
    stream=True,
    stream_options={"include_usage": True},
)
Тогда в самом конце потока придёт отдельный chunk с полем usage. У такого chunk список choices пустой — учитывайте это при разборе.
Если текст появляется одним куском, а не печатается постепенно — скорее всего, между вами и API стоит прокси или балансировщик, который буферизует SSE. Проверьте, что отключено буферирование ответа (например, proxy_buffering off; в nginx) и что ваш HTTP-клиент не накапливает поток сам. В curl для надёжности добавьте флаг -N (--no-buffer).

Что дальше