﻿# Streaming в OpenRouter: как читать ответ по частям

Как устроен streaming OpenRouter: SSE-события, буферизация частей ответа, первый токен, завершение, usage и обработка обрыва без ложного статуса успешной генерации.

Автор: Команда Retrivium
Обновлено: 2026-11-01
Канонический URL: https://retrivium.ai/ru/journal/openrouter-streaming-client/
Language: ru

Streaming OpenRouter позволяет показывать ответ по мере генерации. Для этого клиент передаёт `stream: true` и читает поток событий выбранного API. Разница с обычным запросом заключается не только в выводе текста: приложение должно правильно обрабатывать границы событий, завершение и отказ после начала передачи.

Форматы Chat Completions и Responses различаются. Не объединяйте их парсеры только потому, что оба сервиса передают данные постепенно. Описание ниже проверено по документации 1 ноября 2026 года.

## Выберите один протокол

[Руководство streaming OpenRouter](https://openrouter.ai/docs/api_reference/streaming) описывает передачу через SSE. Для Chat Completions полезный текст поступает в соответствующих частях выбора ответа; Responses использует собственные типы событий. Сначала сохраните формат, который реально запрашивает ваше приложение.

HTTP-клиент может возвращать байтовые части в произвольном размере. Один такой фрагмент не обязательно равен целому событию или целому JSON. Поэтому чтение каждого сетевого куска через отдельный `JSON.parse` ненадёжно даже при исправном сервере.

## Разбирайте SSE с буфером

Правила разделения событий и служебных комментариев определяет [спецификация Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation). Используйте совместимый парсер либо аккуратно сохраняйте незавершённый остаток между чтениями. Декодирование UTF-8 также должно учитывать символ, разделённый между байтовыми фрагментами.

Условный тест: передайте сохранённую запись событий парсеру сначала целиком, затем кусками по несколько байтов. Итоговый текст и последовательность состояний должны совпасть. Это проверка клиентского кода; для неё не требуется каждый раз оплачивать новый модельный вызов.

## Измеряйте разные моменты

| Событие | Что оно подтверждает |
| --- | --- |
| Пришли заголовки | Соединение и ответ HTTP начались |
| Получен первый полезный текст | Пользователь может начать читать |
| Получено штатное завершение | Поток завершился по правилам выбранного API |
| Получен учёт использования | Есть данные для последующей сверки расходов |

Не называйте время заголовков временем первого токена. Комментарий поддержания соединения тоже не является сгенерированным текстом. Эти различия особенно важны при сравнении GPU-провайдеров с разными очередями и стадиями подготовки.

## Обрабатывайте частичный ответ

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

Если ответ используется для запуска инструмента, частичного текста недостаточно для выполнения действия. Дождитесь завершённой структуры, проверьте аргументы и примените правила приложения. Успешный HTTP-статус не разрешает автоматически выполнять то, что ещё не закончено.

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

## Свяжите поток с эксплуатацией

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

Дальше полезны [ошибки внутри потока](/ru/journal/openrouter-stream-errors/) и [компромисс задержки и пропускной способности GPU](/ru/journal/throughput-latency-tradeoff/). Планирование инфраструктуры начинается с реального профиля потоковых запросов, а не только с рекламного числа токенов в секунду.
