LLM API и интеграция
JSON от нейросети: как получить строгий формат ответа
Просьба «ответь в JSON» работает на демо и ломается на проде: модель добавляет пояснение перед структурой, оборачивает её в блок кода, теряет поле или возвращает число строкой. Надёжный способ один — режим строгого вывода, где формат гарантируется не уговорами, а самим механизмом генерации. Поддержан он не везде: в нашем каталоге на 30 августа 2026 года capabilities.json_output помечен verified у шести позиций из сорока одной, у тридцати стоит unknown. Разбираем, чем два подхода отличаются, как жить с моделями без гарантии, и почему строгий вывод гарантирует форму, но никогда — содержание.
Почему просьба в промпте ненадёжна
Стоит понять причину, иначе кажется, что достаточно формулировку получше подобрать.
Модель генерирует текст по одному токену за раз, выбирая каждый следующий из распределения вероятностей. Слова «верни только JSON» смещают это распределение в нужную сторону — но не запрещают ничего. Вероятность, что после закрывающей скобки пойдёт пояснение, уменьшается, а не обнуляется.
Отсюда набор типовых поломок, которые видел каждый, кто это пробовал:
- Пояснение вокруг структуры. «Вот запрошенные данные:» перед JSON и «Дайте знать, если нужно что-то ещё» после.
- Обёртка в блок кода. Тройные обратные кавычки с пометкой языка. Парсер об них спотыкается.
- Пропущенное поле. Особенно необязательное или то, для которого модель не нашла данных.
- Неверный тип. Число строкой,
"true"вместоtrue, дата в произвольном виде. - Изобретённое поле. Модель добавляет то, чего в схеме не было, потому что «так логичнее».
Все пять случаев редкие. В этом и проблема: на сотне тестовых запросов вы их не увидите, а на десяти тысячах боевых получите каждый.
Как устроен режим строгого вывода
Здесь принципиально другой механизм, и он объясняет, откуда берётся гарантия.
Вы передаёте не просьбу, а схему: какие поля, каких типов, какие обязательны. Дальше ограничение работает на уровне выбора токенов: если по схеме сейчас должна идти открывающая скобка, все остальные варианты просто исключаются из выбора. Модель физически не может сгенерировать невалидную структуру — не потому что не хочет, а потому что таких вариантов ей не предлагают.
Отсюда три следствия, которые стоит держать в голове.
Форма гарантирована, содержание — нет. Поле email будет строкой на своём месте. Будет ли в нём настоящий адрес из документа или выдуманный — вопрос к качеству модели, а не к режиму.
Схема — тоже часть промпта. Она уходит в модель и оплачивается как входные токены. Развесистая схема с длинными описаниями полей стоит денег при каждом обращении — как это считать.
Слишком жёсткая схема портит ответы. Если вы обязали поле, для которого в исходных данных ответа нет, модель обязана его чем-то заполнить. И заполнит — выдумкой. Необязательные поля здесь не роскошь, а способ получить честное «не нашёл».
Где это поддержано в каталоге
Цифры из живой выдачи GET /v1/models на 30 августа 2026 года.
Значение capabilities.json_output | Позиций |
|---|---|
verified | 6 |
unknown | 30 |
| поле отсутствует | 5 |
Пять позиций без поля — это модели генерации изображений и rerank, к которым вопрос не применим.
Про unknown нужна прямая формулировка, потому что его регулярно читают неправильно. Это не «не поддерживает». Это «мы не проверяли». Модель вполне может уметь строгий вывод — но раз проверки не было, ставить такую позицию в обязательства перед своим клиентом нельзя, пока вы не убедились сами. Как устроены остальные поля контракта, разбирали в материале про чтение цены и возможностей через API.
Проверка своими силами занимает вечер: прогнать пару сотен реальных запросов и посчитать, сколько ответов распарсились с первого раза. Ниже ста процентов — гарантии нет, каким бы ни было поле.
Что делать с моделями без гарантии
Тридцать позиций из сорока одной — это большинство, и работать с ними приходится. Порядок действий, отсортированный по отношению эффекта к усилию.
Дайте пример ответа в промпте. Один заполненный образец действует сильнее, чем абзац требований к формату. Модель хорошо копирует структуру, которую видит.
Просите минимальную структуру. Плоский объект с пятью полями получается надёжнее, чем вложенный на три уровня. Каждый уровень вложенности — дополнительный шанс на ошибку.
Никогда не парсите ответ напрямую. Обязательный слой: вырезать блок кода, если он есть, найти первую открывающую и последнюю закрывающую скобку, распарсить, проверить обязательные поля и типы. Пятнадцать строк, которые снимают четыре поломки из пяти.
Повторяйте при неудаче — с ограничением. Не распарсилось — отправьте запрос заново, приложив текст ошибки. Обычно хватает второй попытки. Жёсткий предел числа повторов обязателен, иначе цикл будет крутиться, пока не кончится баланс — как и с любыми повторами при отказах.
Логируйте неудачные разборы целиком. Не факт ошибки, а сам ответ модели. Через неделю такой лог сам покажет, что именно ломается, — без него вы будете чинить наугад.
Строгий вывод и вызов функций
Полезно понимать связь, потому что механизм под ними один.
Function calling — это по сути и есть структурированный вывод: модель возвращает название функции и аргументы в заданной схеме. Разница в назначении, а не в устройстве.
Отсюда практический приём: если нужен строгий формат, а режим JSON у модели не проверен, попробуйте описать желаемую структуру как функцию. Поддержка вызова функций и поддержка строгого вывода в полях каталога помечены раздельно, и бывает, что первое проверено, а второе нет.
Обратное тоже верно. Если вам нужны просто данные в формате, а никаких действий выполнять не надо, режим строгого вывода проще: не нужно ни описывать функцию, ни обрабатывать намерение её вызвать.
Чего строгий вывод не решает
Раздел, из-за непонимания которого возникает ложное чувство надёжности.
Не проверяет данные на осмысленность. Схема требует число — модель вернёт число. Что это число взято из документа, а не придумано, схема не гарантирует никак.
Не заменяет валидацию в вашем коде. Дата будет строкой, но существует ли такая дата — вопрос к вам. Идентификатор будет корректного типа, но есть ли такая запись в базе — тоже.
Не делает ответы одинаковыми. Два запуска на одном запросе дадут разное содержимое при одинаковой структуре — почему так происходит.
Не отменяет опасности чужого текста. Если в разбираемом документе спрятана инструкция, строгая схема ей не помешает попасть в поля ответа.
Как проектировать схему
Несколько правил, которые снимают большую часть проблем ещё до первого запроса.
Плоско лучше вложенного. Каждый уровень вложенности добавляет модели возможность ошибиться и вам — возможность неверно распарсить. Если структуру можно развернуть в плоский объект, разверните.
Обязательных полей должно быть мало. Обязательное поле, для которого в исходных данных нет ответа, — прямое приглашение к выдумке. Оставляйте обязательными только то, что есть в источнике всегда.
Заведите поле для «не нашёл». Флаг вида found: false или отдельное поле с причиной даёт модели легальный способ сказать «данных нет» вместо того, чтобы заполнять пустоту.
Называйте поля так, как их назвал бы человек. Имя поля — это подсказка о содержимом. date_of_birth понятнее, чем dt2, и результат будет точнее.
Перечисления вместо свободного текста. Там, где вариантов конечное число, задавайте список допустимых значений. Это снимает целый класс расхождений в формулировках.
Чего мы не утверждаем
Не описываем синтаксис запроса. Он различается между протоколами и версиями; актуальную схему смотрите в документации.
Не переносим проверку между моделями. verified у одной позиции ничего не говорит о соседней, даже внутри одного семейства.
Не обещаем, что доли сохранятся. Шесть из сорока одной — состояние на 30 августа 2026 года. Каталог меняется, и единственный надёжный источник — живая выдача.
Что держать в голове
Просьба «ответь в JSON» смещает вероятности, но ничего не запрещает: редкие поломки на проде становятся регулярными. Строгий вывод гарантирует форму механизмом генерации, но проверен в каталоге у шести позиций из сорока одной — у остальных стоит unknown, и это повод проверить самому, а не повод отказываться.
И главное ограничение, которое стоит проговорить ещё раз: гарантируется форма, не содержание. Валидация данных остаётся вашей работой при любом режиме.
Как мы проверяем факты и что храним из запросов — на странице о проекте и в llms.txt. Проверить строгий вывод на нужной модели можно по ключу за вечер: keydealer.ru/login.
Частые вопросы
Как заставить нейросеть отвечать в JSON?
Есть два способа: попросить словами в промпте и включить режим строгого вывода, если модель его поддерживает. Первый работает почти всегда, но не гарантирует формат; второй гарантирует, но доступен не везде.
Почему модель добавляет текст вокруг JSON?
Потому что для неё это обычная генерация текста. Без режима строгого вывода ничто не мешает ей написать пояснение до или после структуры.
Где посмотреть, поддерживает ли модель строгий вывод?
В ответе GET /v1/models, поле capabilities.json_output. На 30 августа 2026 года из 41 позиции каталога значение verified стоит у шести.
Что означает статус unknown?
Что проверка не проводилась. Это не «не работает», но и закладывать такую модель в обязательства перед клиентом нельзя без собственного теста.
Гарантирует ли строгий вывод правильные данные?
Нет. Он гарантирует только форму: поля на месте, типы верные. Содержимое полей модель по-прежнему может выдумать.