3,583 papers
arXiv:2604.16504 74 14 апр. 2026 г. FREE

Структурированное извлечение данных из документов: как правила в промпте дают +60% точности

КЛЮЧЕВАЯ СУТЬ
Одна и та же модель, одни и те же данные — разница в точности 60%. Всё дело в том, закрыл ли ты все дыры в инструкции или нет. Метод позволяет получать стандартизированные структурированные данные из любого документа — так, чтобы сто разных записей были сопоставимы между собой, а не каша из "кесарево", "C/S" и "К/С" в одном поле. Фишка: закрой каждое поле списком допустимых значений прямо в шаблоне вывода — модель перестаёт генерировать любой подходящий паттерн и начинает выбирать из списка. Добавь правила нормализации — и точность растёт без дообучения, без смены модели, без новых данных.
Адаптировать под запрос

TL;DR

Когда просишь LLM извлечь данные из документа и говоришь "напиши тип родов" — модель пишет что хочет. Строгое ограничение пространства вывода на уровне схемы ("тип родов — одно из: NVD, C/S, TOP") вместе с явными правилами нормализации ("дата всегда в формате ДД/ММ/ГГГГ, NAD = норма, ? = неизвестно") даёт более чем 60% улучшение точности на одних и тех же данных — без смены модели.

Главная находка: модель не угадывает правильный формат — она генерирует по паттерну. Без явного списка допустимых значений она "изобретает" свои варианты: кто пишет "кесарево", кто "C/S", кто "К/С" — всё разное, всё несопоставимо. Проблема не в том, что модель не понимает задачу. Проблема в том, что ты не закрыл все дыры в инструкции. Каждая неоднозначность — это ошибка на выходе.

Метод двухуровневый. Первый уровень — схема: перечисли допустимые значения для каждого поля прямо в шаблоне вывода. Второй уровень — правила нормализации: явно пропиши как обрабатывать сокращения, форматы дат, нестандартные обозначения. Всё это идёт в один промпт.


🔬

Схема метода

ШАГ 1: Базовый промпт с инструкцией → [что извлечь, зачем, общий контекст]

ШАГ 2: Правила нормализации → [явный список: как обробатывать форматы, 
         сокращения, нестандартные обозначения]

ШАГ 3: Шаблон вывода с дискретизацией → [JSON/список, где для каждого поля
         уже прописаны допустимые значения]

Всё три уровня — в одном промпте. Один запрос.

🚀

Пример применения

Задача: Фаундер SaaS-стартапа проводит 20+ интервью с клиентами в неделю. Записи — голос → автотранскрипт → каша из текста. Нужно извлекать структурированные данные по каждому интервью: боль, сегмент, готовность платить, стадия продукта у клиента.

Промпт:

Ты извлекаешь структурированные данные из транскрипта customer development интервью.

ПРАВИЛА НОРМАЛИЗАЦИИ:
- Если сегмент не назван явно — выводи "не определён"
- Готовность платить: только числа в рублях или "не обсуждалась"
- Если клиент использует общие слова ("дорого", "нормально") без цифр — пиши "не обсуждалась"
- Боль: одно предложение, максимум 15 слов, без цитат
- Стадия: только из допустимых значений ниже
- Если поле неясно — пиши "нет данных", не придумывай

ШАБЛОН ВЫВОДА (заполни строго по полям):
{
  "сегмент": "[B2B / B2C / не определён]",
  "размер_компании": "[1-10 / 11-50 / 51-200 / 200+ / не определён]",
  "основная_боль": "[одно предложение]",
  "стадия_клиента": "[ищет решение / тестирует альтернативы / 
                      есть текущее решение / не определён]",
  "готовность_платить": "[сумма в рублях / не обсуждалась]",
  "следующий_шаг": "[договорились о демо / отправить материалы / 
                     нет следующего шага / не определён]"
}

ТРАНСКРИПТ:
{вставь текст транскрипта}

Результат: Модель выдаст заполненный JSON строго по шаблону. Поля с явными допустимыми значениями будут стандартизированы — все 20 интервью окажутся сопоставимы между собой. Поля без данных получат "нет данных", а не выдуманный текст. Никакой вариативности в формулировках — одинаковые категории во всех записях.


🧠

Почему это работает

LLM — это паттерн-матчер. Она генерирует следующий токен, исходя из контекста. Когда ты пишешь "опиши тип доставки" — контекст открытый, и модель выбирает любой подходящий паттерн из тренировочных данных. Одна формулировка, другая, третья — все "правильные" с точки зрения языка, но несопоставимые между собой.

Когда ты пишешь "тип доставки — одно из: [самовывоз, курьер, почта]" — контекст закрытый. Модель видит список, понимает что нужно выбрать из него, и генерирует по этому паттерну. Вариативность исчезает не потому что модель "стала умнее" — просто ты убрал свободу интерпретации там, где она вредит.

Рычаги управления: - Количество правил нормализации → добавляй по одному за раз при каждой новой ошибке — легче отлаживать - Жёсткость списков → для критичных полей давай строгий список, для свободных полей (описания, комментарии) — оставь открытым - "Нет данных" как класс → всегда добавляй явно — иначе модель будет придумывать вместо того чтобы признавать неопределённость - Формат вывода → JSON удобен для копирования в таблицы, список с дефисами — для чтения глазами


📋

Шаблон промпта

Ты извлекаешь структурированные данные из {тип_документа}.

ПРАВИЛА НОРМАЛИЗАЦИИ:
- {правило_1: как обрабатывать нестандартные случаи}
- {правило_2: как форматировать конкретный тип данных}
- {правило_3: что делать с неявными или отсутствующими данными}
- Если поле неясно — пиши "нет данных", не придумывай

ШАБЛОН ВЫВОДА:
{
  "{поле_1}": "[{вариант_А} / {вариант_Б} / {вариант_В} / не определён]",
  "{поле_2}": "[{вариант_А} / {вариант_Б} / не определён]",
  "{поле_3}": "[свободный текст, максимум {N} слов]",
  "{поле_4}": "[число / не обсуждалось]"
}

{тип_документа_заглавными}:
{вставь текст или описание документа}

Плейсхолдеры: - {тип_документа} — транскрипт, письмо, договор, отчёт, фото формы - {правило_X} — конкретное "если...то..." для твоего контекста - {поле_X} — название поля, которое хочешь извлечь - {вариант_Х} — допустимые значения через слэш - {N} — лимит слов для свободных полей


🚀 Быстрый старт — вставь в чат:

Вот шаблон для структурированного извлечения данных из документов. 
Адаптируй под мою задачу: {опиши свою задачу}. 
Задавай вопросы чтобы заполнить поля.

[вставить шаблон выше]

LLM спросит какие поля нужно извлекать, какие допустимые значения для каждого и что делать с пропусками — потому что без этого не сможет создать рабочую дискретизацию.


⚠️

Ограничения

⚠️ Только фронтирные модели: GPT-4o и выше, Claude Sonnet/Opus, Gemini 2.5+. Более старые и бюджетные модели часто возвращают список допустимых значений вместо выбора из него — не понимают что нужно выбрать, а не перечислить.

⚠️ Свободный текст не дискретизируется: Метод радикально помогает для полей с конечным числом вариантов. Для свободного описания (комментарии, пояснения) улучшение минимальное — там другая природа ошибок.

⚠️ 60% улучшение — на сложных, нестандартных данных: На чистых, однозначных текстах эффект меньше. Чем больше в исходнике сокращений, форматов и неоднозначностей — тем сильнее работают правила нормализации.

⚠️ Нужна постановка правил из опыта: Первые итерации промпта будут несовершенны. Правила нормализации пишутся по реальным ошибкам — смотришь где модель ошиблась, добавляешь правило, повторяешь.


🔍

Как исследовали

Команда из ЮАР взяла реальные рукописные медицинские формы беременных — 49 документов плюс 4 синтетических. Формы заполнялись разными сотрудниками клиник, часто в спешке: даты написаны вертикально, "NAD" вместо пустой строки, цифры "1/2/3" вместо слов "употребляет/бывший/не употребляет". Такие документы — nightmare даже для человека.

Протестировали 17 моделей с двумя вариантами промпта: базовым (только инструкция) и оптимизированным (инструкция + 16 правил нормализации + шаблон с допустимыми значениями). Результат удивил: оптимизация дала 60%+ улучшение по precision/recall — но почти не повлияла на взвешенные метрики (2-5%). Это говорит о том, что основной эффект — в редких и сложных полях, а не в частых и простых.

Ещё неожиданная находка: размер модели ≠ качество для OCR-задач. Gemini Flash (меньше) регулярно побеждал Gemini Pro (больше) несмотря на меньший бюджет токенов для рассуждений. GPT 5.4 обошёл значительно более дорогой GPT 5.2 Pro. Это намекает: для структурированного извлечения важнее обученность на нужных паттернах, а не общая мощность рассуждений.


💡

Адаптации и экстраполяции

🔧 Техника: Итеративное добавление правил → контроль качества вывода

Вместо того чтобы писать все правила сразу — запусти промпт на 3-5 примерах, посмотри где ошибки, добавь правило под каждую ошибку. Тот же принцип что в исследовании: авторы добавили 16 правил именно по реальным паттернам ошибок, не придумали их заранее.

🔧 Техника: "Нет данных" как обязательный класс → снижение галлюцинаций

Исследование фиксировало галлюцинации (модель придумывает поля которых нет). Решение простое: добавь в каждый пункт шаблона явный вариант "нет данных / не определён / не обсуждалось". Модель перестаёт придумывать — у неё появляется легитимный выход из неопределённости.

🔧 Экстраполяция: Принцип на задачи классификации текста

Та же логика работает когда просишь модель категоризировать — отзывы, заявки, письма. Вместо "определи тональность" → "тональность — одно из: [позитивная / негативная / нейтральная / смешанная]". Вместо "определи срочность" → "срочность — одно из: [критичная — нужен ответ сегодня / высокая — в течение дня / средняя — в течение недели / низкая]".


🔗

Ресурсы

Статья: "From Handwriting to Structured Data: Benchmarking AI Digitisation of Handwritten Forms"

Авторы: Sitwala Mundia, Nicholas Pather, Joshua Fouché, Karl-Günter Technau, Alex Welte, Thokozile Malaba, Ushma Mehta, Bruce A. Bassett

Организации: University of the Witwatersrand (ЮАР), Grai Labs, University of Cape Town, University of KwaZulu-Natal

Проект: UBOMI BUHLE Pregnancy Exposure Registry — ubomibuhle.org.za


📋 Дайджест исследования

Ключевая суть

Одна и та же модель, одни и те же данные — разница в точности 60%. Всё дело в том, закрыл ли ты все дыры в инструкции или нет. Метод позволяет получать стандартизированные структурированные данные из любого документа — так, чтобы сто разных записей были сопоставимы между собой, а не каша из "кесарево", "C/S" и "К/С" в одном поле. Фишка: закрой каждое поле списком допустимых значений прямо в шаблоне вывода — модель перестаёт генерировать любой подходящий паттерн и начинает выбирать из списка. Добавь правила нормализации — и точность растёт без дообучения, без смены модели, без новых данных.

Принцип работы

Модель — паттерн-матчер. Она генерирует следующий токен из контекста. Открытый контекст: пишешь "опиши тип доставки" — подходят десятки формулировок, все разные. Закрытый контекст: пишешь "тип доставки: [самовывоз / курьер / почта]" — одна строка, один выбор. Метод работает на двух уровнях сразу. Первый уровень — схема: для каждого поля перечисли допустимые значения через слэш прямо в шаблоне вывода. Второй уровень — правила нормализации: явно пропиши как обрабатывать сокращения, форматы дат, нестандартные обозначения, пустые поля. Проблема не в модели — она всё понимает. Проблема в том, что каждая неоднозначность в инструкции — это ошибка на выходе. Закрой неоднозначность — ошибка исчезает.

Почему работает

LLM генерирует по паттерну, а не «думает над правильным ответом». Когда поле открытое — контекст допускает любой вариант. Модель и права, и не права одновременно: ответ грамматически верный, но несопоставимый с остальными. Когда список допустимых значений явно задан в промпте — контекст закрыт. Модель видит структуру и выбирает из неё. Вариативность исчезает не потому что модель поумнела — ты просто убрал свободу там, где она вредит. В исследовании +60% точности получили на рукописных медицинских формах — максимально хаотичных данных: сокращения, нестандартные обозначения, неоднозначные почерки. Чем хаотичнее исходник, тем сильнее работают правила нормализации.

Когда применять

Извлечение структурированных данных из документов — особенно когда поле имеет конечное число вариантов: тип, статус, категория, сегмент, стадия. Идеально для: транскриптов интервью, заполненных форм, медицинских записей, договоров, отчётов с повторяющейся структурой — везде где нужно собрать 20+ однотипных записей и сравнить их между собой. НЕ подходит для свободных описательных полей (комментарии, пояснения) — там природа ошибок другая и список допустимых значений не поможет. Также НЕ подходит для бюджетных и старых моделей — они часто возвращают список вариантов вместо того чтобы выбрать один из него.

Мини-рецепт

1. Составь список полей: что именно нужно извлечь из документа — перечисли все поля.
2. Реши по каждому полю: конечное число вариантов или свободный текст? Конечные — категория, статус, тип. Свободные — описание, комментарий.
3. Выпиши допустимые значения: для каждого конечного поля напиши все варианты через / прямо в шаблоне: "сегмент": "[B2B / B2C / не определён]".
4. Добавь "нет данных" явно: для каждого поля — иначе модель будет придумывать вместо того чтобы признавать неопределённость.
5. Напиши правила нормализации: начни с трёх-пяти правил по реальным ошибкам. Формат: "если X — пиши Y". Добавляй по одному при каждой новой ошибке.
6. Упакуй в один промпт: инструкция → правила нормализации → шаблон вывода в JSON → документ. Всё в одном запросе.

Примеры

[ПЛОХО] : Извлеки из транскрипта сегмент клиента, основную боль и готовность платить
[ХОРОШО] : ПРАВИЛА НОРМАЛИЗАЦИИ: - Готовность платить: только число в рублях или "не обсуждалась" - Если клиент использует общие слова без цифр — пиши "не обсуждалась" - Боль: одно предложение, максимум 15 слов - Если поле неясно — пиши "нет данных", не придумывай ШАБЛОН ВЫВОДА: { "сегмент": "[B2B / B2C / не определён]", "боль": "[одно предложение до 15 слов]", "готовность_платить": "[сумма в рублях / не обсуждалась]" } ТРАНСКРИПТ: {вставь текст} Результат: все записи в одном формате, сопоставимые между собой. Поля без данных получат "нет данных", а не выдуманный текст.
Источник: From Handwriting to Structured Data: Benchmarking AI Digitisation of Handwritten Forms
ArXiv ID: 2604.16504 | Сгенерировано: 2026-04-21 05:47

Проблемы LLM

ПроблемаСутьКак обойти
Открытое поле вывода даёт несопоставимые результатыПросишь модель извлечь одно и то же поле из разных документов. Допустимые значения не прописаны. Модель выдаёт "кесарево", "C/S", "К/С", "кесарево сечение" — всё семантически верно, но поля нельзя сравнить или свести в таблицу. Одна запись, один формат, другая — другой. Это тихая ошибка: модель не "ломается", просто итог бесполезенЗакрой список допустимых значений прямо в шаблоне вывода. "тип_родов": "[NVD / C/S / TOP / нет данных]". Добавь правило нормализации: "если поле неясно — пиши 'нет данных', не придумывай". Модель выберет из списка, а не сгенерирует произвольное

Методы

МетодСуть
Двухуровневое закрытие вывода — сопоставимые данные из любых документовУровень 1 — схема с допустимыми значениями. В шаблоне вывода для каждого поля пишешь список через слэш: "[B2B / B2C / не определён]". Модель видит список и выбирает из него. Уровень 2 — правила нормализации. Явно прописываешь как обрабатывать нестандартные случаи: "дата — только ДД/ММ/ГГГГ", "нет цифры — пиши 'не обсуждалась'", "'нет данных' если поле неясно". Оба уровня — в одном запросе. Когда применять: поля с конечным числом вариантов, нужна сводимость данных по множеству документов. Когда не работает: свободный текст без допустимых значений — метод не поможет
📖 Простыми словами

From Handwriting to Structured Data: BenchmarkingAIDigitisation of Handwritten Forms

arXiv: 2604.16504

Проблема оцифровки рукописных форм или кривых транскриптов упирается в то, что нейронки по своей природе — патологические болтуны. Когда ты просишь модель вытащить данные из текста, она ведет себя как творческая личность: один раз напишет «кесарево», другой — «C-section», а в третий вообще решит поумничать. Для базы данных это полный провал, потому что компьютер не понимает, что это одно и то же. Фундаментальная механика тут проста: LLM предсказывает наиболее вероятное следующее слово, и если ты не поставил ей жесткий забор, она будет гулять по всему словарю, плодя хаос вместо структуры.

Это как если бы ты попросил соседа сходить в магазин за «чем-нибудь к чаю». Один раз он принесет сушки, другой — торт, а в третий — воблу, потому что он так видит. Чтобы не остаться голодным, тебе нужно выдать ему строгий список и запретить покупать что-то, чего в нем нет. Исследование доказывает: если навязать модели жесткую схему вывода, где шаг вправо или влево невозможен, точность взлетает на 60% без смены самой модели. Ты просто заменяешь свободу творчества на тупую инструкцию, и магия начинает работать.

Вместо того чтобы надеяться на интеллект машины, нужно внедрять ограничение пространства вывода. Это работает через два рычага: жесткую схему (например, «статус заказа — только доставлен или в пути») и правила нормализации (дата — строго ДД/ММ/ГГГГ). Если в рукописной форме стоит закорючка, похожая на «норма», модель обязана превратить её в код NAD, а не расписывать мемуары. Конкретика вроде ? = неизвестно убивает галлюцинации на корню, потому что у модели больше нет нужды выдумывать ответ там, где она ничего не поняла.

Этот принцип — спасение для любого бизнеса, который тонет в неструктурированном контенте. Тестировали это на медицинских бланках, но схема универсальна: от расшифровок звонков в отдел продаж до анализа отзывов на маркетплейсах. Если ты фаундер и прогоняешь интервью с клиентами через AI, не проси его «сделать саммари». Требуй заполнить строгую таблицу с полями «боль», «сегмент» и «готовность платить». Без этого ты получишь тонну текста, который невозможно сравнить между собой, а с этим — готовый аналитический отчет.

Короче: хватит играть в «умный чат» и надейся на здравый смысл алгоритма — его там нет. Хочешь точности — зажимай модель в тиски структурированной схемы и четких правил нормализации. Прирост качества в 60% на ровном месте — это слишком жирный бонус, чтобы его игнорировать. Либо ты диктуешь правила игры, либо твои данные превращаются в бесполезную кашу, в которой невозможно найти концы.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с