用PaddleOCR VL提取复杂数据

今天,我将用 PaddleOCR-VL 测试四个关键挑战:公式识别、表格识别、阅读顺序和手写文本。

用PaddleOCR VL提取复杂数据

一位关注者联系我,谈到了他们在使用 OCR 聊天机器人时遇到的问题。我觉得这是一个常见问题,所以决定制作一个新视频来帮助他和其他开发者。

当文档包含复杂的表格、数学公式或多列布局时,传统的 OCR 工具通常会生成混乱的内容,需要手动排序。

就在上周,我在浏览 GitHub 时,偶然发现了百度新开源的 PaddleOCR-VL-0.9B。

说实话,当我看到它只有 9 亿个参数时,我的第一个念头是“哦,又一个小型模型加入了进来?” 但出于职业好奇心,我不得不问:这个模型真的能做到吗?结果让我大吃一惊。

这不仅仅是 OCR,更是文档理解领域的一次飞跃。

PaddleOCR-VL 完全超出了我的预期。它在全球权威评测榜单 OmniDocBench v1.5 上获得了 92.6 分,综合性能全球第一。它的推理速度比 MinerU2.5 提升了 14.2%,比 dots.ocr 提升了 253.01%。

我最直观的感受是,它非常准确,或者说太准确了!它不愧是能够登顶并排名第一的模型。

那么,让我通过一个实时聊天机器人的快速演示来解释我的意思:

今天,我将用 PaddleOCR-VL 测试四个关键挑战:公式识别、表格识别、阅读顺序和手写文本。

首先,让我们从公式识别开始。我上传了一张包含复杂数学公式的图片。正如你所见,该模型处理这些公式非常出色——能够准确地识别上标、下标,甚至是非常长且复杂的表达式。

接下来是表格识别。这是一个出了名的难题,表格类型多样,有的带边框,有的不带边框,其中包含大量数字,这些数字很容易被模型误解。我在几个表格示例中使用了 PaddleOCR-VL,发现它的准确率确实令人印象深刻。

另一个主要挑战是理解文档结构和阅读顺序。在现代文档中,内容不仅更加复杂,而且布局也千差万别。想想多栏设计、文本和图像混合、折叠、彩色打印、倾斜扫描以及手写注释——所有这些都使 OCR 变得复杂。正确的阅读顺序并不总是简单的从上到下、从左到右的流程。

PaddleOCR-VL 技术报告展示了该模型如何像人类一样理解这些复杂的结构。无论是学术论文、多栏报纸还是技术报告,它都能智能地分析布局并恢复符合人类直觉的阅读顺序。

最后,即使在更复杂的布局下,PaddleOCR-VL 也能保持极高的稳定性。以这张手写笔记为例。它将文本、数字、段落和图像组合在一个通常只有人类才能辨认的左右、上下栏布局中。

1、PaddleOCR VL 的独特之处是什么?

PaddleOCR VL 不再只是简单的文本识别,而是能够真正“理解”文档结构。无论是学术论文、多栏报纸还是技术报告,PaddleOCR-VL 都能智能地理解文档布局,并自动按正确的顺序组织内容。

同时,它还能精准提取文档中复杂的内容信息,例如表格、数学公式、手写笔记和图表数据,并将其转换为可直接使用的结构化数据。

此外,它支持 109 种语言的识别,涵盖中文、英语、法语、日语、俄语、阿拉伯语和西班牙语等多语言场景,大幅提升了模型在多语言文档中的识别和处理能力。

2、PaddleOCR VL 的训练过程

PaddleOCR-VL 由两部分组成:PP-DocLayoutV2 和 PaddleOCR-VL-0.9B。

其中,核心部分是 PaddleOCR-VL-0.9B,它集成了预训练的视觉编码器、动态分辨率预处理器、双层 MLP 投影器以及预训练的大型语言模型。

预处理技术采用原生动态高分辨率。视觉编码器采用 NaViT 风格的编码器,支持原生分辨率输入。

这种设计减少了幻觉,并提升了性能。视觉语言模型 PaddleOCR-VL-0.9B。

投影器能够高效地将视觉编码器的特征连接到语言模型的嵌入空间。

在自回归语言模型中,整个序列是通过逐个预测词元生成的。这意味着解码器的大小直接影响整体推理延迟,因此模型越小,解码速度越快。

3、开始编码

现在让我们逐步探索,揭开创建强大推理应用程序的答案。我们将安装支持该模型的库。为此,我们将执行 pip install 命令。

复制以下内容:

!pip uninstall -y torch paddlepaddle paddlepaddle-gpu
!pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
!pip install paddleocr paddlepaddle
!pip install langchain langchain-community langchain-openai faiss-cpu sentence-transformers openai python-dotenv

下一步是常规步骤:我们将导入相关的库,随着我们进行一些基本配置,这些库的重要性将逐渐显现。

PaddleOCR:以业界领先的准确率将文档和图像转换为结构化的、AI 友好的数据(例如 JSON 和 Markdown),从而为 AI 应用提供支持。

import torch
from paddleocr import PaddleOCR
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.docstore.document import Document

我构建了这个 SimpleRAG 系统,它结合了 PaddleOCR-VL 进行文本提取和 OpenAI 生成查询。下面我将带您了解我的开发成果。

在初始化阶段,我设置了核心组件——我使用 HuggingFace 的 BGE 嵌入进行向量表示,并使用 GPT-4o 作为聊天模型,同时设置零温度以确保回复的一致性。我还初始化了向量存储和问答链的占位符,这些组件我们稍后会构建。

至于提取方法,我首先尝试使用 HuggingFace transformers 版本的 PaddleOCR,结果抛出了一个奇怪的错误,提示图像标记不匹配。然后安装 PaddlePaddle 竟然导致 PyTorch 崩溃(我不得不重启运行时并按正确的顺序重新安装所有组件)。之后,由于方法已被弃用,新方法的参数也不同,我只能不断猜测 API 的用法。

真正的突破出现在我打印出结果对象实际结构之后——原来它只是一个包含一个字典的列表,而这个字典有一个名为 rec_texts 的键,它实际上就是一个包含图像中所有文本字符串的列表。

因此,我不再需要尝试使用 .boxes.text 来访问复杂的嵌套对象结构,而只需要检查结果是否为字典,获取 rec_texts 键,并将这些字符串添加到我的列表中即可。

class SimpleRAG:
    def __init__(self):
        self.embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-en-v1.5")
        self.llm = ChatOpenAI(model="gpt-4o", temperature=0)
        self.vectorstore = None
        self.qa_chain = None
        self.ocr = PaddleOCR(use_textline_orientation=True, lang='en')
    
    def extract_text_from_images(self, image_paths: list):
        docs = []
        for path in image_paths:
            result = self.ocr.predict(input=path)
            
            text_lines = []
            for res in result:
                if isinstance(res, dict) and 'rec_texts' in res:
                    text_lines.extend(res['rec_texts'])
            
            text = "\n".join(text_lines) if text_lines else "No text found"
            docs.append(Document(page_content=text, metadata={'source': path}))
        
        return docs

在 build_index 中,我从所有图像中提取文本,使用 RecursiveCharacterTextSplitter 将文档分割成 1000 个字符、重叠 200 个字符的块,创建一个包含 BGE 嵌入的 FAISS 向量存储,并设置一个使用 GPT-4o 的 RetrievalQA 链,该链为每个查询检索前 3 个最相关的块。

对于查询,我只需将问题传递给 QA 链,该链负责检索和生成,并返回答案。

def build_index(self, image_paths: list):
        docs = self.extract_text_from_images(image_paths)
        
        text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
        splits = text_splitter.split_documents(docs)
        
        self.vectorstore = FAISS.from_documents(splits, self.embeddings)
        self.qa_chain = RetrievalQA.from_chain_type(
            llm=self.llm,
            retriever=self.vectorstore.as_retriever(search_kwargs={"k": 3})
        )
def query(self, question: str):
        return self.qa_chain.invoke(question)

# Usage
rag = SimpleRAG()
rag.build_index(["Your pic"])
answer = rag.query("extract all the table?")
print(answer)

4、结束语

在这个人工智能技术飞速发展的时代,我们常常被各种炒作所包围。关于“史上最强大”和“颠覆性”的说法并不多见。然而,真正有价值的突破往往源于解决特定问题并简化技术使用的创新。

PaddleOCR-VL 或许不会成为主流新闻头条,但对于每天需要处理文档的开发者来说,它可能是期待已久的解决方案。

毕竟,最好的技术是那些悄然融入日常工作,让你几乎察觉不到其存在的技术。PaddleOCR-VL 正朝着这个方向迈出坚实的一步。


原文链接:PaddleOCR VL + RAG: Revolutionize Complex Data Extraction (Open-Source)

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