Промпт-инжиниринг для анализа документов
Промпт для анализа документа — не разовая формулировка, а спецификация процедуры: роль, контекст, критерии, ограничения и формат результата. Разбираю, как строить такие промпты для извлечения данных, сравнения источников, поиска противоречий и многошагового анализа, и как их тестировать на разных документах, а не на одном удобном.
Введение: почему качество анализа зависит не только от модели
Одна и та же модель на одном и том же документе способна дать два принципиально разных результата в зависимости от того, как сформулирована задача. Дело не в случайности генерации. Свободная формулировка вроде "проанализируй этот документ" не задаёт ни цель анализа, ни критерии, ни формат, ни то, что делать с неоднозначными местами, и заполнять эти пробелы приходится уже самой модели.
Формальные замеры это подтверждают. Исследования устойчивости моделей к формулировке промпта показывают, что смена формата инструкции при абсолютно тех же весах модели способна менять точность ответа на десятки процентных пунктов, а у отдельных моделей разброс между семантически эквивалентными формулировками одной и той же задачи доходит до нескольких десятков пунктов точности. Для анализа документов это не абстрактная теория: контекст, цель анализа, ограничения и формат результата решают не меньше, чем сама модель.
В общем разборе работы с источниками уже показаны три рабочих промпта как пример. Дальше разбираю саму механику за хорошей формулировкой: хороший промпт превращает свободный запрос в формализованную процедуру анализа вместо удачно подобранной фразы, которая один раз случайно сработала.
Какие задачи можно решать с помощью промптов
Диапазон задач, которые решает промпт для анализа документа, шире, чем "перескажи текст": извлечение фактов и конкретных сведений, структурирование неструктурированного текста, сжатие в краткое изложение, классификация документов и фрагментов, поиск противоречий, сравнение нескольких документов, выявление рисков и проблем, анализ аргументации, выделение ключевых положений, преобразование содержания в структурированные данные.
Каждый класс задач требует своей постановки запроса, и это не формальность. Задача извлечения фактов ("найди в тексте все даты и суммы") задаёт узкий, дословный режим работы: цитировать, не интерпретировать. Задача анализа аргументации ("оцени, насколько вывод автора подкреплён приведёнными данными") требует обратного: модель должна рассуждать, не просто искать совпадения. Промпт, написанный под один класс задач, обычно плохо работает для другого, даже если оба формально называются "анализом документа".
Из чего состоит хороший промпт для анализа документа
Рабочий промпт обычно собирается из восьми компонентов: роль модели, задача, контекст, критерии анализа, ограничения, требования к достоверности, формат результата и правила работы с отсутствующей информацией. Пропуск любого из них не всегда ломает результат сразу, но каждый раз оставляет решение за моделью там, где решение должен принимать ты.
Здесь легко упустить одну разницу: промпт должен описывать не только то, что нужно найти, но и то, как интерпретировать найденное. "Найди в договоре пункты об ответственности сторон" — задача извлечения. "Найди в договоре пункты об ответственности сторон и оцени, есть ли дисбаланс в пользу одной из сторон" добавляет к извлечению ещё и интерпретацию. Без второй явной инструкции модель либо молча добавит интерпретацию от себя, либо остановится на голом списке, и оба варианта могут оказаться не тем, что реально было нужно.
Формулировка цели анализа
Самая частая проблема на этом шаге — слишком общий запрос вроде "проанализируй документ". Абстрактный глагол вроде "проанализируй" или "разбери" не задаёт конкретную операцию, и модель сама выбирает, с чего начать и чем закончить, обычно выбирая нейтральный пересказ вместо того результата, который реально требовался.
Рабочая формулировка превращает абстрактную задачу в конкретную аналитическую операцию с понятным результатом: не "проанализируй риски", а "выдели все пункты договора, создающие финансовый риск для нашей стороны, и оцени каждый по шкале от 1 до 5". Стоит различать пять разных типов запроса, которые легко смешать в одной формулировке: пересказ, анализ, оценка, классификация и извлечение информации. Каждый предполагает свою степень вмешательства модели в исходный текст, от нулевой при извлечении дословных фрагментов до высокой при оценке с собственным суждением. Путаница между ними в одном промпте обычно даёт результат, отвечающий сразу на два вопроса, ни на один как следует.
Управление контекстом
Просто передать модели документ и попросить его проанализировать недостаточно. Без явных инструкций непонятно, какую часть документа учитывать в первую очередь, какие сведения приоритетны, какие внешние знания допустимо привлекать, что делать с неоднозначными фрагментами и где вообще проходит граница интерпретации.
Один из самых практически значимых эффектов здесь: модели заметно хуже удерживают и анализируют информацию, расположенную в середине длинного контекста, чем в начале или в конце. Это показало исследование Лю и коллег 2023 года ("Lost in the Middle"): точность извлечения факта резко падает, если он находится где-то посередине длинного документа, даже когда модель формально способна обработать весь текст целиком за один проход. Практический вывод: важные инструкции и критерии стоит размещать в начале или в конце промпта, не полагаясь на то, что модель одинаково внимательно прочитает всё.
Отдельно важно явно разделять содержание документа и инструкции для модели, не смешивая их в одном сплошном тексте. Чёткие разделители, например XML-теги вроде <document> и <instructions>, снижают риск того, что модель спутает часть текста документа с частью инструкции, особенно если сам документ содержит фразы, похожие на команды.
Работа с длинными документами
Контекстное окно модели физически ограничено, и даже там, где формально влезает весь документ, обработка одним запросом не всегда лучшая стратегия. Чем длиннее документ, тем менее равномерно модель распределяет внимание по нему, и эффект потерянной середины из предыдущего раздела только усиливается с ростом объёма.
Рабочие подходы: предварительное разбиение на фрагменты, анализ каждого фрагмента отдельно, сохранение промежуточных результатов, последующая агрегация этих результатов в единый вывод, иерархический анализ там, где сам документ имеет вложенную структуру, повторная проверка самых важных выводов отдельным дополнительным запросом. На практике это обычно сводится к одной из двух схем: Map-Reduce, когда фрагменты анализируются параллельно и независимо, а результаты сводятся на отдельном шаге, либо иерархическая свёртка, когда сначала конспектируются мелкие части, потом конспекты этих конспектов, и так до одного финального результата.
Промпты для извлечения структурированной информации
Переход от свободного текста к заранее заданной структуре результата — один из самых практически ценных приёмов: структурированный вывод можно сразу подать дальше по пайплайну, без ручного разбора.
Рабочий промпт задаёт фиксированный набор полей, тип данных для каждого поля, явно помечает обязательные и необязательные значения и отдельно описывает, что делать при отсутствии данных: выводить явный маркер вроде "null" или "не указано", не пытаться додумать значение самому. Современные модели поддерживают это на уровне механизма, не только текстовой инструкции. Жёсткие схемы вывода, JSON-режим, function calling, структурированное декодирование по заданной схеме снижают долю синтаксически некорректных ответов почти до нуля по сравнению со свободным текстом, где модель время от времени путает формат, пропускает поле или добавляет лишний комментарий перед данными.
Как уменьшить количество галлюцинаций
Недостоверные выводы при анализе документа обычно возникают не потому, что модель "врёт", а потому, что промпт не запрещает ей достраивать отсутствующие сведения по общим знаниям вместо содержания документа.
Рабочие приёмы: явное требование опираться только на содержание документа, прямой запрет додумывать отсутствующие сведения, обязательное обозначение неопределённости там, где ответа в тексте нет, разделение фактов и интерпретаций как двух разных категорий вывода, привязка каждого вывода к конкретному фрагменту документа, дополнительная проверка критически важных утверждений отдельным шагом. Метод Chain-of-Verification, где модель сначала формулирует черновой ответ, затем сама составляет проверочные вопросы к собственным утверждениям и отвечает на них независимо, по опубликованным результатам снижает число галлюцинированных фактов на 50-70% по сравнению с обычным прямым ответом на тех же задачах.
Инструкция нулевой толерантности к домыслам работает надёжнее расплывчатой просьбы "будь точным". "Если в тексте нет прямого ответа на вопрос, выведи статус 'данные отсутствуют', использовать знания за пределами документа запрещено" — конкретное правило вместо общего пожелания.
Цитирование и доказательность выводов
Отдельная задача: заставить модель показывать основание для каждого своего вывода, не просто выдавать убедительно звучащий ответ. Рабочий приём — требовать точную цитату, номер страницы или раздела, идентификатор части документа рядом с каждым существенным утверждением.
Разница на практике заметная. Промпт "перечисли риски в договоре" и промпт "перечисли риски в договоре, для каждого укажи точную цитату из текста и номер пункта" дают формально похожие списки. Только второй можно быстро проверить, не перечитывая весь документ заново. Это особенно ценно для автоматизации: если модель обязана возвращать пары "утверждение плюс точная цитата", отдельный скрипт способен проверить, действительно ли эта цитата есть в исходном документе, и отфильтровать выводы, которые этой проверки не проходят, ещё до того, как результат увидит человек.
Анализ документа в несколько этапов
Последовательный пайплайн из нескольких промптов обычно даёт более надёжный результат, чем один универсальный запрос "разбери документ полностью". Логика может выглядеть так: определить структуру документа, извлечь релевантную информацию, классифицировать найденные данные, провести основной анализ, проверить противоречия и пропуски, сформировать итоговый результат.
Смысл разделения простой: каждый отдельный шаг предъявляет к модели куда более узкое требование, чем "сделай всё сразу". Промпт, который одновременно просит извлечь факты, классифицировать их, оценить риски и сформулировать рекомендации, конкурирует сам с собой за внимание модели. Обычно одна из этих подзадач страдает в пользу остальных, часто незаметно для того, кто читает готовый результат.
Сравнение нескольких документов
Промпты для сравнения нескольких источников сталкиваются с проблемами, которых нет при анализе одного документа: разные структуры документов, разная терминология для одних и тех же понятий, прямые противоречия между источниками, отсутствие части информации в одном из них, необходимость сопоставлять одинаковые сущности под разными именами.
Рабочий приём для последней проблемы: первым шагом сравнительного промпта всегда идёт унификация словаря, до самого сравнения. Модель сначала строит единый список терминов и их соответствий по всем сравниваемым документам, и только после этого переходит к содержательному сопоставлению. Пропуск этого шага почти гарантированно даёт ложные "противоречия", которые на самом деле просто разная терминология одного и того же понятия. Критерии сравнения тоже стоит задавать заранее и явно, не оставляя модели решать самой, что именно сравнивать.
Анализ противоречий и несоответствий
Это отдельный класс задач: модель здесь сопоставляет разные утверждения между собой, а не просто извлекает их из текста по отдельности: внутренние противоречия в одном документе, противоречия между несколькими документами, несогласованные значения одного и того же показателя, логические несоответствия в рассуждении автора, потенциальные ошибки в исходных данных.
Задача обнаружения скрытых противоречий работает надёжнее, если промпт явно разбивает рассуждение на шаги вместо одного запроса "найти противоречия": сначала перечислить все утверждения по конкретному вопросу, затем попарно сверить их на совместимость, и только на третьем шаге сформулировать вывод. Модели, которых просто попросили найти нестыковки, регулярно пропускают неявные логические коллизии, не выраженные буквально противоречащими друг другу фразами. Отдельно важно разделять само обнаруженное противоречие и интерпретацию его причины: то, что два места в договоре указывают разные сроки, это факт; является ли это опечаткой или намеренным условием, уже интерпретация, и путать эти два уровня в одном выводе не стоит.
Как задавать формат результата
Формат ответа должен быть частью промпта, не решаться моделью по умолчанию. Уровни структурирования разные: краткое резюме, тематические блоки, таблица, список отдельных утверждений, набор структурированных полей, машинно-обрабатываемый формат вроде JSON.
Выбор формата стоит делать исходя из того, что произойдёт с результатом дальше. Результат, который человек будет бегло сканировать глазами в поисках конкретных цифр, обычно удобнее в виде таблицы или списка: искать конкретное значение среди строк и колонок быстрее, чем в абзаце, где та же цифра спрятана посреди предложения. Результат, который пойдёт дальше в автоматическую обработку, обязан быть в машинно-читаемом формате независимо от того, насколько текстовый пересказ выглядел бы понятнее человеку.
Плохие и хорошие промпты: критерии качества
Вместо конкретных примеров полезнее держать в голове критерии. Хороший промпт однозначно определяет задачу, задаёт релевантный контекст, ограничивает область анализа, определяет критерии оценки, контролирует недостоверные выводы, задаёт ожидаемый формат и позволяет проверить результат независимо от того, кто его читает.
Плохой промпт узнаётся по симптомам, не по конкретной формулировке: размытая цель, отсутствие критериев, чрезмерная зависимость финального результата от того, как конкретно модель решит интерпретировать неоднозначный запрос. Проверка простая: если два разных прогона одного и того же промпта на одном документе дают структурно разные ответы, не просто разные слова при одинаковой сути, промпт, скорее всего, недостаточно ограничивает задачу.
Как тестировать промпты
Промпт стоит воспринимать как объект итеративной оптимизации, не как формулировку, придуманную один раз и больше не тронутую. Рабочий процесс: собрать набор тестовых документов, заранее определить, что должно быть в правильном результате, проверить промпт на разных типах документов, зафиксировать типичные ошибки, менять за раз одну группу инструкций, сравнивать результаты разных версий промпта друг с другом.
Отдельно стоит проверять промпт на неудобных документах, не только на репрезентативных: на сканах с плохим распознаванием текста, на документах с нестандартной структурой, на пограничных случаях, где правильный ответ — "информация отсутствует". Один из рабочих методов автоматизации этого шага — LLM-as-a-Judge: отдельная модель оценивает качество ответа по заранее заданному рубрикатору, что позволяет прогонять десятки версий промпта на десятках документов без ручной проверки каждого результата.
Личный пример: довольно долго я тестировал промпты для анализа документов на двух-трёх примерах, которые сам же и выбрал именно потому, что они хорошо обрабатывались. Промпт, отлично справлявшийся с этой узкой выборкой, регулярно ломался на реальных пользовательских документах с другой структурой. Тестовый набор, подобранный под уже работающий промпт, ничего не говорит о том, как он поведёт себя за пределами этого набора.
Типичные ошибки при создании промптов
Самые частые проблемы повторяются от промпта к промпту: слишком общая постановка задачи, чрезмерно длинные инструкции, которые сами начинают противоречить друг другу, смешивание нескольких независимых задач в одном запросе, отсутствие критериев качества, отсутствие явных правил для неопределённых данных, отсутствие требований к источникам выводов, попытка решить сложную задачу одним запросом вместо пайплайна, отсутствие проверки результата после получения ответа.
Из этого списка одна ошибка ломает промпт особенно надёжно: избыточное количество правил и ограничений, часть которых начинает противоречить друг другу. Модель в такой ситуации следует какому-то из этих правил по своей внутренней логике, не по твоей, и результат становится непредсказуемым именно там, где промпт пытался всё предусмотреть заранее.
Промпты как часть автоматизированного анализа документов
В программном пайплайне промпт перестаёт быть разовым пользовательским запросом и становится частью архитектуры: загрузка документа, извлечение текста, сегментация, определение релевантных частей, LLM-анализ, структурирование результатов, сохранение, последующий поиск и использование данных.
На этом уровне промпт правильнее воспринимать как конфигурируемый код. Он версионируется, тестируется на регрессию при обновлении модели и меняется по тем же правилам, что и остальной код системы, не на глаз, когда что-то пошло не так.
Как выбирать стратегию анализа
Универсального промпта на все случаи не существует. Практическая система выбора подхода опирается на параметры конкретной задачи: небольшой документ с простой задачей обычно закрывается одним прямым промптом, большой документ требует разбиения и агрегации, несколько документов требуют унификации терминов перед сравнением, задача извлечения структурированных данных требует жёсткой схемы вывода, аналитическая задача с оценочными суждениями требует явных критериев оценки, задача с высокими требованиями к доказательности требует обязательного цитирования и проверки, повторяющийся автоматизированный анализ требует версионируемого промпта внутри пайплайна.
Заключение
Несколько принципов, к которым сводится всё сказанное выше: сначала определить аналитическую задачу, затем контекст, который для неё нужен, явно задать критерии и ограничения, отделять извлечение информации от интерпретации, требовать доказательность выводов, использовать многошаговый анализ для сложных документов, тестировать промпты на реальных данных, а не на удобных, и относиться к промпту как к части аналитического процесса, не как к случайно найденной формулировке, которая один раз сработала.
Комментарии
Комментариев пока нет. Будь первым.