Основы

Стриминг ответов: зачем нужен и как обрабатывать

Зачем нужен стриминг ответов модели, как устроен SSE и как обрабатывать поток чанков на Python и JavaScript — с примерами кода для единого API.

2 минуты чтения

По умолчанию API возвращает ответ целиком — приходится ждать, пока модель допишет последнее слово. Стриминг отдаёт ответ по мере генерации, токен за токеном, как печатающий собеседник. Для интерфейсов это ключевая деталь: пользователь видит текст сразу, а не смотрит на спиннер. Разберём, зачем это нужно и как обработать поток. Определение — в глоссарии.

Зачем нужен стриминг

  • Отзывчивость — первые слова появляются через доли секунды, а не после полной генерации. Воспринимаемая скорость выше, даже если суммарное время то же.
  • Длинные ответы — при генерации большого текста ожидание целиком было бы мучительным; поток показывает прогресс.
  • Ранняя реакция — можно начать читать или обрабатывать ответ, не дожидаясь конца, и при необходимости прервать генерацию.
Стриминг не ускоряет саму генерацию и не меняет стоимость — токены те же. Он меняет то, как ответ доставляется: по кусочкам вместо одного блока. Для фоновых задач без интерфейса стриминг обычно не нужен.

Как устроен SSE

Технически стриминг работает поверх Server-Sent Events (SSE) — сервер держит соединение открытым и шлёт события по мере готовности. Каждое событие — строка вида data: {…} с очередным фрагментом (чанком). Поток завершается маркером data: [DONE]. Чтобы включить режим, добавьте в запрос stream: true.

data: {"choices":[{"delta":{"content":"При"}}]}
data: {"choices":[{"delta":{"content":"вет"}}]}
data: {"choices":[{"delta":{"content":"!"}}]}
data: [DONE]

Обработка потока на Python

from openai import OpenAI

client = OpenAI(
    base_url="https://ai-gatewey.ru/v1",
    api_key="sk-aigate-ваш_ключ",
)

stream = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    messages=[{"role": "user", "content": "Расскажи о стриминге в двух предложениях"}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
print()

Обработка потока на JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://ai-gatewey.ru/v1",
  apiKey: "sk-aigate-ваш_ключ",
});

const stream = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5",
  messages: [{ role: "user", content: "Расскажи о стриминге в двух предложениях" }],
  stream: true,
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) process.stdout.write(delta);
}
process.stdout.write("\n");
Токены расхода при стриминге те же, но поле usage приходит в самом конце потока (или отдельным запросом) — не рассчитывайте получить его из первого же чанка. Копите фрагменты delta.content в буфер, если нужен полный ответ целиком.

Список моделей с поддержкой стриминга и детали протокола — на странице возможности стриминг.

Частые вопросы

Стриминг ускоряет ответ модели?

Нет, сама генерация идёт с той же скоростью, и суммарное время не меняется. Стриминг улучшает воспринимаемую скорость: первые слова появляются сразу, поэтому интерфейс кажется живее, чем при ожидании полного ответа.

Стриминг стоит дороже обычного запроса?

Нет, расход токенов идентичен — меняется только способ доставки ответа. Поле usage с итоговым числом токенов приходит в конце потока.

Как собрать полный ответ из потока?

Накапливайте фрагменты delta.content из каждого чанка в строку-буфер до маркера [DONE]. В примерах на Python и JavaScript это делается в цикле по потоку — добавьте конкатенацию вместо вывода на экран.

Стриминг из коробки в едином API

Начать бесплатно