Стриминг (Server-Sent Events)

Token-by-token ответ для чатов и длинных генераций

Стриминг включается полем stream: true. Вместо одного JSON вы получаете поток событий data:в формате Server-Sent Events с Content-Type: text/event-stream.

Как включить

python
stream = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "Count from 1 to 5 slowly."}],
    stream=True,
)
for chunk in stream:
    content = chunk.choices[0].delta.content or ""
    print(content, end="", flush=True)

Формат чанка

Каждое событие начинается с data: и содержит JSON-delta:

json
data: {"id":"chatcmpl-9xT","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl-9xT","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"1"},"finish_reason":null}]}

data: {"id":"chatcmpl-9xT","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":", 2"},"finish_reason":null}]}

data: {"id":"chatcmpl-9xT","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]
  • Первый чанк обычно содержит delta.role, далее — только delta.content.
  • Финальный чанк имеет finish_reason (stop, length, tool_calls, content_filter).
  • Поток завершается специальной строкой data: [DONE].
  • Ошибки в середине потока приходят как data: {"error": ...}.

usage в стриминге

Чтобы получить финальную статистику по токенам в стриме, добавьте stream_options: { "include_usage": true }. KodikRouter дошлёт последний чанк с полем usage.

json
{
  "model": "openai/gpt-4o",
  "stream": true,
  "stream_options": { "include_usage": true },
  "messages": [{"role":"user","content":"Hi"}]
}

Отмена стрима

Просто закройте HTTP-соединение / abort-контроллер. Счётчик токенов продолжится только до последнего отданного чанка.

typescript
const controller = new AbortController();
setTimeout(() => controller.abort(), 2000);

const stream = await client.chat.completions.create(
  { model: "openai/gpt-4o", stream: true, messages: [...] },
  { signal: controller.signal },
);
CDN-прокси и буферизация
Если вы проксируете ответ шлюза через свой backend, убедитесь, что промежуточный слой (nginx, Cloudflare, API Gateway) не буферизует SSE. Нужны заголовки X-Accel-Buffering: no и отключенная сжимающая буферизация.