Перейти к содержимому
Документация

Потоковая передача ответов (SSE)

Функции могут передавать вывод потоком вместо одного финального ответа. Платформа оформляет каждый фрагмент как сообщение Server-Sent Events (SSE), поэтому браузеры, CLI-инструменты и оркестраторы показывают прогресс — токены LLM, статус задачи, долгие вычисления, — пока обработчик ещё работает.

Потоковая передача — это обычный HTTP: без перехода на WebSocket и специальных клиентских библиотек. Читать поток может всё, что умеет читать HTTP-ответ построчно: fetch с reader, curl -N, EventSource.

Пишем потоковый обработчик#

В Node.js экспортируйте асинхронный генератор (или верните его из обработчика): каждый yield становится одним SSE-фреймом. Обработчики на Python передают поток так же — yield из генератора или асинхронного генератора, и каждое значение уходит фреймом data:. Обработчики на Go возвращают канал для чтения, и среда выполнения пересылает каждое полученное значение SSE-фреймом, так же как генераторы Node.js и Python.

index.jsjs
// Return an async generator and the platform streams each chunk
// to the client as Server-Sent Events over /invoke/stream.
exports.handler = async function* (event, context) {
  yield { type: 'status', message: 'starting' };

  for (const token of ['Hello', ' from', ' a', ' stream']) {
    // Objects are framed as `data: {...}` SSE events automatically;
    // yield a string to write a raw SSE frame yourself.
    yield { token };
  }

  yield { type: 'done' };
};

Если отдать объект, среда выполнения сериализует его в JSON внутри фрейма data:; если отдать строку, вы сами записываете сырой SSE-фрейм. Если обработчик вернул одно значение вместо генератора, поток завершается одним фреймом event: done с результатом — вызывающая сторона обрабатывает оба варианта одинаково.

Вызываем потоковый эндпоинт#

Любую функцию можно вызвать в потоковом режиме через POST /functions/{functionId}/invoke/stream. Ответ начинается сразу и остаётся открытым, пока обработчик не завершится:

curlbash
# -N disables buffering so events render as they arrive
curl -N -X POST "https://api.inquir.org/functions/{functionId}/invoke/stream" \
  -H "Authorization: Bearer $INQUIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": {"prompt": "stream me"}}'

# data: {"type":"status","message":"starting"}
# data: {"token":"Hello"}
# …
# event: log   — console output is interleaved as log events
# event: done  — emitted when the handler returns a value instead of a generator

Потоковая передача через API-шлюз#

Маршруты шлюза тоже передают поток: маршрут, привязанный к потоковому обработчику, пересылает SSE-фреймы на публичный URL по мере их появления. Так выглядит собственный эндпоинт с потоковой выдачей токенов LLM:

  • Соединение остаётся открытым в пределах таймаута функции — потоковая передача не продлевает лимит, она лишь доставляет вывод раньше.
  • Для потоковых путей отключена буферизация прокси, поэтому фреймы доходят до клиента без задержек на накопление.
  • Авторизация на маршруте (API-ключ или Bearer) действует для потоковых маршрутов так же, как для обычных.
  • Поток передают только маршруты с целью lambda. Маршрут, нацеленный на графовый пайплайн, отклоняет потоковый запрос с кодом 400.
  • SSE-соединение поддерживается heartbeat-комментарием : ping примерно раз в 25 секунд, чтобы простаивающие прокси не обрывали медленный поток.

Особенности поведения#

  • Вывод console.log вплетается в поток фреймами event: log — живые логи приходят вместе с данными без второго соединения.
  • Если обработчик упал посреди потока, поток завершится фреймом event: error с сообщением — проверяйте его, прежде чем считать закрытый поток успешным.
  • Потоковая передача работает и из тёплых, и из холодных контейнеров; при холодном старте просто позже приходит первый фрейм.