Artfical AI / API
Получить API-ключ Открыть tAI
Начало работы

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

Установите "stream": true, и тот же самый эндпоинт будет возвращать ответ постепенно, через server-sent events, вместо того чтобы ждать полного завершения генерации.

Зачем использовать потоковую передачу

Запрос без потоковой передачи блокируется, пока модель не закончит генерировать весь ответ целиком, и только потом возвращает его целиком за один раз. Для короткого ответа это почти незаметно. Для длинного это означает ожидание в несколько секунд (иногда дольше), в течение которых на экране ничего не происходит, прежде чем появится хоть какой-то текст. Потоковая передача решает эту проблему, отправляя ответ по частям, по мере того как модель его генерирует, так что клиент может начать отрисовывать текст уже через доли секунды после отправки запроса, а не ждать всё целиком. Это разница между чат-интерфейсом, который ощущается мгновенным, и тем, который кажется зависшим на каждом сообщении. Это опциональная возможность, и она не стоит ничего дополнительно.

Включение потоковой передачи

{
  "model": "tai-4.1",
  "messages": [{"role": "user", "content": "1'den 5'e kadar say"}],
  "stream": true
}

Content-Type ответа становится text/event-stream вместо application/json. Каждая строка события имеет префикс data: , а соединение остаётся открытым и отправляет по одному событию на каждую порцию нового контента, пока поток не завершится буквальной строкой data: [DONE].

Формат чанка

Большинство чанков несут небольшой фрагмент только что сгенерированного текста в choices[0].delta.content:

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": "1"}, "finish_reason": null}]}

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": ", 2"}, "finish_reason": null}]}

Последовательное соединение всех значений delta.content по порядку, по всем чанкам, восстанавливает полный текст ответа. Формирование этой конкатенации — задача клиента; API ни на каком этапе не отправляет накопленный текст, только очередной инкремент, добавляемый каждым чанком.

Финальный чанк

Последний чанк, содержащий контент, несёт пустой delta и настоящий finish_reason ("stop" или "tool_calls", если модель запрашивает вызов инструмента, см. Вызов инструментов):

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}

Чанк с использованием токенов

После финального чанка отправляется ещё один чанк с пустым массивом choices и заполненным объектом usage, того же формата, что и поле usage в ответе без потоковой передачи:

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [], "usage": {"prompt_tokens": 2, "completion_tokens": 3, "total_tokens": 5}}

data: [DONE]

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

Чтение потока в коде

# Python, с использованием официального пакета openai
stream = client.chat.completions.create(
    model="tai-4.1",
    messages=[{"role": "user", "content": "Kısa bir şiir yaz"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Официальные SDK OpenAI (для Python и Node) уже умеют разбирать этот формат событий, поскольку это тот же формат, который использует их собственный API; никакой специфики tAI в клиенте не требуется, кроме указания base_url как https://api.artfical.com/v1, как описано на странице Аутентификация.

Поток всегда завершается корректно

Даже если что-то идёт не так на середине пути — генерация завершилась неудачей, запрос истёк по внутреннему таймауту, причина не важна — поток всё равно заканчивается видимым сигналом, а не просто обрывом соединения без объяснений. В этом случае вы увидите чанк с содержимым, включающим короткое уведомление в скобках, финальный чанк с "finish_reason": "stop", а затем [DONE] — то же корректно оформленное завершение, что и у обычного успешного потока. Клиенту следует всегда считать появление [DONE] однозначным концом хода, и не следует считать успешным поток, завершившийся без него; оборванное соединение без [DONE] означает, что запрос нужно считать неудавшимся и повторить, точно так же, как для запроса без потоковой передачи, у которого истёк таймаут.