TL;DR
Исследование показало, что правильная стратегия промптинга при извлечении структурированных данных из текста важнее параметров модели. Две стратегии показали лучшие результаты: P (явная инструкция со схемой и примером в промпте) и PJ+ (то же + передача схемы через API). Обе работают в обычном чате — достаточно дать модели JSON-схему и пример объекта.
LLM плохо справляются с извлечением структурированных данных "в лоб". Попросишь вытащить информацию в JSON — модель либо вернёт невалидный JSON (синтаксическая ошибка, лишний текст, сломанная структура), либо валидный но с неправильными данными (пропущенные поля, искажённые значения). Маленькие модели особенно нестабильны: то работают, то ломаются на одинаковых задачах.
P-стратегия даёт меньше семантических ошибок, но иногда ломается структурно (особенно на слабых моделях). PJ+-стратегия почти всегда возвращает валидный JSON, но чаще содержит неправильные значения. Выбор зависит от приоритета: нужна ли гарантия структуры (используй PJ+) или точность данных (используй P). На хороших моделях обе работают отлично, на слабых — приходится выбирать трейдофф.
Две стратегии извлечения
P-стратегия (Prompt-only):
Инструкция в промпте: "Верни JSON по этой схеме"
+ JSON-схема с типами полей
+ Пример заполненного объекта
→ Модель видит явную структуру и образец
PJ+-стратегия (Prompt + JSON Schema):
То же что P
+ API-параметр format с JSON-схемой (где доступно)
→ Модель принудительно следует схеме
Обе стратегии работают в одном запросе к модели.
Пример применения
⚠️ Зона применения: Тексты с явной информацией (заявки, описания, заказы). Не подходит для извлечения из текстов, где нужна интерпретация контекста или вывод недостающих данных.
Задача: Вытащить данные о заказе из сообщения клиента в техподдержку Озона.
Промпт (P-стратегия):
Извлеки информацию из сообщения клиента и верни в формате JSON по
этой схеме:
{
"order_id": "строка",
"item_name": "строка",
"quantity": число,
"issue_type": "строка",
"contact_phone": "строка"
}
Пример:
{
"order_id": "OZ-12345678",
"item_name": "Наушники Sony WH-1000XM5",
"quantity": 2,
"issue_type": "не пришёл товар",
"contact_phone": "+79161234567"
}
Сообщение клиента:
"Здравствуйте! Заказ OZ-87654321, три пары кроссовок Adidas Ultraboost.
Один товар пришёл не того размера, нужна замена. Связаться можно по
номеру +79267778899."
Результат:
Модель вернёт JSON-объект со всеми полями: order_id, item_name (из описания "кроссовки Adidas Ultraboost"), quantity: 3, issue_type (классифицирует как "неправильный размер" или близко по смыслу), contact_phone.
С P-стратегией: высокая точность значений, но на слабых моделях может обернуть JSON в текст или сломать синтаксис.
С PJ+-стратегией (если модель поддерживает API-параметр): всегда валидный JSON, но может неточно извлечь item_name или issue_type.
Почему это работает
Слабость LLM: Модели генерируют текст последовательно, без явного "планирования структуры". При запросе "верни JSON" они балансируют между формированием синтаксиса (фигурные скобки, кавычки, запятые) и извлечением смысла (найти в тексте order_id, понять что именно заказывали). Модель может сфокусироваться на одном в ущерб другому.
Сильная сторона LLM: Модели отлично копируют паттерны из примеров. Дашь схему с типами + заполненный пример → модель понимает и структуру, и формат значений. Это few-shot learning в действии: один пример кардинально улучшает качество.
Как работают стратегии:
P-стратегия даёт модели явную схему и образец в контексте. Модель следует паттерну, но полагается на собственное понимание JSON-синтаксиса — поэтому иногда ломается структурно, зато внимательнее к значениям.
PJ+-стратегия добавляет внешнее ограничение через API (constrained decoding): модель не может сгенерировать невалидный JSON. Это 100% гарантирует структуру, но отвлекает внимание модели от точности значений — она тратит "мощность" на соблюдение схемы.
Трейдофф: Защита от структурных ошибок → больше семантических ошибок. Это как вести машину с GPS-навигатором: меньше заблудишься (валидный JSON), но можешь пропустить нужный поворот (неправильное значение).
Рычаги управления:
- Сложность схемы — добавь только критичные поля, уберёшь необязательные → модель сфокусируется на главном, меньше ошибок.
- Детализация примера — дай пример с краевыми случаями (пустая строка, ноль, массив) → модель лучше обработает нетипичные данные.
- Выбор стратегии — нужна стабильность структуры? PJ+. Нужна точность данных? P.
Шаблон промпта (P-стратегия)
Извлеки информацию из текста и верни в формате JSON по этой схеме:
{схема_с_типами}
Пример заполненного объекта:
{пример_объекта}
Текст:
{исходный_текст}
Что подставлять:
{схема_с_типами}— JSON-объект с названиями полей и типами ("строка", число, массив) вместо значений{пример_объекта}— полностью заполненный JSON с реалистичными данными, не из твоей задачи (чтобы модель не скопировала значения){исходный_текст}— текст, из которого нужно извлечь данные
Шаблон промпта (PJ+-стратегия)
Извлеки информацию из текста и верни в формате JSON по этой схеме:
{json_schema_спецификация}
Пример заполненного объекта:
{пример_объекта}
Текст:
{исходный_текст}
Дополнительно: При вызове через API (OpenAI, Anthropic, локальные модели с поддержкой structured outputs) — передай {json_schema_спецификация} в параметр response_format или аналогичный.
Что подставлять:
{json_schema_спецификация}— полная JSON Schema (с"type","properties","required"и т.д.){пример_объекта}— заполненный JSON{исходный_текст}— исходный текст
🚀 Быстрый старт — вставь в чат:
Вот две стратегии извлечения JSON из текста. Адаптируй под мою задачу:
{опиши что извлекаешь и из какого текста}.
Создай JSON-схему с нужными полями, заполни пример, и дай мне готовый
промпт для извлечения.
[вставить шаблон P-стратегии выше]
LLM спросит какие поля нужны, какие типы данных, примеры значений — потому что для создания схемы и примера нужно понимать структуру данных. Она возьмёт паттерн "схема + пример + инструкция" и адаптирует под твою задачу.
Ограничения
⚠️ Глубоко вложенные структуры: Исследование не покрывает JSON с глубиной больше 4 уровней. Авторы пытались генерировать сложные тесты, но модели ломались даже на этапе создания примеров — упускали значения, путали вложенность.
⚠️ Интерпретация и вывод: Стратегии работают когда вся информация явно есть в тексте. Если нужно додумать, классифицировать неоднозначно или вывести скрытый смысл — точность падает. Метод извлекает, не интерпретирует.
⚠️ Разные модели — разные слабые места: Семейство Phi3 катастрофически ломалось на P-стратегии (много failed cases), другие модели справлялись. PJ+ выравнивает результат, но не панацея. На слабой модели придётся выбирать между структурой и точностью.
Как исследовали
Команда создала LLMStructBench — бенчмарк из 995 тестов на 5 сценариях (заявки на отпуск, IT-тикеты, регистрация на конференцию, займ оборудования, продление проекта). Каждый тест — пара "текст + корректный JSON". Сценарии различаются по сложности структуры: от плоских 5 полей до вложенных 10 полей с массивами объектов.
Тесты генерировали синтетически с помощью GPT-4o: сначала создавали валидные JSON-объекты, потом превращали их в естественные тексты (email-стиль). После — полностью вручную проверили: выкинули кейсы где текст не соответствовал JSON, поправили системные несоответствия. Это гарантировало что каждый тест имеет однозначное правильное решение.
Протестировали 22 open-source модели (от 0.6B до 70B параметров — Qwen, Phi, Gemma, Deepseek-R1, Llama) + GPT-4o как эталон. Каждую модель прогнали через 5 стратегий промптинга, различающихся по наличию явных инструкций, схемы, примера и API-параметров.
Измеряли двумя метриками:
Micro-F1 — точность на уровне полей: правильность ключей (25% веса) и значений (75% веса). За точное совпадение — полный балл, за близкие значения (например "42" vs 42) — частичный, за type-ошибки — ноль.
DOCmicro — доля полностью корректных документов. Один неправильный символ → весь тест не засчитан. Это отражает реальность: автоматизированные пайплайны часто требуют 100% валидный JSON с первой попытки.
Комбинированный Score = 50% Micro-F1 + 50% DOCmicro уравновешивает "почти правильно" и "идеально".
Главное открытие: На шкале результатов разброс между стратегиями промптинга оказался шире, чем между размерами моделей. Маленькая модель с PJ+-стратегией обгоняла большую модель с базовым промптом. Особенно ярко на семействе Phi3 (3.8B параметров): P-стратегия давала 130+ failed cases, PJ+-стратегия — ноль failed, но больше ошибок в значениях.
Не ожидали: Явное указание схемы в API-параметре (JSON Schema constrained decoding) увеличивает семантические ошибки. Модель тратит "внимание" на соблюдение структуры → меньше фокуса на корректности данных. Это объясняет почему P-стратегия (без API-принуждения) иногда точнее по значениям, хотя и менее стабильна структурно.
Инсайт для практики: Если работаешь с надёжной моделью (топовая open-source или GPT-4) — используй P-стратегию для максимальной точности данных. Если модель слабая или нужна 100% гарантия парсинга → PJ+. Это не "одна стратегия лучше", это выбор приоритета: защита от структурных сбоев vs защита от искажённых значений.
Ресурсы
LLMStructBench: Benchmarking Large Language Model Structured Data Extraction
Sönke Tenckhoff, Mario Koddenbrock, Erik Rodner
University of Applied Sciences Berlin
