Разделы документации
Формат ответа
Разбор объекта chat.completion: choices, finish_reason, usage и контроль расхода токенов
Ответ на POST /v1/chat/completions приходит одним JSON-объектом в формате Chat Completions. Кодировка всегда UTF-8, заголовок ответа: Content-Type: application/json; charset=utf-8. Русский текст приходит как обычные символы, декодировать вручную ничего не нужно.
Пример ответа
Поля объекта ответа
| Поле | Тип | Что означает |
|---|---|---|
| id | строка | Идентификатор ответа. Удобно писать в свои логи, чтобы потом сопоставить запрос и списание. |
| object | строка | Тип объекта. Для обычного ответа — chat.completion, для фрагмента стрима — chat.completion.chunk. |
| created | число | Момент создания ответа, секунды Unix-времени (UTC). |
| model | строка | Модель, которая фактически отработала: libra-fast или libra-pro. |
| choices | массив | Варианты ответа. Сейчас в массиве всегда один элемент с index = 0. |
| choices[].index | число | Порядковый номер варианта, начинается с нуля. |
| choices[].message | объект | Само сообщение: role всегда assistant, content — текст ответа. |
| choices[].finish_reason | строка | Почему генерация остановилась (см. ниже). |
| usage | объект | Счётчик израсходованных токенов. |
Как читать finish_reason
- stop — модель закончила мысль сама. Ответ полный, ничего дорезать не надо.
- length — упёрлись в max_tokens (или в остаток контекста). Ответ обрезан на полуслове: либо поднимите max_tokens (максимум 32 000), либо попросите продолжить, отправив полученный текст обратно в messages.
- content_filter — генерация прервана фильтром содержимого. Ответ может быть пустым или неполным.
Практическое правило: если вы собираете длинный текст, всегда проверяйте finish_reason перед тем, как показывать результат пользователю. Значение length — это не ошибка HTTP, код ответа остаётся 200, обрезку видно только по этому полю.
Блок usage и контроль расхода
- prompt_tokens — сколько токенов заняло всё, что вы отправили: системное сообщение, история переписки и текущий вопрос.
- completion_tokens — сколько токенов модель сгенерировала в ответ.
- total_tokens — сумма первых двух. Именно она списывается с баланса аккаунта.
Баланс предоплаченный, в токенах, общий на весь аккаунт (не на отдельный ключ). После каждого ответа в журнал операций попадает запись типа «расход» на total_tokens. Стоимость токенов различается: вход у libra-fast — 337,50 ₽ за 1 млн, выход — 675 ₽ за 1 млн; у libra-pro — 450 ₽ и 900 ₽ за 1 млн. Повторно отправленный неизменный префикс запроса может попасть в кеш, он дешевле: 54 ₽ за 1 млн у libra-fast и 72 ₽ у libra-pro.
Так как история переписки уезжает на сервер целиком каждый раз, prompt_tokens растёт с каждым ходом диалога. Если расход неожиданно поднялся — смотрите именно на prompt_tokens: чаще всего дело в разросшейся истории, а не в длине ответов. Обрезайте старые сообщения или сворачивайте их в короткое резюме.
Ответ при стриминге
Если вы передали stream: true, ответ приходит потоком server-sent events, и целого объекта chat.completion не будет. Каждый фрагмент — это объект chat.completion.chunk с тем же id, где вместо message лежит delta с кусочком текста. Поток закрывается строкой data: [DONE].
Важная деталь для учёта: в предпоследнем фрагменте массив choices пустой, зато присутствует блок usage с итоговыми счётчиками за весь ответ. Читать расход при стриминге нужно именно оттуда — суммировать длину кусочков самостоятельно не надо и неправильно. Служебный параметр stream_options сервис проставляет сам, передавать его не требуется.