文档提取:从OCR到视觉大模型

令人惊讶的是,大多数医疗保健组织仍然依赖遗留技术。传真机、寻呼机和电话仍在大量使用。

许多外部实验室结果(病理学、放射学、遗传测试等)仍然通过传真到达,而不是通过API。像eFax这样的服务可以接收这些传真,并将它们交付到电子邮件收件箱或文件共享中,工作人员手动审查它们并将它们路由到EHR(电子健康记录)系统中的正确患者记录。

我最近一直在开发一个概念验证(PoC),用于自动化接收管道,以处理这些传真并将数据提取到结构化格式。输出可以存储在数据库中,并与UI应用程序配对,诊所工作人员可以在其中监控和查看传入结果。

本文涵盖了我在这个项目中学到的关于从PDF提取信息的知识,并将PoC描述为迈向更全面自动化医疗文档接收系统的潜在垫脚石。这包括将系统与AI助手集成。

如果您宁愿跳过从PDF提取文本的细节,只对创建的处理这些传真的PoC系统感兴趣,请点击这里

1、挑战

第一个惊喜是意识到从电子文档提取信息仍然不是一个解决的问题。OCR已经存在很长时间,所以我假设我可以插入一个足够好的解决方案。我错了。

在对医疗结果文档进行一些快速尝试提取数据后,我了解到它们不是基于文本的PDF,其中文本可以以编程方式提取。虽然它们作为PDF到达,但每个文件本质上是围绕扫描页面嵌入图像的包装,所以直接文本提取不起作用。没有问题,我想。我会用OCR来提取信息。

PoC的第一迭代使用OCR在转换为结构化数据之前提取文本。它在技术上工作,但准确性不够好。它错过了数据元素,弄乱了文本,并产生了太多字符识别错误而无法信任。

2、解决方案

突破来自一个意外的转向:完全移除OCR。

而不是OCR,我们切换到一个能够解释每一页并将其转换为Markdown的视觉能力LLM。这保留了布局和格式,包括表格,作为数据提取之前的中间步骤。

移除OCR并添加Markdown转换步骤显著提高了提取准确性。权衡是如果您在本地运行以确保数据隐私,则计算要求更高,如果在云中运行则成本更高。对于像医疗文档处理这样的准确性优先工作流程,这是可以接受的妥协。

在接下来的部分,我将分享我学到的关于PDF和从它们提取数据的知识,以及我们构建的PoC系统的概述。

3、PDF文档基础

文档处理系统需要处理的PDF有三种基本类型:纯文本PDF,其中所有内容可以直接提取;混合PDF,其中信息包含在文本和图像的混合中;以及纯图像PDF,其中所有内容都包含在图像中。下图显示了这些类型及其提取特征。

PDF基本类型和提取特征

下表显示了不同文本提取方法以及每种PDF类型和提取方法的特征:

每种PDF文档类型的提取方法和结果

4、直接文本提取

对于简单的纯文本PDF,提取内容很简单,几乎没有错误机会,因为文本是直接复制的。缺点是这种方法只适用于纯文本PDF,并且格式如布局和表格会丢失。因此,输出可能成为文本块,当存在列或表格时,内容可能被错误排序。下面示例显示使用Python中的PyPDF包进行直接文本提取:

使用Doc2MD(视觉-LLM转换)将PDF转换为Markdown的示例

使用此方法从PDF提取文本的完整代码可以在下面找到(我假设您使用“uv”作为您的python环境):

"""
Extract text from a PDF and print to stdout.

Usage:
    uv run example_basic_text_extraction.py <pdf_file_path>

Dependencies:
    - pypdf (install with: uv pip install pypdf)
"""

import sys
from pathlib import Path
import pypdf


def main():
    if len(sys.argv) < 2:
        print("Usage: uv run example_basic_text_extraction.py <pdf_file_path>")
        sys.exit(1)
    
    pdf_path = Path(sys.argv[1])
    
    # Open and read the PDF
    with open(pdf_path, 'rb') as file:
        pdf_reader = pypdf.PdfReader(file)
        
        # Extract text from each page
        for page in pdf_reader.pages:
            text = page.extract_text()
            print(text)


if __name__ == "__main__":
    main()

5、OCR提取

我们将检查的下一个方法是光学字符识别(OCR)。对于混合PDF(文本和图像的混合)和纯图像PDF,可以使用OCR来提取文本内容。这种方法与直接文本提取共享一些相同的限制。格式如布局和表格会丢失,文本可能被错误排序,但OCR也会引入字符识别错误,尤其当图像或扫描质量低时。在此示例中,我们将使用Tesseractpdf2image Python包。

注意: 除了Python包之外,这还需要在您的操作系统中安装“tesseract”和“poppler”实用程序:

  • MacOS: "brew install tesseract poppler"
  • Linux (Ubuntu): "sudo apt-get install tesseract-ocr poppler-utils"
  • Windows: Tesseract: 从UB Mannheim下载;Poppler: 从GitHub下载
使用直接文本提取从PDF提取文本的示例

使用此方法从PDF提取文本的完整代码可以在下面找到:

"""
Extract text from a PDF using OCR and print to stdout.

Usage:
    uv run example_ocr_extraction.py <pdf_file_path>

Dependencies:
    - pytesseract (install with: uv pip install pytesseract)
    - pdf2image (install with: uv pip install pdf2image)

System Requirements:
    - Tesseract OCR: "brew install tesseract" (macOS), "sudo apt-get install tesseract-ocr" (Ubuntu)
    - poppler-utils: "brew install poppler" (macOS), "sudo apt-get install poppler-utils" (Ubuntu)
"""

import sys
from pathlib import Path
import pytesseract
from pdf2image import convert_from_path


def main():
    if len(sys.argv) < 2:
        print("Usage: uv run example_ocr_extraction.py <pdf_file_path>")
        sys.exit(1)
    
    pdf_path = Path(sys.argv[1])
    
    # Convert PDF to images
    images = convert_from_path(pdf_path, dpi=300)
    
    # Perform OCR on each page
    for image in images:
        text = pytesseract.image_to_string(image)
        print(text)


if __name__ == "__main__":
    main()sdf

6、用视觉LLM转换和提取 Markdown

正如我在本文早期的"挑战"和"解决方案"部分所注意到的,我需要处理的许多文件是质量差的扫描,而OCR不够准确。它产生了太多识别错误和太多乱码文本,无法可靠提取所需数据。我估计我只能正确提取大约80%的所需数据。

我在几个过去项目中使用过LLM驱动的管道,包括使用视觉能力(多模态)LLM的图像分类管道(LLaVA)。我决定尝试当时可用的最好的开源视觉模型。经过一些快速测试,它比OCR慢得多,但准确性显著更高。

下一个重大突破来自在结构化数据提取之前添加Markdown转换步骤。下面是使用我在此项目期间创建的独立Doc2MD实用程序进行PDF到Markdown过程的示例。最重要的是对于医疗结果文档,它保留了表格,这使得提取相关数据更容易。

使用Doc2MD(视觉-LLM转换)将PDF转换为Markdown的示例

我已经开源了我作为此项目一部分创建的视觉-LLM驱动的PDF/图像到Markdown实用程序,可以在这里找到:https://github.com/robert-mcdermott/doc2md

7、Markdown提取比较:OCR vs. 视觉LLM

7.1 OCR:质量差的扫描、复杂文档

示例1: OCR中有许多字符识别错误,一些扫描伪影如页面边缘被错误检测为字符。从这个文本中提取一些数据仍然是可能的,但会有太多错误而无法信任。

质量差复杂文档示例1的OCR文本提取

示例2: 这个文档甚至更复杂,输出中有太多错误和乱码文本而无法使用:

质量差复杂文档示例2的OCR文本提取

7.2 视觉-LLM:质量差的扫描、复杂文档

示例1:与此文档的OCR版本相比,它在转换中做得很好。我们必须意识到的一件事是LLM可能超出提取,并添加东西来填补空白或尝试"帮助"。在此示例中,它添加了下面指示的有用信息,这些信息在原始文档中不存在:

质量差复杂文档示例1的视觉-LLM提取和Markdown转换

示例2: 这个文档被选为最坏情况示例。表格中没有水平线,一些行是嵌套的,它是扭曲的。虽然输出不完美,但它在尝试以Markdown重新创建它时仍然做得令人印象深刻。幸运的是,我需要处理的医疗结果文档没有这么乱:

质量差复杂文档示例2的视觉-LLM提取和Markdown转换

很明显,一个视觉-LLM,即使是一个小的开源模型在本地运行,也比OCR在从扫描文档准确提取信息方面优越得多。

8、文档到Markdown转换工具

因为我在构建LLM驱动的数据管道和使用视觉能力LLM方面有以前的经验,我在花时间看看已经存在什么之前就开始构建自己的解决方案。在创建Doc2MD后,我后来发现了类似的工具,还有几个额外的解决方案随后发布。

在本节中,我将分享Doc2MD的信息以及我后来发现的两个其他系统:DeepSeek-OCR和Docling。

8.1 Doc2MD

Doc2MD是我创建并在此PoC项目中开源的独立实用程序。它作为视觉-LLM驱动的文档到Markdown方法的公共示例:

Doc2MD

8.2 DeepSeek-OCR

DeepSeek-OCR名称中的"OCR"有点误导。它不使用像Tesseract这样的传统OCR方法。相反,它使用具有令人印象深刻提取能力的视觉能力LLM:

DeepSeek OCR

DeepSeek-OCR可以根据系统提示有不同的输出类型。它可以输出:

  • 文档的高级描述
  • 文档内容的Markdown版本
  • 文档中的文本,带有文本来自文档中位置的坐标
  • 原始文档的图像,在每个检测/提取的文本块上带有颜色编码的边界框。
DeepSeek-OCR示例与代码及其输出

这是DeepSeek-OCR可以产生的独特边界框覆盖和坐标输出的特写:

DeepSeek-OCR边界框覆盖和坐标输出

8.3 Docling

Docling是另一个强大的文档文本提取实用程序,具有广泛的选项和功能。我能够使用Docling获得类似于我使用DeepSeek-OCR产生的输出。使用Docling,我能够生成以下输出格式:

  • Doctags与坐标
  • HTML
  • Markdown

DeepSeek-OCR主要是模型,而Docling是具有广泛功能的完整功能实用程序。如果我早知道Docling,我可能不会创建Doc2MD,而是使用Docling作为我们医疗结果管道PoC的一部分:

Docling示例与代码及其输出

9、PoC:医疗结果传真文档处理

我开始这条路径并学到我涵盖的所有东西的原因是构建外部医疗结果传真处理管道,我将在本文的其余部分涵盖它。如前面所注意的,这个管道最初使用OCR从传入传真提取信息,但它不够准确。

注意: 下面示例中显示的所有患者信息(PHI)都是假的,这篇文章不包含敏感信息。

9.1 顶层概念

下面的图像显示了视觉-LLM驱动管道的高水平概念。简而言之,文档被转换为图像栈(每页一个图像)。这些图像然后传递给视觉能力LLM,它将文档转换为Markdown。Markdown然后被馈送到带有任务特定提取指令的纯文本LLM,它返回存储在数据库中的JSON文档:

文档处理管道的顶层概念

9.2 数据模式

在与主题专家合作定义应该从外部医疗结果文档捕获什么数据后,我们为管道的数据提取阶段创建了以下模式:

用于医疗结果管道的数据模式

9.3 顶层架构图

下面是构建用于处理外部医疗结果文档的PoC系统的顶层图表。系统的直接文本提取和OCR提取能力首先实现,如果需要仍然可以使用,但视觉-LLM提取配置为默认方法:

PoC文档处理系统的顶层架构图

9.4 管理和监控界面

PoC系统包括一个基本管理UI,可用于监控指标、健康和配置,以及控制启动、停止或手动触发文档摄取目录扫描:

文档处理系统管理面板

9.5 搜索界面和结果

系统包括搜索界面,用户可以在其中对整个文档文本执行全文搜索或搜索特定字段。匹配记录显示在表格中:

搜索和文档结果界面

9.6 文档详情、审查、编辑、导出和查看

当用户为搜索结果中的记录点击"查看"操作时,他们被带到文档详情页面。在那里,他们可以审查提取的数据,如果需要进行编辑,导出数据,并查看文档:

文档详情、审查和导出界面

9.7 API

系统公开API,可用于监控、控制、搜索和检索文档。这个API还启用与其他系统的集成:

具有示例的医疗结果文档处理系统API

10、AI医疗结果助手

使用上面显示的API,我们构建了一个AI助手,允许用户询问关于文档、患者特定结果或系统可以回答的任何其他问题。助手使用API检索相关信息并响应用户。

MCP(模型上下文协议)服务器也可以使用相同的API为AI代理提供干净接口到文档系统。下图显示了IOERD助手如何与文档系统接口。

AI助手如何与医疗结果文档系统接口

为了保持一切开源和开放权重,我们使用OpenAI的开放权重模型,GPT-OSS-120B,用于AI助手。这允许整个系统在内部运行,防止敏感数据离开校园网络。

10.1 AI助手示例

  • 左侧的示例(下方图像),显示代理告诉用户它是什么、它的目的是什么以及它如何帮助他们
  • 右侧的示例(下方图像),显示助手获取并显示系统收到的最后5条记录:
AI助手与医疗结果文档系统接口
  • 左侧的示例(下方图像),显示助手基于标本/样本编号找到结果文档。
  • 右侧的示例(下方图像),显示助手找到特定患者的結果:
AI助手与医疗结果文档系统接口

11、结束语

OCR对于某些用例仍然有用,但对于从复杂文档提取信息,尤其是质量低于最佳的扫描文档,它比新的视觉-LLM方法表现差得多。在实践中,LLM也比杂乱的提取单词流更可靠地处理Markdown,所以在运行任何提取步骤之前将文档转换为Markdown可能是游戏改变者。

视觉-LLM方法相对于OCR的主要缺点是成本和性能。如果在本地GPU上运行以确保数据隐私,它更具计算密集性,如果在租用GPU(例如,AWS EC2)上运行或按token计费(例如,OpenAI、Anthropic或AWS Bedrock)时,它可能更昂贵。对于像医疗文档处理这样的准确性优先工作流程,这是可以接受的妥协。


原文链接:OCR Isn't Good Enough: From Faxes to Structured Data

汇智网翻译整理,转载请标明出处