TL;DR
Когда вы отдаёте агенту Word или PDF, конвертер (docling, «чистый текст» и подобные) сохраняет слова, но выбрасывает цвет текста и маркерное выделение. Для агента красное требование, жёлтое исключение и обычный абзац выглядят одинаково. Метод из статьи: собрать документ в текст так, чтобы цвет и выделение остались видны, например [COLOR:#FF0000] и [HIGHLIGHT:YELLOW]. Дальше нужно расшифровать агенту, что эти метки значат (критично, предупреждение, отменено).
Боль в том, что конвейер при этом не ломается. Текст на месте, ошибок нет, агент отвечает бойко. На задаче «перечисли требования, которые автор выделил» качество падает с 0,69 до 0,08–0,15. Агент не говорит «не вижу пометок», он угадывает. У docling доля ложных срабатываний на невыделенных требованиях примерно в четыре раза выше, чем у метода с метками. Другие модели, наоборот, замолкают почти полностью. Ни то ни другое не заметно без эталонных ответов.
Метод в три хода. Первый: сохранить цвет и маркер как метки в тексте. Второй: типизировать метки, то есть дать каждой роль (критично / предупреждение / устарело). Третий: не размечать то, что встречается везде (жирный, курсив, заголовки). Из всех видов оформления работают только цвет и маркер. Жирный, курсив, моноширинный шрифт и зачёркивание прироста не дали.
Схема метода
ШАГ 1: Прочитать .docx/PDF с сохранением оформления → блоки текста, где у каждого куска есть цвет/маркер/зачёркивание
(код, не LLM)
ШАГ 2: Превратить оформление в метки внутри текста → **жирный** в Markdown, [COLOR:#FF0000], [HIGHLIGHT:YELLOW]
ШАГ 3: Добавить роль к редким меткам → красный/красный маркер = CRITICAL_WARNING,
любой другой маркер = WARNING, зачёркнуто = DEPRECATED
ШАГ 4: Передать агенту размеченный текст + легенду, что значат роли → в одном промпте
ШАГ 5 (проверка): Тестовый документ с известными пометками → сверить, что агент их увидел
Шаги 1–2 делаются скриптом до агента. Шаги 3–5 пишутся словами в системном промпте.
Пример применения
Задача: Юрист в банке ведёт регламент по противодействию отмыванию доходов (в духе 115-ФЗ) в Word. В нём красным отмечены обязательные требования, жёлтым маркером — исключения, зачёркнуто — отменённые нормы. Агент в автоматизации без кода (n8n, Dify) должен отвечать операционистам: «Что обязательно проверить при переводе на 750 000 ₽?» Если регламент прогнать через обычный конвертер, цвета исчезнут, и агент не отличит обязательное от справочного.
Промпт (системная инструкция агенту):
Ты помощник операционистов банка. Отвечаешь только по регламенту ниже.
В тексте регламента сохранены пометки оформления автора:
- [COLOR:#FF0000]...[/COLOR] или красный маркер = CRITICAL_WARNING:
автор выделил обязательное требование. Приоритет выше обычного текста.
- [HIGHLIGHT:любой цвет]...[/HIGHLIGHT] = WARNING: исключение или особое условие,
на которое автор просит обратить внимание.
- ~~текст~~ = DEPRECATED: норма отменена, не применяй её и не называй действующей.
- **жирный** — это просто структура или термин. НЕ считай его признаком важности.
- Если пометок рядом с пунктом нет — это обычный пункт. Не называй его
выделенным автором, если не видишь метки.
1. Когда просят «что обязательно», сначала перечисли пункты с CRITICAL_WARNING.
2. К каждому пункту приведи дословную цитату из регламента.
3. Если в регламенте нет пометок вообще — скажи об этом прямо.
2.4. Операции свыше 600 000 ₽ [COLOR:#FF0000]подлежат обязательному контролю
с фиксацией основания в журнале[/COLOR].
2.5. Клиент вправе подтвердить источник средств выпиской. [HIGHLIGHT:YELLOW]Исключение:
переводы между счетами одного клиента внутри банка[/HIGHLIGHT].
2.6. ~~Допускается устное подтверждение источника средств.~~
2.7. Операционист ведёт **Журнал контроля** в электронном виде.
Вопрос: что обязательно сделать при переводе 750 000 ₽ клиенту, который принёс выписку?
Результат: Модель выделит в ответе пункт 2.4 как обязательный и приведёт цитату. Исключение 2.5 она назовёт отдельным условием. Устное подтверждение (2.6) она не предложит как действующий вариант. Пункт 2.7 про журнал она не вынесет в «обязательное» только потому, что слово выделено жирным. Если убрать метки и легенду, модель с большой вероятностью начнёт перечислять всё подряд или пропустит ключевое.
Почему это работает
Слабость. LLM читает токены, а не страницу. Всё, что автор закодировал оформлением (красный = «не нарушать», маркер = «смотри сюда»), исчезает, когда конвертер оставляет только слова. По словам задачу почти не решить: даже обученный на разметке классификатор по тексту даёт лишь немного лучше случайного результата (AUC 0,66). Модель без подсказок остаётся с догадкой.
Сильная сторона. Если сигнал виден в тексте, модель им пользуется. Метки [COLOR:…] и [HIGHLIGHT:…] она читает без обучения. Вторая сильная сторона: она хорошо следует расшифровке. Когда рядом написано «красный = обязательное», модель использует метку как признак приоритета. Типизация дала ещё +0,085 поверх голых меток.
Как метод соединяет одно с другим. Сначала сигнал возвращают в текст. Затем сужают его до редких, осмысленных признаков. Это и есть рычаг: - Что размечать. Цвет и маркер, потому что они редкие и намеренные. Жирным выделен каждый заголовок, поэтому он ничего не «выделяет». В ablation (убираем один вид оформления) жирный, курсив, моноширинный и зачёркивание дали ноль. - Сколько ролей давать. Короткий набор (критично / предупреждение / устарело). В полном наборе около 62% ролей описывали структуру (заголовок, акцент). Модель принимала любую роль за флажок и начинала всё подряд помечать как выделенное. - Что не размечать. Неоднозначное, например зелёный цвет. Авторы исключили такие правила: неверная подсказка вредит больше, чем её отсутствие. - Маркер по наличию, а не по оттенку. Правило «жёлтый = предупреждение» пропускало голубые и серые маркеры. Замена на «любой маркер, кроме белого» подняла долю охваченных абзацев с 79% до 98%.
Шаблон промпта
Ты ассистент, который отвечает строго по документу ниже.
В документе сохранены пометки оформления автора. Читай их как сигнал приоритета:
- {метка_критично} = CRITICAL_WARNING: {что это значит в моём документе}
- {метка_предупреждение} = WARNING: {что это значит в моём документе}
- {метка_устарело} = DEPRECATED: {что это значит, как с ним поступать}
- **жирный**, *курсив*, заголовки — только структура. Это НЕ признак важности.
- Если у пункта нет пометки — это обычный пункт. Не называй его выделенным автором.
1. На запросы «что важно / обязательно / критично» сначала перечисли пункты
с CRITICAL_WARNING, затем с WARNING.
2. К каждому пункту приведи дословную цитату из документа.
3. Не применяй пункты с DEPRECATED как действующие.
4. Если в документе нет ни одной пометки — скажи об этом, не угадывай.
{текст_документа_с_метками}
Вопрос: {вопрос}
Что подставлять:
- {метка_…}: ровно те метки, которые у вас стоят в тексте. Например [COLOR:#FF0000] или «красный маркер».
- {что это значит…}: значение из вашей практики. В статье подчёркивается, что одно и то же оформление в разных отделах значит разное. Не угадывайте, спросите автора документа.
- {текст_документа_с_метками}: документ после конвертации с метками. Как их получить, показано в «Быстром старте» ниже.
🚀 Быстрый старт — вставь в чат:
Вот шаблон промпта для чтения документов с пометками оформления. Адаптируй под мою задачу: [какие у меня документы и что в них выделено цветом, маркером, зачёркиванием].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
Дополнительно напиши короткий скрипт на Python (python-docx), который читает мой .docx и выводит текст с метками [COLOR:#RRGGBB], [HIGHLIGHT:ЦВЕТ] и ~~зачёркнуто~~ вокруг соответствующих кусков.
LLM спросит, что значит каждый цвет и каждый маркер в ваших документах, кто и как их ставит, и какие вопросы будут задавать агенту. Это нужно потому, что метод держится на расшифровке: без неё метки остаются голым сигналом, а типизация давала дополнительный прирост. Она возьмёт паттерн из шаблона и подставит ваши значения.
Ограничения
⚠️ Только цвет и маркер: Жирный, курсив, моноширинный шрифт и зачёркивание в тесте прироста не дали. Размечать их «на всякий случай» нечего. Хуже того, лишние метки засоряют текст.
⚠️ Типизация даёт скромный прирост: Сохранение меток даёт основную часть эффекта. Расшифровка добавляет +0,085, и значимость там на границе (p = 0,049), оценка с широким интервалом. На двух моделях из шести расшифровка пользы не принесла.
⚠️ Модели ошибаются по-разному: Без метки одни модели перечисляют лишнее, другие почти отказываются отвечать (одна давала очень точные, но редкие ответы, полнота около 0,09). Оба сбоя не видны без эталонных ответов.
⚠️ Нужен код или скрипт: Метки не появятся сами. Обычные конвертеры (docling, plain text, часть загрузчиков в чат-интерфейсах) цвет теряют. Нужно собрать небольшой разбор .docx, это под силу LLM, но без этого шага метод не работает.
⚠️ Проверена одна задача: Находить требования, которые автор выделил. Другие вопросы к документам, например точное цитирование или сравнение, не проверялись.
⚠️ Значение цвета не универсально: Одно и то же оформление в разных отделах значит разное. Нельзя заранее вписать «красный = опасно»: значение нужно узнать у автора. Авторы сознательно исключили неоднозначные правила, например зелёный цвет.
⚠️ PDF и сканы сложнее: В PDF нет «свойств текста», цвет и маркер восстанавливаются по геометрии символов. Результат на PDF примерно равен лучшему из существующих конвертеров, а для сканов нужен распознаватель текста со своими ошибками.
⚠️ Теряется не только оформление: Колонтитулы, сноски, свойства документа и принятые правки (текст, который реально действует) обычный обход тела документа не достаёт. Авторы сами обнаружили это во время работы, их первая версия тоже это пропускала.
Как исследовали
Исследователи просканировали 6462 реальных .docx-документа с публичных политик. У 32,8% есть намеренный красный цвет или маркер, у 10,3% он стоит на предложении с обязательством. Это не экзотика, а обычное состояние корпоративных документов. Из них собрали задачу на 84 документа (332 выделенных требования и 4192 невыделенных). Модели нужно было назвать требования, которые автор «отметил особым вниманием». Эталон взят из свойств самого файла, а не из чьего-то мнения. Оценка без LLM-судьи: требование считается найденным, если в ответе есть четыре подряд идущих значимых слова из его начала.
Сравнивали шесть способов подготовки текста при одинаковом вопросе. Простой текст дал 0,075, docling 0,150, docx2python (он сохраняет оформление как HTML) 0,586, метод авторов 0,690. Самый чистый вывод пришёл из послойного эксперимента: из текста убирали по одному виду оформления, и весь эффект ушёл на маркер (+0,302) и цвет (+0,262). Жирный, курсив, моноширинный и зачёркивание остались в пределах ±0,003 от нуля. Удивительно, что в одном документе бывает больше тысячи жирных меток. Они не информативны именно потому, что слишком обычны: автор, выделивший жирным все заголовки, этим ничего не выделил.
Вопрос «нужна ли расшифровка помимо сохранения» проверяли в заранее зарегистрированном тесте: гипотезы и метод анализа зафиксированы до запуска. Он подтвердился, но с p = 0,049, на границе. Авторы честно показали, что после исправления собственной ошибки в парсере (он вставлял лишние чёрные метки) значимость стала хуже, а эффект остался тем же. Также проверяли на внешнем тесте Microsoft (326 вопросов, 59 документов) и на шести моделях двух разработчиков. Простой текст провалился на всех (0,007–0,075), то есть дело в способе подачи документа, а не в модели. Полный конвейер с извлечением и сборкой пакета подтвердил разрыв: 0,503 против 0,258 (docx2python) и 0,084 (docling).
Адаптации и экстраполяции
🔧 Техника: добавить в легенду «чего не считать сигналом» → меньше ложных срабатываний
В статье типизировали только редкие признаки. Правило «жирный — это структура» удобно вписать в промпт прямо:
- **жирный**, заголовки, курсив — просто структура. Не причина считать пункт важным.
- Если метки рядом нет, пиши «автор не выделял», а не «похоже, важно».
Это та же идея, что в оригинале (узкий набор ролей), но выраженная как явный запрет для моделей, которые склонны принимать любую пометку за флажок.
Экстраполяция: аудит конвейера перед запуском агента. В статье это не описано, это мой перенос принципа «проверяй по эталону из самого файла».
Возьмите один документ, где вы сами знаете, что выделено, и спросите агента:
В этом документе автор выделил часть пунктов цветом или маркером.
Перечисли ровно те пункты, которые выделены, и для каждого укажи,
по какой пометке ты это понял. Если пометок в тексте не видно — напиши «пометок не вижу».
Если модель отвечает уверенным списком, а пометок в её входе нет, значит, она угадывает. Если честно пишет «не вижу», конвейер теряет сигнал, и пора чинить конвертацию. Это дешёвая проверка на «тихую потерю». Так вы поймаете то, чего не поймает ни один монитор.
Ресурсы
- Статья: What the Author Wrote, What the Agent Reads: Silent Cue Loss in Enterprise Document Ingestion. Yikai Zhao, Saurabh Pandey, Pradeep Kumar Misra, Amazon.
- Упомянуты в работе: Microsoft Office Comprehension Benchmark (File-Fidelity, Word), ParseBench, OmniDocBench; конвертеры docling, docx2python, python-docx, Unstructured, pymupdf4llm, mammoth.
- Смежное: PASTA (управление вниманием по стилю текста), Dillitzer et al. (внимание ≠ точность), TexTAR (распознавание жирного, курсива, подчёркивания и зачёркивания на изображениях), Yang et al. (USENIX Security, визуальные приёмы обхода модерации).
