Caicaini
Начать

Возможности

Стриминг

Поставь stream: true в любом запросе /v1/messages или /v1/chat/completions, и токены будут возвращаться по Server-Sent Events. Та же аутентификация, тот же выбор модели, та же арифметика кредитов.

Базовый стрим

Добавь stream: true и читай тело ответа как text/event-stream. Большинство HTTP-библиотек делает это без дополнительных зависимостей. В примере ниже curl с флагом -N отключает буферизацию, чтобы токены было видно в реальном времени.

curl -N https://caicaini.com/v1/messages \
  -H "Authorization: Bearer cai_api_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "caicaini/auto",
    "max_tokens": 200,
    "stream": true,
    "messages": [{"role":"user","content":"Count to 10 slowly."}]
  }'

События на /v1/messages

Эндпойнт messages выдаёт последовательность именованных SSE-событий. У каждого фрейма строка event: и строка data: с JSON. Фреймы разделяются пустой строкой.

СобытиеСмысл
message_startПервый фрейм. Несёт id и количество входных токенов.
content_block_startНачался новый контент-блок. Тип может быть text, tool_use или thinking.
content_block_deltaКусок токенов для текущего блока. Форма delta соответствует типу блока.
content_block_stopТекущий блок завершён.
message_deltaНесёт финальный stop_reason и авторитетный credits_consumed.
message_stopПоследний фрейм. Прекращай чтение.
pingKeepalive примерно раз в 15 с. Игнорируй.
errorОшибка посреди стрима. Соединение может ненадолго остаться открытым. Считай терминальным событием.

Пример сырого вывода

сырой стрим
event: message_start
data: {"type":"message_start","message":{"id":"msg_01H...","type":"message","role":"assistant","content":[],"model":"caicaini/auto","stop_reason":null,"usage":{"input_tokens":12,"output_tokens":0}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"One, "}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"two, three..."}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":12,"output_tokens":24,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"credits_consumed":18}}

event: message_stop
data: {"type":"message_stop"}

События на /v1/chat/completions

Эндпойнт chat-completions стримит безымянные события: каждый фрейм — одна строка data: с объектом chat.completion.chunk, и поток заканчивается литералом data: [DONE].

сырой стрим
data: {"id":"chatcmpl_01H...","object":"chat.completion.chunk","created":1746748800,"model":"caicaini/auto","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"chatcmpl_01H...","object":"chat.completion.chunk","created":1746748800,"model":"caicaini/auto","choices":[{"index":0,"delta":{"content":"One, two, "},"finish_reason":null}]}

data: {"id":"chatcmpl_01H...","object":"chat.completion.chunk","created":1746748800,"model":"caicaini/auto","choices":[{"index":0,"delta":{"content":"three..."},"finish_reason":null}]}

data: {"id":"chatcmpl_01H...","object":"chat.completion.chunk","created":1746748800,"model":"caicaini/auto","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":12,"completion_tokens":24,"total_tokens":36,"credits_consumed":18}}

data: [DONE]

О чём не стоит забывать

  • Всегда разбирай фреймы по пустой строке, а не по отдельным строкам data:. Многострочные payload-ы в SSE валидны.
  • credits_consumed за поворот становится финальным на message_delta (messages) или на последнем чанке перед [DONE] (chat completions). Всё, что раньше — частичные значения.
  • Если стрим обрывается посреди работы, запрос всё равно стоит кредитов за уже сгенерированные токены. Если разрыв произошёл до того, как пришёл хоть какой-то вывод, мы вернём кредиты автоматически.
  • Количество одновременных стримов на ключ ограничено тарифом. См. Лимиты запросов.