TL;DR
Structured JSON Generation — техника явного указания JSON-схемы в промпте для получения структурированных ответов от LLM. Исследование OMNISTRUCT показало: современные модели умеют генерировать валидный JSON и следовать схемам почти безупречно (ошибки парсинга < 0.5%), но это не гарантирует качество контента. Модель может идеально соблюсти формат, но дать неправильный ответ.
Ключевой инсайт: соблюдение формата ≠ правильность ответа. LLM натренированы на JSON-данных и хорошо понимают структуру, но без явной схемы в промпте могут генерировать данные в неподходящем формате. GPT-4o показывает лучшие результаты на сложных задачах (планирование, рассуждения), малые модели хороши на простых (извлечение сущностей, связей).
Техника работает через добавление в системный промпт JSON-схемы, которая определяет структуру ответа: какие поля обязательны, какие типы данных, какая вложенность. Модель генерирует ответ строго по этой схеме. Для задач с фиксированной структурой (извлечение данных) достаточно одной схемы на все запросы. Для задач с переменной структурой (таблицы, вызовы функций) схема может меняться от запроса к запросу.
Схема метода
Системный промпт:
→ Описание роли ("helpful assistant")
→ JSON-схема с обязательными полями
→ Правило: "только JSON, без лишнего текста"
Пользовательский промпт:
→ Описание задачи
→ Входные данные
Результат:
→ Валидный JSON, следующий схеме
Всё происходит в одном запросе.
Пример применения
Задача: Ты анализируешь отзывы о новом российском сервисе доставки. Нужно извлечь из отзыва: что хвалят, что ругают, общую оценку (позитив/негатив/нейтрал), и упомянутые конкурентов.
Промпт:
Системный промпт:
Ты — аналитик отзывов. Отвечай строго в JSON формате по схеме:
{
"praise": ["список положительных аспектов"],
"criticism": ["список негативных аспектов"],
"sentiment": "positive/negative/neutral",
"competitors_mentioned": ["список упомянутых конкурентов"]
}
Не добавляй ничего кроме JSON в ответ.
---
Пользовательский промпт:
Проанализируй отзыв:
"Попробовал новый Самокат Про — доставили за 15 минут, это быстрее чем Яндекс Лавка обычно везёт.
Но приложение тормозит жутко, хуже чем у СберМаркета. Цены норм, ассортимент широкий."
Результат:
Модель вернёт структурированный JSON с четырьмя полями. В praise окажутся "быстрая доставка", "хорошие цены", "широкий ассортимент". В criticism — "тормозящее приложение". sentiment будет "positive" (больше хвалят). В competitors_mentioned появятся "Яндекс Лавка" и "СберМаркет". Формат гарантированно валидный, все обязательные поля заполнены.
Почему это работает
LLM обучались на огромных массивах JSON-данных — конфигах, API-ответах, структурированных логах. Модель знает синтаксис JSON на уровне паттернов. Когда видит схему с полями {"name": "string", "age": "number"}, она понимает: нужно заполнить эти поля правильными типами данных.
Но понимание структуры ≠ понимание задачи. Модель может идеально оформить ответ, но ошибиться в содержании. Например, правильно извлечь имена людей в поле "entities", но пропустить половину или перепутать типы. Схема задаёт формат контейнера, не гарантирует качество того, что в него попадёт.
Явная схема в промпте работает как контракт: "вот какие данные я жду, вот в какой структуре". Это убирает двусмысленность. Без схемы модель может вернуть список, словарь, текст — как ей удобнее. Со схемой — строго по спецификации.
Рычаги управления:
- Обязательные vs опциональные поля — пометь в схеме
"required": ["field1", "field2"], чтобы модель не пропускала ключевые данные - Ограничения значений — укажи
"enum": ["positive", "negative", "neutral"]для фиксированного набора вариантов - Типы данных —
"type": "number"вместо"type": "string"заставит модель вернуть число - Вложенность — простые плоские структуры работают надёжнее, глубокая вложенность может сбить модель
- Правило "только JSON" — без этого модель может добавить объяснения до или после JSON, сломав парсинг
Шаблон промпта
Системный промпт:
Ты — {роль}. Отвечай строго в JSON формате по схеме:
{
"поле_1": "{тип и описание}",
"поле_2": ["{если это список}"],
"поле_3": {
"вложенное_поле": "{для сложных структур}"
}
}
Не добавляй ничего кроме JSON в ответ.
---
Пользовательский промпт:
{описание задачи}
{входные данные}
Как заполнять:
- {роль} — кто модель: аналитик, помощник, эксперт
- {поле_N} — конкретные поля для твоей задачи с понятными названиями
- {тип и описание} — что должно быть в поле: "строка с именем", "число от 1 до 10", "список тегов"
- {описание задачи} — что нужно сделать одним предложением
- {входные данные} — текст/информация для обработки
Пример простой схемы для извлечения фактов:
{
"facts": ["список извлечённых фактов"],
"confidence": "high/medium/low"
}
Пример сложной схемы для анализа встречи:
{
"participants": [{"name": "имя", "role": "должность"}],
"decisions": ["список решений"],
"next_steps": [{"task": "задача", "owner": "ответственный", "deadline": "срок"}]
}
Ограничения
⚠️ Формат ≠ Качество: Модель может вернуть идеально структурированный JSON с неправильным содержанием. Схема гарантирует форму ответа, но не его правильность.
⚠️ Сложность задачи: На простых задачах (извлечение имён, дат, фактов) техника работает отлично. На сложных задачах требующих рассуждений (планирование, многошаговый анализ) структурированный формат может снижать качество — модель тратит "внимание" на соблюдение формата вместо глубокого анализа.
⚠️ Переусложнение схемы: Схемы с 20+ полями или глубокой вложенностью (объект в объекте в объекте) сбивают модель. Чем проще структура — тем надёжнее результат.
⚠️ Без схемы — хаос: Если просто написать "верни в JSON", модель придумает свою структуру. Схема обязательна для повторяемости результатов.
Как исследовали
Команда собрала бенчмарк OMNISTRUCT из 16 датасетов, покрывающих разные задачи: извлечение сущностей (NER), связей (RE), генерация таблиц, вызов функций, задачи с рассуждениями. Для каждой задачи создали JSON-схему и преобразовали правильные ответы в JSON-формат. Получился спектр от экстрактивных задач (найти информацию в тексте и переупаковать) до абстрактивных (порассуждать и структурировать результат).
Протестировали GPT-4o, Llama 3.1, Qwen 2.5, Phi-4 — от 7B до 32B параметров. Измеряли два аспекта: parsing errors (сколько раз JSON невалидный или не следует схеме) и content quality (правильность ответа по сути). Сравнили обычный промптинг с constrained decoding (Structured Outputs API от OpenAI), который гарантирует валидность через ограничение генерации на уровне токенов.
Результат удивил: parsing errors оказались редкостью (< 0.5% у всех моделей). Современные LLM настолько хорошо знают JSON, что почти не ошибаются в формате. GPT-4o вообще выдал 0% ошибок парсинга — constrained decoding ему не нужен. Но разрыв в качестве контента огромен: GPT-4o обгоняет малые модели на 10-20 пунктов на сложных задачах (планирование встреч, сложная генерация таблиц). На простых задачах (NER, RE) даже Llama 3.1-8B показывает приличные 60-70% F1.
Почему так? Логика такая: соблюдение формата — это поверхностный навык, выученный на примерах JSON в тренировочных данных. Правильность содержания — это глубокое понимание задачи. Малые модели научились первому, но им не хватает мощности для второго на сложных задачах.
Затем команда попробовала дистиллировать GPT-4o: синтезировали 20К примеров структурированных задач, дообучили Llama 3.1-8B. Результат: на NER/RE модель догнала GPT-4o (+7-15 пунктов к базе), на функциях подтянулась (+5 пунктов), но на рассуждениях и планировании всё равно отстаёт. Инсайт: малую модель можно научить хорошо структурировать экстрактивные задачи, но для абстрактивных нужна фундаментальная мощность большой модели.
Адаптации и экстраполяции
🔧 Техника: Добавить поле "reasoning" → увидеть логику модели
Базовая схема возвращает только результат. Добавь поле для объяснений:
{
"reasoning": "пошаговое объяснение как пришёл к ответу",
"result": {
"основные поля ответа"
}
}
Модель заполнит reasoning своими рассуждениями, потом result. Это помогает проверить логику и отловить ошибки в выводах.
🔧 Техника: Итеративное уточнение структуры
Если не уверен какая схема нужна — начни с простой, попроси модель предложить улучшения:
Вот моя задача: {задача}
Вот моя схема: {схема}
Проанализируй: какие поля я упустил? Какие лишние?
Предложи улучшенную схему в том же JSON формате.
Модель вернёт доработанную схему — используй её в следующем запросе.
🔧 Комбинация: Structured Output + Верификация
Сначала получи структурированный ответ, затем попроси модель проверить себя:
Запрос 1: [схема выше] → получаешь JSON Запрос 2:
Вот задача: {задача}
Вот ответ в JSON: {ответ из запроса 1}
Проверь: все ли поля заполнены правильно?
Где могут быть ошибки? Верни улучшенную версию в том же формате.
Двойная проверка снижает ошибки контента, сохраняя структуру.
Ресурсы
OmniStruct: Universal Text-to-Structure Generation across Diverse Schemas
Авторы: James Y. Huang, Wenxuan Zhou, Nan Xu, Fei Wang, Qin Liu, Sheng Zhang, Hoifung Poon, Muhao Chen
University of Southern California, University of California Davis, Microsoft Research
