stream: true переключает /api/v1/chat/completions на Server-Sent Events: вместо одного ответа в конце вы получаете прирастающий текст. Это единственный способ обойти потолок запроса в 300 секунд — поток идёт до 15 минут.
В примерах ниже
$TEXT_MODEL — переменная окружения с идентификатором модели из GET /api/v1/models. Идентификаторы не зашивают в код: состав каталога меняется. Разбор — в разделе Модели и цены.Формат кадра
Каждый кадр — одна строкаdata: с JSON-объектом chat.completion.chunk. Между кадрами идут пустые строки-разделители.
delta повторяет форму сообщения: role приходит в первом кадре, дальше идёт content, при рассуждении — reasoning и reasoning_content, при вызове функций — tool_calls. finish_reason приходит пустым (null) во всех промежуточных кадрах и заполненным в последнем.
Маркер [DONE]
Поток завершается строкой data: [DONE]. Это не JSON — парсить его как объект нельзя. Ниже, после [DONE], сервер может дописать технические поля ([DONE]-строка не обязана быть самой последней), поэтому прекращайте разбор на ней, а не на закрытии соединения.
Python
Кадр со списанием
Непосредственно перед[DONE] приходит кадр, у которого choices — пустой массив, а в usage лежит разобранный расход:
stream_options.include_usage — параметр на чат-эндпоинте ничего не отключает.
Списывание происходит по факту завершения генерации, а не по факту прочтения. Если кадр с
usage не пришёл — генерация не была оплачена как завершённая; сверяйте расход по эндпоинту баланса.Ошибка внутри потока
Если провайдер оборвал генерацию, в середине потока приходит кадр с объектомerror:
[DONE] не придёт.
Python
[DONE] — это сигнал, что что-то пошло не так, а не просто «поток закончился». Каждый кадр проверяйте на наличие error; формат ошибок разобран в Ошибках.
Деньги и разрыв соединения
Практические следствия:- Закрытие вкладки или отмена
fetchне освобождает деньги. - Слот параллельной генерации освобождается, а расход уже произведён.
- Не открывайте поток, если не планируете его читать: полная цена не зависит от того, сколько вы успели прочитать.
- Ставьте клиентский таймаут больше серверного, иначе обрыв будет на ровном месте.
Таймауты
Переход на
stream: true снимает 300-секундный потолок для длинных генераций. Клиент при этом должен быть готов держать соединение дольше: поставьте 900–1000 секунд.
Полный список ограничений — в разделе Лимиты.
Примеры
curl
Флаг-N отключает буферизацию вывода — без него curl накопит весь поток в памяти и напечатает разом в самом конце, хотя запрос отработал корректно.
cURL
Флаги
--line-buffered у grep и sed обязательны: без них пайп буферизует вывод блоками и поток снова выглядит как единый ответ в конце.Python, синхронно
Python
Python, асинхронно
Python
TypeScript
TypeScript
Отмена
Отмена на стороне клиента освобождает слот параллельной генерации, но не возвращает деньги — генерация завершится и будет оплачена. Способ не тратить средства здесь один: не начинать запрос.Что дальше
Запрос чату
Сводная таблица полей и формат кадра
Ошибки
Ошибки внутри потока и коды повторов
Лимиты
Таймауты и параллельные потоки
Учёт средств
Как читать списание из кадра
