Документ «не распозналось» — и сообщение об ошибке ничего не объяснило. Эта статья — про то, что стоит за словом «распознавание» на самом деле, из чего оно состоит и почему в одних случаях работает мгновенно, а в других отказывает вовсе.
Сразу проясним, о чём речь не пойдёт: если вы ищете распознавание первичных бухгалтерских документов для 1С — счетов-фактур, УПД, накладных, — это не та страница. Здесь разбирается распознавание документов в составе тендерного пакета — того самого пакета, чья полная анатомия разобрана в материале «Тендерная документация: из чего собирается пакет и где он разваливается» — и в целом принцип, по которому такие системы устроены.
Коротко. «Распознавание документов» — не одна технология, а каскад. Сначала система пытается прочитать текстовый слой файла напрямую — это быстро и почти безошибочно. Если слоя нет (скан, фотография), подключается OCR: у нас это Yandex Vision для страниц, таблиц и рукописного текста, с Tesseract как резервным вариантом. Каждый уровень отдаёт оценку уверенности; при низкой система помечает результат «проверьте распознавание», а если текст не извлечён вовсе — сообщает об отказе, а не возвращает пустоту. Качество распознавания определяется не моделью, а тем, в каком виде документ попал на вход.
Распознавание — это каскад, а не кнопка
Ответ короткий: за словом «распознавание» в производственной системе стоит не один шаг, а последовательность из трёх уровней, где каждый следующий дороже и менее уверен в результате, чем предыдущий. Систему выгодно устроить так, чтобы дешёвый и точный способ пробовался первым, а дорогой и менее надёжный подключался только тогда, когда первый объективно не сработал.
Порядок здесь не случаен: прямое чтение текстового слоя — это доли секунды и предсказуемый результат, поэтому его можно применять ко всему входящему потоку документов без раздумий. Распознавание изображений — на порядок затратнее по вычислениям и по своей природе даёт менее уверенный результат: буквы на фотографии или скане система не читает напрямую, а восстанавливает, а восстановление — это уже вероятностная задача, а не механическое извлечение. Поэтому OCR включается только там, где текстового слоя объективно нет.
Разница между тремя уровнями — не в том, «умнее» ли один способ другого, а в том, какую задачу он на самом деле решает. Уровень 1 читает то, что уже закодировано в файле как текст, — здесь нет распознавания в строгом смысле, только извлечение. Уровень 2 восстанавливает текст по изображению — задача принципиально другая, и она никогда не будет такой же надёжной, как чтение готового текста, сколько бы ни улучшалась модель. Уровень 3 — не альтернативный способ распознавания, а страховка на случай, когда основной механизм уровня 2 не справился. Смешивать эти три уровня в один разговор «работает или не работает OCR» — значит терять именно ту информацию, которая нужна, чтобы понять, почему конкретный документ не прочитался.
Каждая ступень уже предыдущей и ниже по уверенности — система спускается на неё только при неудаче ступени выше. Подробный разбор структуры всего тендерного пакета — в материале о структуре тендерного пакета.
Уровень 1: текстовый слой, который уже есть
Ответ короткий: если документ изначально создан в цифровом виде — PDF с текстовым слоем, DOCX, XLSX, — текст извлекается напрямую, на практике через PyMuPDF, за доли секунды и с высокой уверенностью. Это должно работать всегда, без исключений: на этом уровне отказ недопустим, потому что текст физически уже есть в файле, его не нужно распознавать — только прочитать.
Разница между «PDF с текстом» и «PDF-картинкой» на глаз не всегда очевидна, но проверяется буквально за пять секунд: откройте файл и попробуйте выделить текст мышью или найти слово через Ctrl+F. Если текст выделяется и находится — перед вами цифровой документ, и распознавание в смысле OCR ему не требуется, только извлечение уже существующего текстового слоя. Если файл выглядит как страница, но ни выделить, ни найти в нём ничего нельзя, — значит, это изображение, вставленное в PDF-контейнер, то есть отсканированная или сфотографированная страница, и вступает следующий уровень.
Эта проверка не техническая деталь для инженеров — это первое, что стоит сделать самому, прежде чем считать, что «система не распознаёт документ». Часто выясняется, что документ и не должен был распознаваться в смысле OCR: он уже текстовый, просто отдельная его часть — например, вставленная как изображение печать или таблица со сканированной подписью — действительно требует другого уровня обработки.
Стоит отдельно сказать, почему этот уровень вообще выделен как самостоятельный шаг, а не просто «всегда пробуем прочитать текст». Значительная часть документов тендерного пакета — техническое предложение, смета, сопроводительные письма — создаётся сразу в цифровом виде: их готовит сам участник в Word или Excel и экспортирует в PDF перед подачей. Для этой части пакета уровень 1 — не запасной вариант, а основной и единственный нужный путь: прогонять цифровой документ через OCR было бы не просто лишней тратой вычислений, а источником случайных ошибок распознавания там, где текст можно прочитать безошибочно. Именно поэтому каскад начинается с попытки извлечь текстовый слой напрямую, а не с распознавания изображений по умолчанию. Что происходит с распознанной сметой дальше — как её колонки сводятся к ролям и сверяются с каталогом — отдельный разбор.
Уровень 2: OCR — Yandex Vision и когда его недостаточно
Ответ короткий: OCR вступает в дело ровно тогда, когда текстового слоя в документе нет, — и дальше это тоже не один шаг, а три разных режима с разной надёжностью: распознавание страницы, отдельный режим для таблиц и отдельный для рукописного текста. У нас это Yandex Vision.
Таблицы — не частный случай обычного текста, а отдельная задача. Строка текста на сканированной странице — это последовательность символов вдоль одной линии; распознать её — значит правильно прочитать буквы. Таблица — это ещё и структура: где заканчивается одна ячейка и начинается следующая, какая строка соответствует какой графе. Модель, которая хорошо читает сплошной текст, не обязана одинаково хорошо восстанавливать эту структуру — поэтому таблицы обрабатываются отдельным режимом, а не как побочный эффект распознавания текста. То же с рукописным текстом: почерк варьируется от человека к человеку сильнее, чем печатный шрифт, поэтому уверенность распознавания рукописных пометок в среднем ниже, чем печатной страницы, — и это честно, а не недоработка конкретной модели.
Каждый уровень каскада возвращает собственную оценку уверенности результата. При низкой уверенности система не блокирует загрузку документа и не скрывает проблему за красиво отформатированным, но ошибочным текстом — она помечает результат значком «проверьте распознавание». Это осознанно неблокирующее решение: система не берёт на себя роль последней инстанции там, где сама не уверена, а отдаёт решение человеку, который может открыть исходный файл и свериться глазами за несколько секунд — что дешевле, чем разбираться с последствиями неверно распознанного документа на этапе рассмотрения заявки.
Если распознавание через Yandex Vision не дало уверенного результата ни в одном из режимов, последней попыткой перед отказом становится Tesseract на CPU — более простой резервный движок, который иногда справляется там, где основной OCR-сервис не смог, но не наоборот: он не первый выбор, а именно страховка на случай, когда основной путь исчерпан.
Практически это значит, что один и тот же скан может пройти через два независимых механизма распознавания, прежде чем система признает документ нечитаемым. Такая последовательность стоит вычислительного времени только потому, что альтернатива — либо остановиться на первой неудаче и заведомо потерять часть документов, которые второй механизм всё же прочитал бы, либо экономить на проверке и получить менее надёжный результат там, где можно было получить более надёжный. Для тендерного пакета, где каждый непрочитанный документ — это потенциально незамеченное требование заказчика, эта разница не абстрактная: именно поэтому каскад из двух независимых OCR-механизмов, а не одного, оправдан даже с учётом дополнительной стоимости.
Честный отказ лучше пустого результата
Ответ короткий: если ни один из трёх уровней не извлёк из документа ни одного символа текста, система сообщает об этом открыто — явной ошибкой распознавания, а не пустым результатом, который выглядит как успешно обработанный документ без содержания.
Разница между этими двумя исходами больше, чем кажется на первый взгляд. Пустой результат неотличим по форме от документа, в котором действительно ничего не было, — например, от титульного листа без текста. Дальше по цепочке обработки, там, где документ сопоставляется с пунктами чек-листа заявки, пустота читается ровно так же, как «в этом документе релевантных требований не найдено». Специалист, который полагается на систему, не увидит разницы между «здесь нечего искать» и «система не смогла прочитать документ» — и именно вторая ситуация опаснее, потому что маскируется под первую.
Открытый отказ решает эту проблему тем, что не оставляет места для такой путаницы: он явно говорит «этот документ не удалось распознать», и специалист понимает, что должен вмешаться — открыть файл вручную, пересканировать страницу в лучшем качестве или ввести данные напрямую, — вместо того чтобы по умолчанию доверять пустой строке.
Это решение выглядит очевидным, когда его формулируешь вслух, но на практике многие пайплайны идут по более простому пути: возвращают то, что удалось получить, каким бы скудным оно ни было, потому что явная ошибка требует отдельной ветки обработки, а пустой результат этой ветки не требует — код короче, интерфейс проще. Цена такого упрощения перекладывается на человека, который в итоге доверяет системе больше, чем она заслуживает, и узнаёт о проблеме позже, чем мог бы. Честный отказ стоит нескольких дополнительных строк кода на стороне системы и нескольких секунд внимания специалиста в моменте — и экономит часы разбирательств уже после подачи заявки.
Одна и та же неудача распознавания даёт два разных исхода в зависимости от того, молчит система об ошибке или сообщает о ней.
Что не читается: границы честно
Ответ короткий: часть форматов не входит в контур пайплайна сознательно, а не по недосмотру — PPTX, ODT, RTF и архивы система не разбирает, и это стоит сказать прямо, а не обходить формулировками вроде «поддерживаем любой формат».
К такому обещанию в этой нише стоит относиться настороженно: скорее всего, вендор либо ещё не видел реального разнообразия документов, которые встречаются в тендерных пакетах, либо умалчивает, где на самом деле заканчиваются возможности его продукта. Честнее заранее назвать границу, чем позволить пользователю обнаружить её на важном документе в разгар подготовки заявки.
Отдельная и более коварная категория — не форматы, а формы, напечатанные как обычная сетка внутри технического задания. Такой документ заказчик обычно собирает в Word: форма попадает в файл как рядовая таблица, а готовый текст затем экспортируется в PDF. На выходе страница выглядит как форма для человека, но не несёт для машины никакой машиночитаемой разметки «это поле для заполнения» — ни полей AcroForm, ни какой-либо иной метки. Это не про качество распознавания текста на странице, а про то, что сама структура «здесь нужно вписать данные» физически не закодирована в файле. Подробный разбор того, как такие формы находятся и заполняются, — в отдельном материале.
Важно разделить эти два вида ограничений, потому что они требуют разного отношения. Отказ от Tier 3 форматов — это техническая граница пайплайна, и её можно спокойно обходить: пересохранить документ в PDF или DOCX перед загрузкой, если он изначально пришёл в другом формате. Форма-сетка внутри уже поддерживаемого формата — это не ограничение пайплайна, а ограничение самого документа: заказчик не заложил в него машиночитаемую структуру, и никакое улучшение OCR со стороны получателя эту структуру не создаст, потому что распознавание текста и распознавание назначения этого текста — разные задачи. Текст на такой странице читается прекрасно; то, что это именно форма для заполнения, а не описательный абзац, — вот что требует отдельного механизма, а не более мощной модели распознавания символов.
Что это меняет для тендерного пакета
Ответ короткий: в пакете участника доля отсканированных документов предсказуемо высока — уставные документы, лицензии, банковские справки нередко существуют только в виде сканов или фотографий, — и именно поэтому распознавание встроено прямо в контур хранилища документов, а не работает как отдельный внешний инструмент, который специалист должен вспомнить запустить.
Здесь стоит вернуться к теме, которая уже разбиралась в материале о структуре пакета: актуальность документа важнее идеального распознавания устаревшего. Безупречно распознанная банковская справка трёхмесячной давности не помогает заявке — она просто аккуратно оформленная ошибка. Распознавание решает задачу «прочитать то, что есть», но не решает задачу «убедиться, что это то, что нужно»; за это по-прежнему отвечает наполненность и актуальность хранилища, а не качество OCR. Что нейросеть делает с прочитанным дальше — классификация, извлечение полей, сопоставление с чек-листом — и где этот класс технологий систематически ломается, разобрано в отдельном материале. Разбор того, почему именно актуальность, а не полнота пакета, оказывается решающим фактором, и почему четыре слоя документов участника обновляются с разной частотой, — в материале «Тендерная документация: из чего собирается пакет и где он разваливается».
Если у вас есть тендерные документы, которые система раз за разом отказывается читать, — это почти всегда сигнал о конкретном уровне каскада, а не о распознавании вообще: полезно сначала проверить, есть ли в файле текстовый слой, прежде чем считать проблему нерешаемой.
Практический вывод для того, кто собирает пакет вручную или готовится передать эту работу системе: качество распознавания на выходе определяется тем, в каком виде документ был загружен на входе, а не только тем, насколько хорош OCR-движок за кулисами. Отсканированная с телефона фотография при плохом освещении даст более низкую уверенность распознавания, чем та же страница, отсканированная на планшетном сканере с ровным светом, — и это верно для любого OCR-сервиса, а не специфика конкретной модели. Там, где документ ещё предстоит получить — например, запросить у банка свежую справку или у СРО актуальную выписку, — разумно сразу попросить цифровую версию с текстовым слоем, а не скан бумажного оригинала: это снимает вопрос распознавания целиком, переводя документ сразу на уровень 1 каскада вместо уровня 2.
Это возвращает к тезису, с которого начинался этот текст: узкое место — не в модели распознавания, а во входе. Улучшать OCR можно бесконечно и почти всегда стоит — но нельзя подменить этим улучшением элементарную гигиену входящих документов: чем больше документов в пакете участника изначально существует в цифровом, а не отсканированном виде, тем меньше пакет вообще зависит от качества распознавания как такового.
Разбор конкретного пайплайна и вопросы по интеграции распознавания в ваш процесс сборки тендерной документации — можно обсудить напрямую, контакты команды.
