Перейти к основному содержанию
response_format просит модель отдать JSON вместо свободного текста. Это не гарантия валидности, а способ сильно сузить пространство ответов — поэтому всегда проверяйте результат.
В примерах ниже $TEXT_MODEL — переменная окружения с идентификатором модели из GET /api/v1/models. Идентификаторы не зашивают в код: состав каталога меняется. Разбор — в разделе Модели и цены.

Три значения type

Требование слова «JSON» в промпте при json_object — не наш каприз, а требование провайдера: без него запрос отклоняется. Фраза «верни ответ в JSON» в системном или пользовательском сообщении выполняет его.

json_schema

Точная форма объекта:
name стоит сделать стабильным: одинаковое имя при неизменной схеме позволяет провайдеру переиспользовать скомпилированную схему, а переименование каждый раз сбрасывает этот кэш.
strict: true работает не у всех моделей. Там, где строгий режим не поддерживается, схема остаётся подсказкой: лишние поля и пропуски возможны. Валидация на своей стороне обязательна в обоих случаях.

Примеры схем

Плоский объект

Вложенный объект

Массив объектов

Перечисление

Ограничения на глубину вложенности, длину, размер схемы и поддержку отдельных конструкций задаёт провайдер модели. Схема, которую приняли вчера, может быть отвергнута сегодня — будьте готовы к 400 и упрощайте.

Запрос и разбор

content — строка с JSON. Её нужно распарсить один раз: json.loads, не два.

Отказ

Иногда модель не отвечает данными, а отказывается. Тогда content пуст, а причина лежит в message.refusal:
Проверяйте refusal до попытки распарсить content:
Python
Поле refusal заполняется не у всех моделей, и вместо честного отказа часть из них возвращает content с объяснением обычным текстом. Отказ может выглядеть как JSON с пустыми полями. Всегда валидируйте содержимое, а не только факт его наличия.

Поддержка по моделям

Нативный структурированный вывод есть не у всех моделей. Если модель его не поддерживает, response_format может быть проигнорирован: запрос пройдёт, вернётся обычный текст, и ошибки не будет. Проверяйте на конкретной модели, а не по факту приёма запроса.

Запасной путь

Если модель не поддерживает нативный формат, разбирайте JSON из текста в markdown-ограждении. Модели часто оборачивают объект в json … , но могут добавить преамбулу или эпилог — вырезайте строго по ограждениям.
Python
Этот путь ненадёжен и остаётся запасным. Он ломается на вложенных ограждениях, на объяснениях вокруг объекта и на усечённом ответе. Основной режим — json_schema плюс валидация.

Валидация

Единственная рекомендуемая практика — всегда валидировать по схеме. Ошибки не подтверждены, но встречаются, и цена ошибки — неверное действие в вашем приложении.

pydantic

Python
model_json_schema() на стороне Python решает проблему рассинхрона: схема в запросе и схема валидации генерируются из одного объявления. Отдельный JSON Schema поддерживайте вручную только ради совместимости с языком, в котором нет генератора.

zod

TypeScript

Что дальше

Вызов функций

Когда модели нужны действия, а не данные

Запрос чату

Сводка полей запроса и формат ответа

Ошибки

Что приходит вместо ответа

Учёт средств

Сколько стоит такой запрос