Структурированный JSON от ИИ: как задать схему и проверить результат
Структурированный вывод помогает получить от модели JSON нужной формы, но не гарантирует правильность значений. Показываем, как спроектировать схему, обработать ошибки и проверить результат до передачи в приложение.
Редакция PENROUZ NEWSОпубликовано: 20 окт. 2026 г., 21:0512 мин чтения0 комментариев
Короткий ответ: задайте схему и всё равно проверяйте значения
Если ответ ИИ должен попасть в программу, таблицу или базу данных, одной просьбы «верни JSON» недостаточно. JSON может быть синтаксически корректным, но содержать пропущенное поле, неожиданное значение или неверный тип. Структурированный вывод решает первую часть задачи: приложение передаёт модели схему с допустимыми полями и типами, а поддерживаемый режим ограничивает форму ответа. После получения результата код отдельно проверяет смысл значений, статус завершения и возможность безопасно продолжить обработку.
OpenAI различает обычный JSON mode и Structured Outputs: первый гарантирует корректный JSON, но не соответствие конкретной схеме, а второй предназначен для соблюдения заданной структуры. Google также описывает structured output через поддерживаемое подмножество JSON Schema и прямо рекомендует валидировать значения в приложении. Поэтому схема уменьшает число ошибок формата, но не доказывает истинность текста внутри полей.
Когда нужен structured output, а когда function calling
Structured output подходит, когда конечный ответ модели должен иметь предсказуемую форму: карточка товара, извлечённые реквизиты, набор тегов, список шагов или данные для интерфейса. Function calling нужен, когда модель должна выбрать разрешённый инструмент и подготовить его аргументы, а приложение затем решает, выполнять ли действие. В руководствах OpenAI это разделено явно: схема ответа предназначена для структурирования результата пользователю, а вызов функции связывает модель с функциями и данными приложения.
Различие особенно важно для процессов с последствиями. Объект `{action: "refund", order_id: "A-17"}` ещё не является возвратом средств. Это предложение вызвать функцию с параметрами. Доверенный код должен проверить права, существование заказа, допустимость операции и подтверждение пользователя. Материал об ИИ-агентах и чат-ботах подробнее разбирает границу между решением модели и фактическим выполнением инструмента.
Начните с минимальной схемы
Хорошая схема описывает только данные, которые действительно нужны следующему шагу. Для каждого поля задайте тип, короткое назначение и обязательность. Для классификации используйте enum вместо произвольной строки. Для отсутствующего, но допустимого значения предусмотрите `null`, если конкретный API поддерживает такой вариант. Не помещайте длинные инструкции в названия полей: смысл лучше объяснить в `description`, а бизнес-правила — в системной инструкции и программной проверке.
Не копируйте весь объект приложения в запрос «на всякий случай». Чем больше вложенность и число необязательных веток, тем труднее понять ошибку и тем выше риск наткнуться на неподдерживаемую часть JSON Schema. Google предупреждает, что structured output реализует подмножество стандарта и слишком сложная или глубоко вложенная схема может быть отклонена. OpenAI также указывает, что поддерживаются не все возможности JSON Schema. Сначала используйте простой объект, затем добавляйте поля только вместе с тестом, который доказывает их необходимость.
Рабочий пример: разбор обращения в службу поддержки
Вымышленный сервис «Маяк» получает обезличенные обращения и хочет подготовить данные для оператора. Схема содержит пять полей: `category` с перечислением `delivery`, `payment`, `account` или `other`; `summary` как короткую строку; `order_id` как строку или `null`; `needs_human` как boolean; `missing_information` как массив строк. Модель не получает инструментов изменения заказа и не отправляет ответ клиенту. Её задача — только заполнить объект для последующей проверки.
Для текста «Заказ A-17 должен был прийти вчера, но статуса нет» ожидается категория доставки, идентификатор A-17, краткое описание и передача оператору. Для сообщения «Не могу войти» идентификатор заказа должен быть `null`, а в `missing_information` требуется указать, каких данных не хватает. Эти примеры задают ожидание, а не подтверждают реальную работу конкретной модели. Их нужно прогнать через выбранный API и сохранить фактические ответы.
Проверяйте JSON в два этапа
Первый этап — структурная проверка. Убедитесь, что запрос завершён штатно, результат можно разобрать, присутствуют обязательные поля, типы совпадают, enum не содержит неизвестных значений, а лишние свойства обрабатываются согласно правилам схемы. Отдельно распознавайте отказ модели и ответ, оборванный из-за лимита вывода. OpenAI перечисляет отказ и незавершённую генерацию среди случаев, когда ожидаемый структурированный результат может не появиться.
Второй этап — смысловая проверка. Схема способна гарантировать, что `order_id` является строкой, но не что такой заказ существует. `category` может формально попасть в enum, но быть выбрана неверно. Сверяйте идентификаторы с доверенной системой, диапазоны — с бизнес-правилами, даты — с календарём, а извлечённые факты — с исходным текстом. Здесь применим общий порядок из руководства по проверке ответов ИИ: отделить форму ответа от доказательств и не принимать уверенную формулировку за подтверждение.
Предусмотрите вход, который не подходит задаче
Схема заставляет модель заполнить предусмотренные поля даже тогда, когда исходный текст не содержит нужных сведений. OpenAI предупреждает: при несвязанном с задачей вводе модель может попытаться подогнать ответ под схему и выдумать значения. Добавьте явный выход: например, `status` со значениями `ok`, `insufficient_input` и `refused`, а для неизвестных данных разрешите `null` или пустой массив. В инструкции потребуйте не угадывать отсутствующие реквизиты.
Сам промпт остаётся важен: он задаёт задачу, исходные данные, границы и критерий готовности, тогда как схема отвечает за форму. Руководство по составлению промпта помогает сформулировать эти условия, но не заменяет программный валидатор. Если значение нарушает бизнес-правило, безопаснее вернуть объект на повторную обработку или человеку, чем автоматически исправлять его догадкой.
Как собрать контрольный набор
Добавьте типовые, пограничные и ошибочные входы. Для учебного примера «Маяк» это обращения с идентификатором и без него, несколькими проблемами сразу, пустым текстом, незнакомой категорией, просьбой выполнить запрещённое действие и содержимым, которое похоже на инструкцию для модели. Для каждого случая заранее запишите ожидаемый статус, допустимые значения и условие передачи человеку. Размер набора зависит от риска и разнообразия задачи; универсального числа примеров нет.
После запуска считайте отдельно ошибки разбора, несоответствия схеме, неверные значения, необоснованно заполненные поля, отказы и обрывы. Сохраняйте версию модели, схему, инструкцию и сырой ответ. Если поменять всё одновременно, источник улучшения определить нельзя. При обновлении схемы добавьте тест, из-за которого изменение понадобилось, и проверьте обратную совместимость потребителя данных.
Проверка результата
Процесс готов к ограниченному использованию, если приложение отличает успешный объект от отказа и незавершённого ответа, валидирует структуру и значения, не исполняет предложенные действия без контроля и передаёт нестандартные случаи человеку. Structured output сокращает количество ручного разбора и ошибок формата, но надёжность появляется только вместе с узкой схемой, проверяемой инструкцией, контрольным набором и программными ограничениями.