Главная / Статьи

От отсканированных лабораторных отчетов к структурированным данным: компромиссы в архитектуре OCR

Как стартап в сфере здравоохранения с ограниченным бюджетом может сравнить библиотеки OCR, API Google Cloud и самостоятельно развернутые нейронные сети для обработки изображений при преобразовании медицинских сканов в структурированный JSON.

Издатель: REACTAPP.TOP8 мин чтения1779 слов

Источники: How We Chose Our OCR Architecture for a Medical Reports Pipeline (Part 1 of 2)

Преобразование фотографии лабораторного отчета в строку с текстом «Гемоглобин, 13.2, г/дл, норма 12.0–15.5» кажется проблемой OCR, но распознавание обычного текста — это лишь первый шаг. Настоящая задача заключается в том, чтобы дешево, надежно и без утечки данных пациента извлечь из неструктурированного скана его смысл. В этом руководстве описаны архитектурные решения, лежащие в основе одного из таких инструментов для извлечения данных в рамках MVP медицинских отчетов, чтобы вы могли использовать эти принципы при решении аналогичных задач по пониманию документов с ограниченным бюджетом.

Требование, которое определяет всё

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

Именно последнее утверждение является ключевым. Инструмент, возвращающий блок распознанных символов, сам по себе не соответствует этому требованию. Необходимо еще определить, какое число относится к какому тесту, какая строка является единицей измерения и какая пара чисел представляет собой нормальный диапазон. Каждое решение касается того, где происходит этот шаг «понимания» и какова его стоимость.

Ограничения были типичными для MVP: небольшая команда, ограниченный бюджет на инфраструктуру и ожидаемый начальный объем примерно 500 загруженных отчетов в день, что соответствует примерно 30 000 страницам в месяц.

Решение 1: Выбор языка для реализации

Преимущества экосистемы Python действительно существуют

Если начать с вопроса «какой язык обладает лучшими инструментами для OCR и машинного обучения», то Python без особых споров остается победителем. Зрелые open-source-механизмы вроде PaddleOCR и EasyOCR разработаны прежде всего для Python, у OpenCV там есть первоклассные биндинги, а большинство примеров по компьютерному зрению предполагают использование именно этого языка. Пайплайн OCR с нуля естественным образом будет создаваться на Python.

Также важно честно говорить о том, что не является фактором отличия. API Vision от Google был одним из рассматриваемых платных вариантов, причем Google предоставляет клиентские библиотеки как для Python, так и для Go. Следовательно, наличие SDK не отдавало преимущества ни одному из языков.

Почему всё равно победил Go

Решающими факторами стали аспекты окружающей системы, а не сам OCR. Остальная часть асинхронной обработки уже была спланирована как работа в режиме Go: она потребляет задания из Redis Streams, загружает загруженные файлы из объектного хранилища Cloudflare R2 и записывает результаты в Postgres. Реализация этапа извлечения данных на Python означала бы необходимость запуска двух сред выполнения, отдельного развертывания, управления зависимостями и мониторинга для одной функции. Кроме того, инженер, разрабатывавший этот продукт, работал наиболее эффективно с использованием Go для подобных инфраструктурных сервисов.

Общий урок: язык с наиболее обширной библиотекой каталогов не всегда является наилучшим выбором. Если шаг извлечения данных можно свести к вызову модели по HTTP (что и происходит в данной архитектуре), то использование единой среды выполнения для всего слоя рабочих процессов часто ценнее, чем обширность библиотеки, с которой вы почти не будете работать.

Решение 2: облачные API против самостоятельного хостинга, с учетом стоимости

Команда сравнила четыре варианта с ожидаемым объемом в 30 000 страниц в месяц. Приведенные ниже цифры — это оценки, использованные во время оценки; цены в облаках могут меняться, поэтому перед использованием их рекомендуется проверять актуальные тарифы.

  • Google Cloud Vision с функцией DOCUMENT_TEXT_DETECTION. Возвращает необработанный текст вместе с координатами, без структурированных полей. Стоимость составляет примерно 1,50 доллара за 1 000 страниц, то есть примерно 45 долларов в месяц.
  • Google Document AI (Form или Custom Parser). Возвращает структурированные пары «ключ-значение» и таблицы. Стоимость составляет от 30 до 65 долларов за 1 000 страниц, что примерно соответствует 900–1 950 долларам в месяц.
  • Gemini Flash на Vertex AI. Работает в мультимодальном режиме и на основе промптов, возвращает структурированный JSON. Оплата производится за токены; оценочная стоимость составляет примерно 20–50 долларов в месяц.
  • Самостоятельно развернутый ЯЗЫК ИИ для обработки изображений (MiniCPM-V от Ollama). Прямо генерирует структурированный JSON. Расходы — это фиксированная стоимость хостинга сервера, примерно 40–80 долларов в месяц за VPS, независимо от объема работы.
  • Как правильно интерпретировать цифры

    API Vision кажется недорогой, но решает совершенно другую проблему. Она сообщает о том, что символы «13.2» находятся в определенных координатах; она не имеет понятия о том, что это показатели гемоглобина. Вам все равно придется самостоятельно создавать весь слой обработки данных, поэтому ее стоимость несопоставима с вариантами, возвращающими структурированные данные.

    Document AI действительно возвращает структурированные данные, но стоимость в размере от 1000 до 2000 долларов в месяц является высокой переменной затратой для продукта, который еще не принес дохода.

    Gemini Flash — действительно интересный конкурент. Ценообразование на основе токенов для отсканированных страниц находится в том же диапазоне, что и при самостоятельном хостинге, к тому же не требуется наличие инфраструктуры с GPU. Так почему бы не выбрать именно его?

    Почему самостоятельный хостинг оказался предпочтительнее

    Решение было принято под влиянием трех аргументов:

    • Лимит стоимости. Одиночный узел стоит одинаково независимо от того, обрабатывает ли он 5 000 или 50 000 страниц. У API с измерением трафика нет такого лимита: всплеск нагрузки, серия попыток обработки или массовый импорт непосредственно отражаются в счете.
    • Изоляция данных. Медицинские отчеты содержат конфиденциальную информацию о здоровье. Выполнение операций извлечения во внутренней частной сети команды означает, что документы пациентов никогда не отправляются на API стороннего поставщика при каждой загрузке, что позволяет избежать целого ряда вопросов, связанных с соблюдением нормативов и проверкой поставщиком, с которыми команда MVP не может справиться.
    • Отсутствие внешних квот и задержек. Не существует ограничений по скорости обработки, уровней одновременной работы или дополнительных сетевых прыжков на критическом пути.

    В результате были отклонены варианты Google Cloud и Vertex AI, и было принято решение использовать полностью самохостинговую инфраструктуру.

    Полезно также учитывать и обратную сторону. Расходы на сервер остаются предсказуемыми только до уровня пропускной способности, который может обеспечить один узел; за его пределами приходится покупать дополнительное оборудование и самостоятельно заниматься планированием мощностей и обеспечением непрерывной работы. Самостоятельное хостинг также не освобождает от обязанностей по соблюдению норм, поскольку вы продолжаете нести ответственность за хранение данных, контроль доступа и их аудит. Для небольшой, стабильной нагрузки с конфиденциальными данными обычно выгоднее самостоятельное хостинг; в случае резкого роста объемов работы и отсутствия у команды возможностей для управления, более разумным решением может стать использование услуг управляемого API.

    Решение 3: Игнорирование традиционных библиотек OCR

    Инструменты с открытым исходным кодом, такие как PaddleOCR и Docling, способны выполнять задачу, но их результаты предназначены для отображения. Обычно контент формируется с использованием тегов макетирования или форматируется в Markdown, чтобы хорошо отображаться в интерфейсе или HTML-странице. Это идеально, когда результат будет читать человек, но неудобно, когда коду нужно извлечь значение вроде «Гемоглобин: 13,2 г/дл» в виде чистого поля.

    Преодоление этого разрыва — это самостоятельный проект. Потребуется извлекать значения из структуры тегов, пробовать различные подходы в процессе тестирования для адаптации к разным лабораториям и форматам отчетов, а также, вероятно, использовать инструменты предобработки или постобработки от OpenCV для таблиц и областей, которые движок не смог корректно сегментировать. Все это дополняет работу по интеграции и размещению движка OCR. Для минимально жизнеспособной версии продукта это означает огромный объем инженерных задач по созданию инфраструктуры, а не самого продукта.

    Следует обратить внимание на один важный момент: данная оценка отражает мнение команды, а не окончательный вердикт относительно этих инструментов. Инженеры с более глубоким опытом работы с PaddleOCR или Docling могут знать более быстрые способы преобразования структурированных данных в чистые поля, к тому же оба проекта быстро развиваются, поэтому стоит снова проверить их текущие форматы вывода.

    Решение 4: Самостоятельно развернутая модель LLM для обработки изображений, адаптированная под бюджет

    Извлечение смысла вместо символов

    Альтернативой подходу «OCR, затем написание парсера для результата OCR» является использование модели языка с возможностями обработки изображений, способной выполнять оба шага одновременно. Классический OCR распознаёт символы. Модель LLM для обработки изображений, получив хорошо структурированный запрос, может проанализировать отсканированную страницу и сразу вернуть поля параметра, значения и единицы измерения, пропустив промежуточный этап обработки маркированного Markdown.

    Здесь возможности обработки изображений являются неотъемлемыми, а не дополнительным улучшением. Модель, работающая только с текстом, не может помочь с отсканированным изображением, поскольку у неё пока нет текста. Модели приходится сами читать пиксели.

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

    Выбор модели, которую можно реально запустить

    При выборе модели также применялась та же логика, связанная с бюджетом. Более крупные модели Qwen, способные обрабатывать изображения, действительно мощны, но для их работы на собственном оборудовании требуется больше VRAM и вычислительных ресурсов, чем было целесообразно с учетом инфраструктуры, которую команда покупала за счет бюджета MVP. В итоге была выбрана MiniCPM-V — гораздо меньшая модель, которую Ollama может запускать на недорогом оборудовании без проблем, при этом она достаточно хороша для структурированной обработки изображений лабораторных отчетов.

    Если вы повторите этот эксперимент, протестируйте кандидатские модели на репрезентативной выборке ваших реальных документов, включая размытые фотографии с телефона и необычную компоновку лабораторий, а не полагайтесь только на показатели из таблицы лидеров. Самая лучшая по теории модель бесполезна, если у вас нет возможности ее запускать.

    Что еще нужно для реализации

    Приведенная выше архитектура определяет, что обрабатывается; процесс производства все еще должен решать вопрос как. Дальнейшие действия включают преобразование PDF в изображения, которые может читать модель, структурирование запроса к API Ollama и текста-подсказки, защищенный парсинг JSON в случае, если небольшая модель отклоняется от запрошенного формата, а также использование Redis Streams в рабочем процессе на Go для надежной обработки отчетов по мере роста объема данных.

    Основные выводы

    • Сначала определите необходимый результат (здесь: имя, значение, единица измерения, диапазон ссылок), прежде чем сравнивать инструменты; необработанный текст, полученный с помощью OCR, и структурированные данные — это разные продукты с разными ценами.
    • Выбирайте язык для всей системы, а не только тот, у которого есть самый богатый набор библиотек для одного компонента.
    • Сравнивайте облачные решения по эквивалентному результату, затем учитывайте пределы затрат, изоляцию данных и квоты наряду с основной ценой.
  • Результаты OCR, ориентированные на отрисовку, могут скрыть сложность процесса парсинга; нейросеть визуального анализа позволяет объединить OCR и парсинг в один шаг.
  • Подберите модель под имеющееся у вас оборудование, тщательно проверьте её результаты и заново убедитесь в ценах и возможностях инструмента перед принятием решения.