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

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

Сервер и формат событий
В схеме с постоянным API-ключом браузер обращается к вашему серверу, а сервер к провайдеру. Не публикуйте секрет в клиентском коде. Сервер проверяет пользователя и лимиты, передает данные без накопления полного ответа и правильно обрабатывает формат протокола. ReadableStream и getReader позволяют читать части тела fetch. TextDecoder должен корректно обрабатывать границы UTF-8; несколько сетевых частей могут образовать одно событие SSE. Не считайте каждый read готовым сообщением.
Отмена не равна остановке счета
Кнопка Stop может отменить fetch через AbortController. Обработайте отмену отдельно от сетевой ошибки. Передайте сигнал через сервер, если стек это поддерживает, и проверьте, прекратилась ли работа у провайдера. Закрытие соединения в браузере само по себе не доказывает остановку генерации или оплаты. Показывайте частичный текст как незавершенный. Для единого JSON-документа ждите успешного окончания протокола, затем разбирайте и проверяйте схему. Обрыв не является завершением.
Хранение и испытание
Не сохраняйте конфиденциальный частичный ответ автоматически. Определите область сессии, срок хранения и доступ после повторного открытия вкладки. Попросите агента показать diff и обработку ошибок. На тестовых данных замедлите сеть, разорвите соединение, нажмите Stop и разделите многобайтовый символ между частями. Проверьте отсутствие повторного запроса после двойного нажатия, корректное сообщение при обрыве и поведение сервера после отмены. Это предлагаемый план проверки, а не отчет об испытанном приложении.
Источники
- https://wurk.fun/blog/stream-llm-responses-so-your-app-doesn-t-look-frozen
- https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
- https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
- https://developer.mozilla.org/en-US/docs/Web/API/AbortController
- https://wurk.fun/blog/get-json-you-can-trust-from-an-llm-schema-validate-retry