РОУТИНГ LLM

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

В этом материале
ГЛАВНОЕ ЗА МИНУТУ

Streaming требует разбирать события протокола, а не произвольные сетевые куски. Отдельно фиксируйте начало ответа, полезный текст, завершение и возможную ошибку внутри потока.

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

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

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

Руководство streaming OpenRouter описывает передачу через SSE. Для Chat Completions полезный текст поступает в соответствующих частях выбора ответа; Responses использует собственные типы событий. Сначала сохраните формат, который реально запрашивает ваше приложение.

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

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

Правила разделения событий и служебных комментариев определяет спецификация Server-Sent Events. Используйте совместимый парсер либо аккуратно сохраняйте незавершённый остаток между чтениями. Декодирование UTF-8 также должно учитывать символ, разделённый между байтовыми фрагментами.

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

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

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

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

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

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

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

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

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

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

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

← Все материалы