ПрименениеJSON

Структурированный вывод

JSON, схемы и валидированные ответы

Проблема: LLM создают красивые тексты, но вашему коду нужен JSON. Свободный текст ломает парсеры, имеет непредсказуемый формат и требует хрупких регулярных выражений для извлечения данных. Как получить надёжный, машиночитаемый вывод?

Решение: Укрощение свободного текста в структуры данных

Structured output (структурированный вывод) — это способ ограничить ответ LLM так, чтобы он следовал конкретной схеме: JSON-объекту, типизированному набору параметров функции или любой валидируемой структуре данных, вместо свободного текста. Представь, что ты даёшь модели форму для заполнения, а не чистый лист. Обычный промпт может вернуть «Конечно! Клиента зовут Анна, сумма заказа примерно 42 доллара.» — отлично читается человеком, но для кода это кошмар. Структурированный вывод заставляет тот же ответ принять вид { "name": "Анна", "total": 42.0 }, и так каждый раз.

Как это работает

Под капотом есть два основных механизма. JSON mode сообщает модели, что весь её ответ должен быть одним валидным JSON-документом, — это убирает «полезную» болтовню вокруг данных. Function calling (вызов функций, он же tool calling) идёт дальше: ты описываешь функцию и её параметры как схему, и API ограничивает генерацию так, что модель может выдать только аргументы, совпадающие по именам полей и типам с твоим описанием. Многие провайдеры реализуют это через ограниченное декодирование (constrained decoding) — на каждом шаге модель может выбрать только те токены, которые сохраняют вывод синтаксически валидным по схеме, так что некорректный ответ становится структурно невозможным, а не просто маловероятным.

Когда применять — и в чём подвох

Используй структурированный вывод всегда, когда ответ LLM напрямую подаётся в другой код: пайплайны извлечения данных, ответы API, запись в базу, вызовы инструментов агентом или генерация конфигов. Главный выигрыш в том, что можно выбросить хрупкие регулярки и парсинг строк и доверять форме данных. Ключевой подвох: валидный JSON — это не то же самое, что верные данные. Схема гарантирует форму (есть поле total, и оно число), но никогда не гарантирует смысл — модель всё ещё может галлюцинировать неправильное число или перевернуть булево значение. Например, попроси счёт в виде { "amount": number, "currency": string, "paid": boolean } — и получишь идеально валидный JSON, где amount ошибается на разряд, а paid перевёрнут. Всегда валидируй значения инструментом вроде Pydantic или Zod, а не только схему, и при ошибке возвращай её модели для одной-двух повторных попыток.

Представьте это как заполнение формы вместо написания сочинения:

  • 1. Определяем схему вывода: Пишем JSON Schema, модель Pydantic или интерфейс TypeScript, описывающий точную форму данных
  • 2. Включаем JSON mode или function calling: Передаём схему в API; модель теперь ограничена выводом, соответствующим этой структуре
  • 3. LLM генерирует вывод, соответствующий схеме: Модель заполняет поля как форму — имена полей, типы и вложенность гарантированы
  • 4. Парсим и валидируем по схеме: Десериализуем и запускаем валидацию Pydantic/Zod для выявления семантических ошибок, а не только ошибок формата
  • 5. Повторяем с описанием ошибки при невалидном результате: При ошибке валидации возвращаем сообщение об ошибке модели для самокоррекции (не более 2 попыток)

Где это используется?

  • Форматирование ответов API: Гарантированные JSON-ответы, которые парсеры могут использовать без обработки ошибок формата
  • Пайплайны извлечения данных: Извлечение структурированных полей (имя, дата, сумма) из неструктурированных документов в масштабе
  • Автоматизация заполнения форм: Преобразование произвольных форм или писем в валидированные записи базы данных
  • Генерация конфигурации: Превращение описаний фич на естественном языке в типизированные объекты конфигурации или infrastructure-as-code
  • Частая ловушка: семантически неверные значения: Даже в JSON mode LLM может выдать валидный JSON с неверными значениями (придуманные даты, инвертированные булевы) — всегда валидируйте значения, а не только форму схемы, с помощью Pydantic или Zod

Интересный факт: Без JSON mode LLM добавляют "полезный" текст вокруг JSON примерно в 30% случаев: "Вот запрошенный JSON: {...}". С JSON mode это снижается до 0%. Function calling идёт дальше — гарантирует не просто валидный JSON, но валидный JSON, соответствующий вашей точной схеме. Разница в ошибках парсинга: 30% → 0,5%.

Попробуйте сами!

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

Structured Output Explorer

Интерактивно

Входной текст

Привет, я Сара Чен из Acme Corp. Меня можно найти по sarah@acme.com или позвонить 555-0123. Я в Сан-Франциско и хотела бы обсудить предложение о партнёрстве на Q3.

Free Text Mode

Отправитель — Сара Чен из компании Acme Corp. Её email: sarah@acme.com, телефон: 555-0123. Она находится в Сан-Франциско и хочет обсудить предложение о партнёрстве Q3.

Как извлечь email? regex? split?
Порядок полей меняется каждый раз
Лишний текст делает парсинг хрупким
JSON Mode
Key Insight
  • JSON mode устраняет 30% ответов, которые оборачивают JSON в «полезную» прозу.
  • Function calling гарантирует соответствие ВАШЕЙ схеме — поля, типы, обязательные/опциональные.
  • Всегда валидируйте + retry: большинство ошибок формата решаются за 1 retry с обратной связью.

Частые вопросы

Что такое JSON mode и когда его использовать?

JSON mode заставляет LLM выдавать валидный JSON. Используйте когда нужен машиночитаемый вывод — ответы API, извлечение данных, заполнение форм. Большинство провайдеров поддерживают через параметр (response_format: json_object).

Как function calling помогает со структурированным выводом?

Function calling позволяет задать точную схему (параметры с типами, обязательные поля, enum). LLM заполняет схему вместо генерации свободного текста. Это гарантирует соответствие формату и позволяет типобезопасную интеграцию.

Что делать, если LLM вернёт невалидный вывод?

Реализуйте валидацию + повтор: распарсите вывод, проверьте по схеме, при ошибке отправьте сообщение об ошибке обратно LLM с просьбой исправить. Большинство сбоев решаются за 1 повтор. Установите лимит (2–3 попытки).

Можно ли получить вложенные или сложные структуры?

Да. Чётко определите вложенные схемы с примерами. Для очень сложных структур разбейте на несколько вызовов — сначала верхнеуровневые поля, затем детали каждого. Pydantic-модели отлично подходят для определения и валидации сложных схем.

Попробуй сам

Интерактивное демо этой техники

Сравнение техник
Демо режим
Предзаписанные ответы
ЗадачаНачинающийАнализ

Извлеки контактную информацию из подписи email в формате JSON

Без техники
Без техники
Промпт
Извлеки контакты из подписи: "Иван Петров, Директор по маркетингу, ООО ТехКорп, ivan@techcorp.ru, +7 (495) 123-45-67, techcorp.ru"
Ответ

Имя: Иван Петров Должность: Директор по маркетингу Email: ivan@techcorp.ru Телефон: +7 (495) 123-45-67

Токены:40/38
Время:310ms
Качество:
С applications-structured-output
С техникой
Промпт
Извлеки контактную информацию из подписи email и верни строго валидный JSON. **JSON-схема (все поля обязательны, null если отсутствует):** ```json { "name": "string", "title": "string | null", "company": "string | null", "email": "string | null", "phone": "string | null", "website": "string | null" } ``` **Правила:** - Телефон: оставь в исходном формате - Веб-сайт: добавь https:// если схема отсутствует - Возвращай только JSON, без пояснений и markdown-блока **Подпись:** "Иван Петров, Директор по маркетингу, ООО ТехКорп, ivan@techcorp.ru, +7 (495) 123-45-67, techcorp.ru"
Ответ

{ "name": "Иван Петров", "title": "Директор по маркетингу", "company": "ООО ТехКорп", "email": "ivan@techcorp.ru", "phone": "+7 (495) 123-45-67", "website": "https://techcorp.ru" }

👁️Явная JSON-схема с типами устраняет вариативность формата — модель знает точную структуру
🧠Требование null для отсутствующих полей важно для программной обработки — избегает KeyError
🔍Запрет markdown-блока (без ```json```) позволяет парсить ответ напрямую через JSON.parse()
Токены:140/80
Время:620ms
Качество:
Почему это работает

Для извлечения структурированных данных дайте модели точную JSON-схему с типами и правилом null для отсутствующих полей — это делает вывод программно парсируемым без постобработки.

1 / 2

Квиз по уроку

1 из 3

1.Что гарантирует JSON mode?

Практика

Создайте бесплатный аккаунт для решения челленджей

1 челленджей с AI-проверкой для этого урока

Связанные уроки:Information ExtractionText To Sql

Этот урок — часть структурированного курса по LLM.

Мой путь обучения