轻量级大模型 OCR 技术实践:从发票识别到复杂 PDF 文档解析
一、OCR 为什么也开始使用大模型了?
假设有一张发票,上面写着:
电子发票(普通发票)
发票号码:12345678901234567890
开票日期:2026年10月20日
商品名称 金额
办公用品 200.00
税额 12.00
价税合计:¥212.00
传统 OCR 可以把文字识别出来,但可能出现一个问题:它知道有“200.00”和“12.00”,却不一定知道哪个数字对应金额、哪个对应税额。
到了复杂 PDF,这个问题更加明显。
一页文档可能同时包含双栏正文、表格、公式、图片和脚注。简单地把识别结果按坐标拼接,可能让原本正确的内容变得难以阅读。
所以,现代文档解析要解决的其实是两个问题:
- OCR: 图片里有哪些文字?
- Document Parsing: 这些文字、表格和公式在文档中是什么结构,应该按照什么顺序阅读?
这正是视觉语言模型(Vision-Language Model,VLM)进入 OCR 领域的重要原因。
1.1 技术原理
传统 OCR 往往采用:
文档图片
│
▼
文字检测
│
▼
文字区域裁剪
│
▼
文字识别
│
▼
纯文本
而以 PaddleOCR-VL 为代表的模型,可以采用:
文档图片 / PDF
│
▼
版面检测
│
├── 标题
├── 正文
├── 表格
└── 公式
│
▼
视觉语言模型 VLM
│
▼
文字与结构恢复
│
▼
Markdown / JSON
以 PaddleOCR-VL 初代版本为例,其核心视觉语言模型只有约 0.9B 参数,由动态分辨率视觉编码器和 ERNIE 语言模型组成。
视觉编码器负责理解图片内容,语言模型负责生成对应的文字及结构表示。
但这里有个细节:0.9B 指的是核心 VLM,并不是整条文档解析流水线的总参数量。完整系统还包括版面分析等模块。
二、有哪些值得关注的轻量级 OCR 模型?
目前,比较有代表性的开源模型有:
| 模型 | 参数规模 | 特点 |
|---|---|---|
| PaddleOCR-VL | 0.9B 核心 VLM | 多语言 OCR、表格、公式及文档结构解析 |
| MinerU2.5 | 1.2B | 复杂 PDF、论文、阅读顺序与表格还原 |
| dots.ocr | 1.7B 语言模型基础 | 将版面检测与内容识别整合进 VLM |
以上是对应模型版本的规模,不代表这些项目的所有后续版本都具有相同参数量。
相关开源项目:
如果只是识别几行清晰文字,传统轻量 OCR 可能已经足够;但如果需要保留复杂文档的结构,VLM 文档解析模型通常更值得测试。
下面两个案例统一使用 PaddleOCR-VL 初代版本,方便复现。
三、实践案例一:发票 OCR 与关键信息提取
3.1 业务场景
假设公司财务每天需要处理大量发票。
我们的目标是从发票图片中获取:
- 发票号码
- 开票日期
- 价税合计金额
最终转换为 JSON,供财务系统入库。
整个过程可以分为两步:先通过模型识别文档,再通过规则提取字段。
3.2 环境准备
建议使用独立 Python 虚拟环境。先按照 PaddleOCR 官方安装指南安装与 CPU 或 CUDA 环境兼容的 PaddlePaddle 3.2.1 及以上版本,再安装文档解析组件:
python -m pip install -U "paddleocr[doc-parser]"
首次运行通常需要下载模型文件。以下代码显式使用 v1,对应 PaddleOCR-VL-0.9B 核心模型。
3.3 Python 实现
准备一张发票图片 invoice.png:
import re
import json
from pathlib import Path
from paddleocr import PaddleOCRVL
# 加载完整文档解析流水线
parser = PaddleOCRVL(pipeline_version="v1")
# 识别发票并保存结果
out = Path("output/invoice")
out.mkdir(parents=True, exist_ok=True)
for result in parser.predict(input="invoice.png"):
result.save_to_markdown(save_path=str(out))
result.save_to_json(save_path=str(out))
# 读取生成的 Markdown
text = (out / "invoice.md").read_text(
encoding="utf-8"
)
# 简单字段提取:适用于固定格式演示
def extract(pattern):
match = re.search(pattern, text)
return match.group(1) if match else None
invoice_data = {
"invoice_number": extract(
r"发票号码[::\s]*([0-9]{8,20})"
),
"date": extract(
r"开票日期[::\s]*([\d年月日./-]+)"
),
"total_amount": extract(
r"价税合计[^\d]{0,20}(\d+\.\d{2})"
)
}
print(json.dumps(
invoice_data,
ensure_ascii=False,
indent=2
))
假设发票内容如前面的示例,且识别文本符合字段匹配规则,预期输出为:
{
"invoice_number": "12345678901234567890",
"date": "2026年10月20日",
"total_amount": "212.00"
}
注意,这里展示的是预期结果,不是实际运行测试。
3.4 这个方案有什么局限?
你可能已经发现:代码中仍然使用了正则表达式。
没错,OCR 模型负责识别文档,并不意味着它已经完成了可靠的业务字段抽取。
如果发票模板发生变化,例如价税合计在表格的另一列,简单的正则表达式就可能失效。
实际生产中,更合理的架构是:
发票图片
│
▼
OCR / 文档解析
│
▼
识别文本及版面结构
│
▼
信息抽取模型或规则引擎
│
▼
字段校验
│
▼
财务系统
对于金额、税号等关键字段,还应增加格式校验、金额一致性检查和必要的人工复核。
四、实践案例二:复杂 PDF 转 Markdown,构建 AI 知识库
4.1 为什么不能直接提取 PDF 文字?
假设我们有一份几十页的技术报告:
- 正文采用双栏排版。
- 中间穿插数据表格。
- 包含数学公式。
- 部分页面来自扫描件。
如果直接使用普通 PDF 文本提取工具,很可能出现这种结果:
第一列第一行
第二列第一行
第一列第二行
第二列第二行
原本连续的两段正文被混在一起。
对于知识库 RAG 而言,这可能比完全识别不到文字更麻烦:检索系统会把错误拼接的内容当作真实语义。
因此,我们希望把 PDF 转换成尽量保留标题、正文、表格和公式结构的 Markdown。
4.2 Python 实现
PaddleOCR-VL 提供了多页结果重构功能。
from pathlib import Path
from paddleocr import PaddleOCRVL
# 初始化模型
parser = PaddleOCRVL(pipeline_version="v1")
pdf_file = "technical_report.pdf"
out = Path("output/report")
out.mkdir(parents=True, exist_ok=True)
# 逐页解析
pages = list(
parser.predict(input=pdf_file)
)
# 重构多页结构
results = parser.restructure_pages(
pages,
merge_tables=True,
relevel_titles=True,
concatenate_pages=True
)
# 保存 Markdown 和 JSON
for result in results:
result.save_to_markdown(save_path=str(out))
result.save_to_json(save_path=str(out))
print("文档解析完成")
这里三个参数比较关键:
| 参数 | 作用 |
|---|---|
merge_tables=True |
尝试合并跨页表格 |
relevel_titles=True |
尝试恢复多级标题关系 |
concatenate_pages=True |
合并多页结果 |
假设原 PDF 包含:
第一章 技术方案
1.1 模型性能
模型 准确率
模型A 92.3%
模型B 94.1%
解析后的 Markdown 可能类似:
# 第一章 技术方案
## 1.1 模型性能
| 模型 | 准确率 |
|---|---|
| 模型A | 92.3% |
| 模型B | 94.1% |
其中公式通常会尝试保留为 LaTeX,表格则可能输出为 Markdown 或 HTML 结构。
实际输出取决于原始文档质量和模型识别结果,并不能保证所有跨页表格都被正确合并。
4.3 接入 RAG 系统
生成 Markdown 后,便可以接入上一篇介绍的 Embeddings 模型:
原始 PDF
│
▼
PaddleOCR-VL
│
▼
结构化 Markdown
│
▼
文本分块 Chunking
│
▼
Embeddings
│
▼
向量数据库
│
▼
知识检索 + LLM 回答
这样就能把原本不适合直接处理的扫描 PDF 转换成 AI 可以检索的知识内容。
不过,真实项目里还要做好两件事:保留页码和原文位置,方便答案溯源;对表格、公式设置合理的分块策略,避免它们被拆散。
五、生产环境中有哪些坑?
1. 模型会把文字“认错”,也可能直接编造内容。
VLM 具备文本生成能力,但这不代表它可以随意补全文档。遇到模糊文字、印章遮挡或低分辨率图片时,必须警惕模型生成原图中不存在的内容。
2. 轻量模型不等于一定跑得快。
参数量虽然小,但高分辨率图片、版面检测、多区域裁剪以及逐页推理都会带来额外开销。
真正需要衡量的是端到端处理时间,而不只是 VLM 的模型推理速度。
3. 不要把所有 PDF 都送进 OCR。
对于可以直接提取文字、结构相对简单的电子 PDF,优先使用 PyMuPDF 等工具往往更省资源。
OCR 更适合扫描件、图片 PDF 和直接提取效果不佳的复杂页面。
4. 评估指标要看业务。
建议重点关注:
| 指标 | 评价内容 |
|---|---|
| CER | 文字字符错误率 |
| TEDS | 表格结构识别质量 |
| 字段准确率 | 发票号码、金额等字段是否正确 |
| 阅读顺序准确率 | 多栏文档是否按正确顺序还原 |
| P95 延迟 | 文档处理的耗时表现 |
对于财务票据,金额和发票号码正确可能比整页 CER 更重要;对于论文解析,表格和公式结构可能是核心。
六、总结
OCR 技术正在经历一个很有意思的变化:它不再只是把图片转成文字,而是逐渐具备了理解文档布局和恢复内容结构的能力。
通过本文两个案例,我们看到了两种典型应用:
- 发票 OCR: 将文档图片转成文字,再进一步抽取业务字段。
- PDF 文档解析: 将复杂文档还原成 Markdown,为 RAG 和知识库提供可用数据。
把它与前面介绍的 ASR、Embeddings 和决策模型放在一起,可以形成更完整的 AI 系统:
图片 / 扫描件 / PDF
│
▼
OCR 文档解析
│
▼
文本内容
│
▼
Embeddings 检索
│
▼
LLM / 决策模型
│
▼
业务处理
ASR 解决“听到了什么”,OCR 解决“文档里有什么”,Embeddings 解决“哪些内容相关”,决策模型和 LLM 则进一步完成判断与处理。
但有一点始终值得记住:
一个模型能够识别文字,不代表它能够理解所有业务含义;一个模型能够还原表格,也不代表表格里的数字就一定正确。
真正可靠的文档 AI 系统,不仅需要好的模型,还需要结构校验、业务规则和必要的人工复核。
- 点赞
- 收藏
- 关注作者
评论(0)