面对复杂排版的文档——如表格、公式、多栏文本,传统OCR工具往往表现不佳。POINTS-Reader提出一种全新的两阶段训练框架,彻底摆脱对“教师模型”的依赖,实现了端到端的高精度文档转换。

在数字化时代,我们经常需要将纸质文档或扫描文件转换为可编辑的电子文本。无论是学术论文、技术报告还是商业文件,其中往往包含复杂的排版元素:多栏文本、嵌套表格、数学公式等。

传统处理方法通常采用流程式方案(pipeline),即先用OCR识别文字,再用专门模型处理表格和公式,最后手动调整结果。这种方式不仅效率低下,而且在处理复杂布局时错误率较高。

近年来,基于视觉-语言模型(Vision-Language Models, VLMs)的端到端方法逐渐兴起,但这类模型通常需要从大型模型(如GPT-4o)蒸馏(distillation)知识来训练,存在性能上限和误差传递的问题。

POINTS-Reader的创新之处在于:它完全摒弃了蒸馏训练,通过两阶段数据构建框架,首先生成大量合成数据让模型“热身”,然后通过自改进机制不断优化模型在真实文档上的表现。最终得到的模型不仅性能优异,而且支持中英文文档的精准转换。

1. 文档转换的挑战与现有方法的局限

文档转换任务的核心难点在于其多样性:纯文本、表格、数学公式和图像等元素需要以不同的格式输出。例如,表格可以用Markdown、HTML或LaTeX等多种方式表示,这种输出格式的不一致性增加了模型学习的难度。

现有的端到端文档转换方法大多依赖于从大型教师模型蒸馏知识。这种方法有两个主要缺陷:

  1. 性能天花板:学生模型很难完全达到教师模型的性能水平
  2. 误差传递:学生模型会继承教师模型的错误和偏差

如下图展示了蒸馏方法可能带来的问题——模型可能无法识别表格、遗漏文本或错误解析表格结构。

Example annotations generated by Qwen2.5-VL-72B and POINTS-Reader

2. POINTS-Reader的核心创新:两阶段训练框架

POINTS-Reader采用了一种全新的两阶段训练方法,完全摆脱了对蒸馏数据的依赖。

2.1 统一格式预热阶段(Uniform Format Warm-up Stage)

在这个阶段,研究团队首先统一了输出格式

  • 纯文本:使用Markdown格式
  • 表格:使用HTML格式(因为Markdown表格无法处理合并单元格等复杂结构,而LaTeX表格缺乏标准化)
  • 数学公式:使用LaTeX格式,行内公式用$...$,独立公式用$$...$$

基于这些统一格式,团队使用大语言模型生成大量文本,并通过以下四种类型增加数据多样性:

  1. 纯文本
  2. 含数学公式的文本
  3. 含表格的文本
  4. 含表格的多栏布局文本

生成的文本随后被转换为HTML并通过Chrome无头模式渲染成图像,最终形成图像-文本对用于训练模型。

2.2 迭代自改进阶段(Iterative Self-improvement Stage)

虽然合成数据可以进行大规模训练,但其分布(如布局)与真实文档仍有差异。为了弥补这一差距,POINTS-Reader引入了迭代自改进框架

这个过程如下:

  1. 使用当前模型对大规模真实文档(如DocMatrix)进行推理,生成文本注释
  2. 应用过滤策略自动验证生成的数据质量
  3. 使用过滤后的高质量数据重新训练模型
  4. 重复这一过程多次,逐步提高模型性能和数据质量
Demonstration of the two-stage pipeline

3. 高质量数据过滤策略

在自改进阶段,POINTS-Reader设计了三种针对性的过滤策略,确保只有高质量数据用于训练。

3.1 纯文本过滤

采用F1分数来过滤纯文本内容。具体步骤如下:

  1. 使用传统OCR模型(如PaddleOCR)提取参考文本
  2. 对模型预测和参考文本进行标准化处理:移除非字母数字字符,按空格分割文本
  3. 统计每个单元的出现次数
  4. 计算精确率、召回率和F1分数

F1分数低于阈值(如0.9)的样本会被丢弃。这种方法显著减少了缺失主要文本部分和幻觉等问题。

3.2 表格过滤

专注于确保表格结构有效性:验证模型输出中每个表格的行列单元格数量一致性。结构无效的样本会被移除。

3.3 数学公式过滤

只验证公式的语法正确性,不检查语义有效性。所有从模型输出中提取的公式都会进行语法错误检查,包含无效公式的样本会被丢弃。

4. 实验效果与性能对比

POINTS-Reader在多个基准测试中表现优异,超越了许多现有公共和专有模型。

4.1 性能对比

下表展示了POINTS-Reader与其他方法在OmniDocBench基准测试上的性能对比:

方法类型 方法 整体错误率↓ 文本错误率↓ 公式错误率↓ 表格错误率↓ 阅读顺序错误率↓
流程式方法 MinerU 0.150 0.061 0.278 0.18 0.079
Marker 0.336 0.080 0.530 0.619 0.114
Mathpix 0.191 0.105 0.306 0.243 0.108
通用视觉-语言模型 Qwen2.5-VL-72B 0.214 0.092 0.315 0.341 0.106
专业视觉-语言模型 GOT-OCR 0.287 0.189 0.360 0.532 0.141
Nougat 0.452 0.365 0.488 0.572 0.382
Mistral OCR 0.268 0.072 0.318 0.600 0.083
POINTS-Reader 0.259 0.176 0.383 0.335 0.144

从表中可以看出,POINTS-Reader在多数指标上优于其他方法,特别是在表格识别方面,它在OmniDocBench的表格指标上比GOT-OCR高出0.197。

4.2 消融实验与研究发现

团队进行了广泛的消融实验,验证了各个组件的有效性:

数据多样性带来性能提升:通过逐步增加不同类型的数据(纯文本、公式、表格、多栏布局),模型性能得到持续提升。特别是添加多栏布局数据后,阅读顺序性能得到显著改善。

数据规模存在饱和点:当合成数据规模超过80万样本时,模型性能不再提升甚至下降。这表明合成数据与真实数据分布存在差异,过度增加合成数据会导致过拟合,从而降低模型泛化能力。

纵横比过滤提升性能:通过过滤掉纵横比异常(超出2/5至5/9范围)的图像,模型准确性得到进一步提高。这是因为A4纸(最常见的文档布局)的纵横比为√2(ISO 216),保持接近这一比例的图像更有助于模型学习。

5. 如何使用POINTS-Reader

POINTS-Reader的使用非常简单,只需要一个固定的提示词和文档图像作为输入,输出则是一个包含提取文本的字符串。

5.1 环境配置

推荐使用以下环境运行POINTS-Reader:

python==3.10.12
torch==2.5.1
transformers==4.55.2
cuda==12.1

5.2 使用Transformers库运行

首先安装WePOINTS库:

git clone https://github.com/WePOINTS/WePOINTS.git
cd ./WePOINTS
pip install -e .

然后使用以下代码运行模型:

from transformers import AutoModelForCausalLM, AutoTokenizer, Qwen2VLImageProcessor
import torch

# 推荐使用以下提示词以获得最佳性能
prompt = (
    'Please extract all the text from the image with the following requirements:\n'
    '1. Return tables in HTML format.\n'
    '2. Return all other text in Markdown format.'
)
image_path = '/path/to/your/local/image'
model_path = 'tencent/POINTS-Reader'
model = AutoModelForCausalLM.from_pretrained(model_path,
                                             trust_remote_code=True,
                                             torch_dtype=torch.float16,
                                             device_map='cuda')
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
image_processor = Qwen2VLImageProcessor.from_pretrained(model_path)
content = [
            dict(type='image', image=image_path),
            dict(type='text', text=prompt)
          ]
messages = [
        {
            'role': 'user',
            'content': content
        }
    ]
generation_config = {
        'max_new_tokens': 2048,
        'repetition_penalty': 1.05,
        'temperature': 0.7,
        'top_p': 0.8,
        'top_k': 20,
        'do_sample': True
    }
response = model.chat(
    messages,
    tokenizer,
    image_processor,
    generation_config
)
print(response)

如果遇到内容重复的问题,可以尝试提高图像分辨率来缓解。

5.3 使用SGLang部署

POINTS-Reader支持通过SGLang进行高效部署。首先需要安装SGLang(目前需要通过特定分支安装):

然后使用以下命令部署模型:

python3 -m sglang.launch_server \
--model-path tencent/POINTS-Reader \
--tp-size 1 \
--dp-size 1 \
--chat-template points-v15-chat \
--trust-remote-code \
--port 8081

部署后可以使用以下代码调用模型:

from typing import List
import requests
import json

def call_wepoints(messages: List[dict],
                 temperature: float = 0.0,
                 max_new_tokens: int = 2048,
                 repetition_penalty: float = 1.05,
                 top_p: float = 0.8,
                 top_k: int = 20,
                 do_sample: bool = True,
                 url: str = 'http://127.0.0.1:8081/v1/chat/completions') -> str:
    """调用WePOINTS模型生成响应"""
    data = {
        'model': 'WePoints',
        'messages': messages,
        'max_new_tokens': max_new_tokens,
        'temperature': temperature,
        'repetition_penalty': repetition_penalty,
        'top_p': top_p,
        'top_k': top_k,
        'do_sample': do_sample,
    }
    response = requests.post(url, json=data)
    response = json.loads(response.text)
    response = response['choices'][0]['message']['content']
    return response

prompt = (
    'Please extract all the text from the image with the following requirements:\n'
    '1. Return tables in HTML format.\n'
    '2. Return all other text in Markdown format.'
)

messages = [{
              'role': 'user',
              'content': [
                  {
                      'type': 'text',
                      'text': prompt
                  },
                  {
                      'type': 'image_url',
                      'image_url': {'url': '/path/to/image.jpg'}
                  }
              ]
            }]
response = call_wepoints(messages)
print(response)

6. 实际应用示例

POINTS-Reader在处理各种类型的文档时都表现出色:

6.1 含LaTeX公式的单栏文档

Example 1

6.2 含表格的单栏文档

Example 2

6.3 含LaTeX公式的多栏文档

Example 3

6.4 含表格的多栏文档

Example 4

7. 当前限制与未来方向

尽管POINTS-Reader在文档转换方面取得了显著进展,但仍存在一些限制:

  1. 语言支持有限:目前主要支持英文和中文,对其他广泛使用的语言(如日文、韩文等)支持有限
  2. 手写体处理不足:所有训练数据均使用印刷字体,导致处理手写文本(如笔记)时性能不理想
  3. 图像提取功能缺失:当前模型仅支持纯文本、公式和表格的提取,尚未支持文档中图像的识别和位置输出

未来,团队计划持续增强POINTS-Reader的多语言能力,并改进对手写体的支持。同时,还将扩展模型功能,使其能够识别和输出文档中图像的位置信息。

8. 常见问题解答

POINTS-Reader与传统OCR有什么区别?

传统OCR通常只能识别纯文本,对于复杂元素(如表格、公式)需要额外处理。POINTS-Reader是端到端的视觉-语言模型,能够同时处理文本、表格和公式,并以结构化格式输出。

POINTS-Reader支持哪些输出格式?

POINTS-Reader使用统一的输出格式:纯文本用Markdown,表格用HTML,数学公式用LaTeX。这种统一格式简化了后续处理流程。

如何提高POINTS-Reader的转换精度?

可以尝试提高输入图像的分辨率,确保文档清晰可辨。对于复杂布局的文档,如果遇到重复或缺失内容的问题,调整生成参数(如temperature、top_p等)也可能有帮助。

POINTS-Reader可以处理手写文档吗?

目前POINTS-Reader对手写文档的处理能力有限,因为训练数据主要使用印刷字体。团队正在努力改进这一方面的性能。

模型支持的最大上下文长度是多少?

POINTS-Reader支持的最大上下文长度为8192个token,这使其能够处理大多数单页文档。对于多页文档,建议分页处理。

9. 结语

POINTS-Reader代表了一种全新的文档转换范式,完全摒弃了传统的蒸馏训练方法,通过两阶段数据构建框架实现了高性能的端到端文档转换。该方法不仅解决了蒸馏训练固有的性能上限和误差传递问题,还提供了一种可扩展的自改进机制,能够持续提升模型性能。

通过统一的输出格式、精心设计的数据过滤策略和迭代自改进过程,POINTS-Reader在多个基准测试中取得了领先的性能,甚至超越了一些参数量更大的模型。其简洁的输入输出设计和高吞吐量特性,使其非常适合实际应用部署。

随着多语言支持和手写体识别能力的不断完善,POINTS-Reader有望成为文档数字化领域的首选工具,为学术研究、企业数字化转型和日常办公提供强大支持。