Документы у заказчиков приходят не в том виде, в каком их любят языковые модели. Половина архива — сканы, снятые многофункциональным устройством десять лет назад. Четверть — PDF, экспортированный из Word, где текстовый слой есть, но заголовки размечены пробелами. Остальное — фотографии страниц, сделанные с телефона под углом, с тенью от руки.
Извлечением занимается Docling, поверх него работает наш слой — okb docling-shim. Он отвечает за две вещи: когда включать распознавание и как резать документ на фрагменты.
Когда включать OCR, а когда это вредно
Соблазнительное решение — пропускать через распознавание всё подряд. Так делать не стоит по двум причинам.
Первая: OCR — самая дорогая операция во всём конвейере. Прогонять через неё документ, где текстовый слой уже есть и он корректен, — значит тратить минуты вычислений там, где хватило бы миллисекунд.
Вторая, более неприятная: распознавание ухудшает хороший текст. Там, где в PDF лежит точная строка, OCR может выдать «1» вместо «l», разорвать таблицу или потерять надстрочный знак. Вы меняете идеальные данные на приблизительные и даже не узнаете об этом.
Поэтому политика распознавания включается точечно. Shim смотрит на страницу и решает: есть ли пригодный текстовый слой, покрывает ли он реальное содержимое страницы, не выглядит ли он мусором из битой кодировки. Скан и фотография уходят в распознавание, нормальный экспорт из офисного пакета — нет. Смешанный документ обрабатывается постранично: у одного файла часть страниц может пойти по одному пути, часть по другому.
Загрузка архива перестаёт быть операцией «на выходные». Кроме того, у одинаковых документов получается одинаковое качество текста — а значит, поиск по ним ведёт себя предсказуемо.
Структурная нарезка вместо нарезки по длине
Дальше документ надо разложить на фрагменты, по которым будет идти поиск. Простой способ — резать по числу символов с перекрытием. Он работает и повсеместно используется, но у него есть встроенный дефект: границы фрагментов проходят где попало.
Мы режем по структуре: заголовок раздела, подраздел, пункт. Каждый фрагмент получает в тело свой заголовочный путь — то есть фрагмент из середины регламента «знает», что он относится к разделу «4.2. Порядок согласования». Из этого следуют три вещи:
- Ответ ссылается на раздел, а не на файл целиком. Проверить утверждение можно за пятнадцать секунд, а не листая семьдесят страниц.
- Поиск точнее. Заголовок в теле фрагмента — сильный сигнал и для векторной модели, и для BM25.
- Фрагменты не рвут мысль пополам. Модель получает законченный кусок, а не хвост одного пункта и начало другого.
Как разбираются структуры конкретных документов и что происходит дальше с этими фрагментами — в разборе про гибридный поиск.
Таблицы — отдельная боль
Таблица в скане — это картинка, где смысл держится на взаимном расположении ячеек. Распознавание возвращает текст, но структура строк и столбцов восстанавливается не всегда. Простые таблицы с одной шапкой обрабатываются нормально. Сводные, с объединёнными ячейками и многоуровневой шапкой, разбираются хуже, и это не лечится настройками — это ограничение метода.
Мы говорим об этом до внедрения, а не после. Если ключевые данные заказчика живут в сложных сводных таблицах, честный ответ — что в этой части система будет помощником, но не источником истины, и проверять придётся глазами.
Что делать с плохими сканами
Кривой скан на выходе даёт кривой текст, и никакая модель этого не исправит: угадывать пропущенные буквы она будет правдоподобно, что хуже, чем не угадывать вовсе. Работающие меры простые и скучные:
- Пересканировать критичные документы — обычно это десятки файлов, а не тысячи.
- Не грузить в базу знаний фотографии страниц, если есть исходник в электронном виде.
- Проверить выборочно, что получилось после загрузки. Пятнадцать документов из архива дают понимание качества по всему массиву.
Docling-shim занимается текстом и структурой. Он не извлекает поля в структурированном виде — автоматической выгрузки реквизитов в 1С у нас нет, это в бэклоге. Рукописный текст не распознаётся: это отдельный класс задач, и обещать его сейчас мы не готовы.
Коротко
Слой между хранилищем и моделью решает больше, чем выбор самой модели. Умное включение OCR экономит часы на загрузке архива и не портит хороший текст. Структурная нарезка даёт ссылки на разделы и делает поиск предсказуемым. Всё это происходит на вашем железе — файлы не уезжают на распознавание ни в какое облако, что для сканов договоров обычно и является решающим аргументом.