Как только языковая модель становится частью программы, а не собеседником, возникает задача: ответ должен быть машиночитаемым. Не абзац текста, а структура с полями, которую можно разобрать и передать дальше.
Задача выглядит простой и решается за пять минут «попроси вернуть JSON». А потом в проде выясняется, что раз в сотню запросов приходит текст с пояснением перед скобкой, оборванная структура или поле с неожиданным типом. Разберём, как получать структуру надёжно.

Три уровня надёжности
Способы получить структуру различаются по гарантиям.
Просьба в промпте. «Ответь в формате JSON». Работает в большинстве случаев и ломается в остальных. Модель может добавить пояснение, обернуть в блок кода, использовать одинарные кавычки. Подходит для черновиков и не подходит для рабочих систем.
Режим JSON. Многие интерфейсы позволяют потребовать, чтобы ответ был корректным JSON. Гарантирует синтаксическую корректность, но не структуру: поля могут отличаться от ожидаемых.
Строгий вывод по схеме. Вы передаёте схему, и модель физически не может выдать ответ, ей не соответствующий: ограничение накладывается на процесс генерации. Это единственный способ с настоящими гарантиями, и если он доступен, использовать нужно его.
Практический вывод: не изобретайте разбор текста, если доступен строгий режим. Регулярные выражения для вытаскивания JSON из ответа это признак того, что выбран не тот уровень.
Проектирование схемы
Схема это не только контракт для кода, но и инструкция для модели. От её устройства зависит качество содержимого, а не только формы.
Говорящие имена полей
Модель понимает смысл поля по имени. Поле value ничего не сообщает, поле total_price_rub сообщает и смысл, и единицу.
Описания полей
Схема позволяет добавить описание к каждому полю. Это самый действенный способ повлиять на содержимое: описание работает лучше, чем такая же фраза в общем промпте.
Перечисления вместо строк
Если значений конечное число, перечисляйте их. Модель не сможет выдумать категорию, которой нет, а вам не придётся сопоставлять синонимы.
Плоская структура
Глубоко вложенные схемы модели даются хуже. Два уровня вложенности это комфортно, пять уже рискованно. По возможности выпрямляйте.
Поле для рассуждения
Полезный приём: добавьте первым полем короткое обоснование. Модель формулирует его до остальных полей, и качество решения растёт. Порядок полей в схеме имеет значение, потому что генерация идёт последовательно.
Обратная ошибка: ставить обоснование последним. Тогда оно объясняет уже принятое решение и ни на что не влияет.
Явный отказ
Обязательное поле для случая, когда данных не хватает. Без него модель заполнит поля выдуманными значениями, потому что схема требует их заполнить. Это одна из главных причин выдуманных данных в структурированном выводе.
Что делать с необязательными полями
Тонкое место. Строгие режимы часто требуют, чтобы все поля схемы присутствовали.
Рабочий приём: делать поле обязательным, но допускать пустое значение. Тогда модель явно говорит «данных нет» вместо того, чтобы придумывать.
Второй приём: пара полей, где первое булево и означает наличие данных, а второе содержит сами данные. Избыточно, но однозначно.
Валидация на своей стороне
Даже строгий режим гарантирует форму, а не смысл. Проверять нужно всё равно.
- Диапазоны. Схема допускает число, но не знает, что цена не может быть отрицательной.
- Согласованность полей. Дата окончания не раньше даты начала, сумма равна сумме позиций.
- Существование сущностей. Если модель вернула идентификатор, проверьте, что он есть в базе.
- Разумность значений. Модель может вернуть формально корректное, но абсурдное значение.
При провале валидации есть два пути: вернуть ошибку модели для исправления либо отбраковать результат. Первый путь работает хорошо, если в ошибке написано, что именно не так.
Частые проблемы
Обрыв на середине. Ответ упёрся в лимит длины, структура оборвана. Признак: JSON не закрывается. Решается увеличением лимита или сокращением схемы. Заметьте, что при строгом режиме обрыв всё равно возможен.
Выдуманные значения. Модель заполняет обязательное поле, когда данных нет. Решается явным полем отказа и описанием, разрешающим оставить пусто.
Неверный тип в строке. Число пришло строкой. Строгий режим это исключает, промпт нет.
Ответ обёрнут в блок кода. Классика при использовании промпта. Ещё одна причина не полагаться на промпт.
Списки не той длины. Модель вернула три элемента, когда ожидалось пять, или наоборот. Ограничения длины в схеме соблюдаются не всегда, проверяйте.
Смешение языков. В многоязычных задачах модель может вернуть значения не на том языке. Указывайте язык в описании поля.
Три типовые задачи и их схемы
Конкретика, которую можно взять за образец.
Разбор входящего письма
Нужно вытащить из свободного текста тип обращения, срочность, упомянутые номера заказов и краткую суть.
Схема: сначала поле с одним предложением о содержании письма, затем перечисление типов обращения, затем перечисление уровней срочности, затем список найденных номеров и в конце поле для случая, когда письмо не относится к теме вовсе.
Ключевой момент: список номеров должен допускать пустое значение. Без этого модель начнёт вписывать в него любые числа из письма, включая суммы и даты.
Оценка текста по критериям
Нужно поставить оценки по нескольким шкалам и обосновать.
Схема: по каждому критерию пара полей, сначала краткое обоснование, затем оценка числом с ограниченным диапазоном. Порядок принципиален: оценка, поставленная до обоснования, будет случайнее.
Дополнительно поле общей уверенности. Низкая уверенность это сигнал отправить случай человеку, а не принимать результат.
Заполнение карточки товара
Нужно из описания поставщика собрать структурированную карточку.
Схема: обязательные поля с описанием единиц измерения, перечисления для категорий, отдельное поле со списком того, чего в исходнике не нашлось. Последнее поле оказывается самым полезным: оно показывает, где данные поставщика неполны, вместо того чтобы прятать это за придуманными значениями.
Расход токенов на такую схему невелик, но при потоке в десятки тысяч карточек он заметен: как это считать, разбирали в материале про стоимость автоматизации на языковых моделях.
Стоимость и производительность
Структурированный вывод не бесплатен.
Схема передаётся с каждым запросом и занимает токены. Большая схема на сто полей может стоить дороже, чем сам запрос. Держите схему компактной: описания полезны, но краткие.
Строгий режим у некоторых поставщиков требует подготовки схемы при первом использовании, что даёт задержку на первом запросе и не даёт на последующих. Если схема генерируется динамически и каждый раз новая, вы платите этой задержкой постоянно.
Само ограничение генерации обычно не замедляет ответ заметно, а иногда ускоряет: модель не тратит токены на пояснения.
Когда структура мешает
Есть задачи, где жёсткая схема вредит.
Творческие тексты в структуре получаются хуже: ограничение формы влияет на содержание. Если нужен качественный текст и метаданные к нему, иногда выгоднее сделать два запроса.
Сложные рассуждения тоже страдают, если схема не даёт места для промежуточных шагов. Отсюда приём с полем обоснования.
Открытые вопросы, где ответ заранее не структурирован, в схему укладывать не нужно: получите насилие над данными.
Связь с вызовом функций
Механизмы близкие, и их путают.
Структурированный вывод это форма ответа модели пользователю. Вызов функции это запрос модели к вашему коду.
Технически они устроены похоже, оба опираются на схему. Но задачи разные: если вам нужны данные в определённом виде, берите структурированный вывод. Если нужно, чтобы модель что-то сделала, берите вызов функций.
Частая ошибка: использовать вызов функции только ради того, чтобы получить структуру. Работает, но сложнее и дороже, чем нужно.
Порядок внедрения
- Опишите схему минимально: только поля, которые действительно нужны дальше по коду.
- Добавьте описания к каждому полю.
- Заложите поле отказа.
- Включите строгий режим, если он доступен.
- Напишите валидацию смысловых ограничений.
- Соберите набор проверочных входов, включая заведомо неполные и противоречивые.
- Логируйте отбраковку и разбирайте её: это лучший источник улучшений схемы.
Частые вопросы
Гарантирует ли строгий режим корректность данных?
Нет. Он гарантирует соответствие схеме. Значения могут быть неверными по смыслу, поэтому валидация нужна всегда.
Что делать, если строгий режим недоступен?
Режим JSON плюс своя проверка по схеме плюс повтор при провале. Работает приемлемо, но требует обработки ошибок.
Насколько большой может быть схема?
Технически большой, практически качество падает после нескольких десятков полей. Если полей много, разбивайте задачу на несколько запросов.
Можно ли получать структуру от локальных моделей?
Да, ограничение генерации по грамматике поддерживается многими локальными средами и работает так же надёжно, как облачный строгий режим. Качество содержимого при этом может отставать, и здесь помогает дообучение под конкретную схему.
Влияет ли порядок полей на результат?
Да, и заметно. Генерация последовательная, поэтому поле, идущее раньше, влияет на последующие. Ставьте рассуждение перед выводом, а не после.


