源码七号站 | 站长:莫潇羽 | 原创技术分享
本文由源码七号站独家原创,转载请注明出处。
写在前面
做过 RAG(检索增强生成)系统的朋友应该都有过这样的痛苦经历:明明是一份排版整齐的 PDF 文档,复制出来却变成了乱七八糟的字符;表格里的数据被拆得七零八落,根本无法还原原始结构;页眉页脚和正文混在一起,后续的文本分块简直是噩梦。
传统的 OCR 工具在处理简单文档时表现尚可,但一旦遇到复杂的表格、多栏排版、公式符号,立刻原形毕露。而调用 GPT-4o 这类商业 API 虽然效果不错,但高昂的费用让很多个人开发者和中小企业望而却步。
今天站长莫潇羽要给大家介绍的这款开源神器——LightOn OCR,正是为了终结这些文档提取的噩梦而生。它由法国 AI 公司 LightOn AI 团队开发,仅需 1B 参数、4GB 左右显存,就能在普通消费级显卡甚至笔记本电脑上流畅运行,实现媲美大模型的文档解析效果。
接下来,我会从技术原理、本地部署、实战应用三个维度,为大家详细拆解这款工具的方方面面。无论你是 AI 开发者、数据工程师,还是刚入门的技术小白,相信都能从本文中获得实用的知识。
第一章:为什么 PDF 提取这么难?
1.1 传统 OCR 的困境
在深入了解 LightOn OCR 之前,我们先来聊聊为什么从 PDF 中提取内容一直是个老大难问题。
PDF(Portable Document Format)的设计初衷是为了保证文档在不同设备上显示一致,它本质上是一种"所见即所得"的格式。但这种设计也带来了一个问题:PDF 存储的是渲染指令,而不是语义结构。
举个例子,一个看起来整齐的表格,在 PDF 内部可能是这样存储的:
- 在坐标 (100, 200) 处绘制文字 "姓名"
- 在坐标 (200, 200) 处绘制文字 "年龄"
- 在坐标 (100, 220) 处绘制文字 "张三"
- 在坐标 (200, 220) 处绘制文字 "25"
你会发现,PDF 文件里根本没有"表格"这个概念,只有一堆坐标和文字。传统的 PDF 解析工具只能按照坐标顺序读取文字,然后尝试用一些启发式规则来"猜测"表格结构。一旦表格稍微复杂一点,或者单元格有合并,解析结果就会乱成一锅粥。
1.2 扫描件和图片文档的挑战
除了原生 PDF,还有大量的扫描件和图片文档需要处理。这类文档的处理流程通常是:
- 图像预处理:去噪、二值化、倾斜校正
- 版面分析:识别文字区域、表格区域、图片区域
- 文字识别:对每个区域进行 OCR
- 结果整合:把各个区域的识别结果拼接起来
传统方案需要多个独立的模型分工合作,每个环节都可能出错,而且错误会层层累积。更麻烦的是,不同模型之间的接口适配、结果格式统一都需要大量的工程工作。
1.3 大模型时代的新思路
随着视觉语言模型(VLM)的发展,一种全新的思路出现了:把文档理解任务交给一个端到端的大模型。
像 GPT-4o、Claude 3.5 这样的多模态大模型,可以直接"看懂"一张文档图片,然后输出结构化的文本。它们不再需要复杂的预处理流程,而是像人类一样,同时理解文字内容和版面布局。
但问题是,这些商业大模型的 API 调用费用不低。如果你要处理成千上万份文档,光是 API 费用就是一笔不小的开支。而且,很多企业出于数据安全考虑,不希望把敏感文档上传到第三方服务器。
LightOn OCR 的出现,正是为了解决这个矛盾:它既能实现大模型级别的文档理解能力,又能在本地部署运行,保护数据隐私,而且资源消耗极低,普通电脑就能跑起来。
第二章:LightOn OCR 技术原理深度剖析
2.1 模型架构概览
LightOn OCR 是一个 1B 参数的视觉语言模型(VLM),它的核心设计思想是:用知识蒸馏的方式,把大模型的能力压缩到一个小模型里。
具体来说,LightOn OCR 的架构由三个主要部分组成:
第一部分:视觉编码器(Vision Encoder)
视觉编码器负责"看"文档图片,把图像信息转换成模型能理解的向量表示。LightOn OCR 采用了 Pixtral(来自 Mistral 3.1)作为视觉编码器的基础。
这个视觉编码器有几个关键特点:
- 原生分辨率处理:不需要把图片裁剪或缩放到固定大小,可以直接处理各种分辨率的输入。这对于文档 OCR 特别重要,因为文档图片通常分辨率较高,强制缩放会丢失很多细节。
- NaViT 风格处理:采用了类似 NaViT 的处理方式,不使用图像分块(tiling),而是直接处理整张图片,保持了视觉信息的完整性。
- 高效的特征提取:在保持精度的同时,尽量减少计算量,为后续的语言模型减轻负担。
第二部分:多模态投影层(Multimodality Projection Layer)
视觉编码器输出的是视觉特征向量,但语言模型需要的是类似文本 token 的输入。多模态投影层的作用就是在两者之间搭建桥梁。
LightOn OCR 在这一层做了一个关键优化:将视觉 token 下采样 4 倍。这意味着原本需要处理 1000 个视觉 token,现在只需要处理 250 个。这大大降低了语言模型的计算负担,而且实验表明对识别精度的影响微乎其微。
此外,LightOn OCR 还移除了传统 VLM 中的 image_break 和 image_end token,进一步简化了架构,减少了不必要的 token 消耗。
第三部分:语言模型解码器(Language Model Decoder)
语言模型解码器负责根据视觉特征生成文本输出。LightOn OCR 采用了 Qwen3 架构作为语言模型的基础。选择 Qwen3 有几个考量:
- Qwen3 是目前开源社区中性能最好的语言模型之一
- 它对中文有较好的支持(这对我们中文用户很重要)
- 模型结构经过了大量优化,推理效率高
2.2 知识蒸馏:小模型如何学会大模型的本领
LightOn OCR 最核心的技术创新在于其训练方法——知识蒸馏(Knowledge Distillation)。这个概念最早由 Geoffrey Hinton 等人提出,简单来说就是让一个小模型(学生)去模仿一个大模型(教师)的行为。
训练数据的生成
LightOn OCR 的训练数据是这样制作的:
- 收集大量的 PDF 文档,涵盖科学论文、书籍、收据、发票、表格、表单等各种类型
- 将 PDF 页面渲染成图片(200 DPI,最大边长 1540 像素)
- 使用 Qwen2-VL-72B-Instruct 这个 720 亿参数的大模型,对每张图片进行"标注",生成对应的 Markdown 文本
- 对生成的 Markdown 进行清洗和规范化处理
- 用这些图片-Markdown 配对数据来训练 1B 参数的小模型
这个过程的关键在于:教师模型的质量决定了学生模型的上限。
LightOn AI 团队在论文中特别指出,他们尝试过用 7B 参数的模型作为教师,但效果明显不如 72B 的模型。这说明在 OCR 这个任务上,教师模型的标注质量与模型大小正相关。虽然用大模型生成训练数据的成本较高,但这是一次性投入,训练完成后就可以用小模型高效推理了。
为什么选择 Markdown 格式?
LightOn OCR 的输出格式是 Markdown,而不是 HTML 或其他格式,这个选择也是经过深思熟虑的:
- 轻量级:相比 HTML,Markdown 的标记语法更简洁,同样的内容需要更少的 token
- 可读性好:Markdown 是人类可读的,方便检查和调试
- 易于转换:Markdown 可以轻松转换成 HTML、PDF 等其他格式
- 对模型友好:简单的语法意味着模型更容易学习,出错的概率也更低
特别值得一提的是,LightOn OCR 在 Markdown 中使用 LaTeX 语法来表示数学公式。这对于处理科技文档、学术论文非常有用。
数据清洗与规范化
即使是 72B 的大模型,生成的标注数据也不是完美的。LightOn AI 团队在论文中提到了几个常见问题:
- 生成循环:模型有时会陷入重复输出相同内容的循环
- 多余的 Markdown 代码块标记:比如不必要的 ``` 标记
- 格式不一致:有时候表格用 Markdown 格式,有时候又用 HTML 格式
为了解决这些问题,他们实现了一套完整的规范化流程,确保所有训练数据的格式统一、质量可控。
2.3 端到端架构的优势
LightOn OCR 最大的特点之一是它的 端到端设计。这意味着从输入一张图片到输出 Markdown 文本,整个过程只需要调用一次模型,没有复杂的中间步骤。
与之形成对比的是传统的 流水线方案,比如 PaddleOCR-VL、dots.ocr 等工具:
传统流水线方案:
输入图片 → 版面分析模型 → 表格检测模型 → 文字检测模型 → 文字识别模型 → 后处理 → 输出
LightOn OCR 端到端方案:
输入图片 → LightOn OCR 模型 → 输出
端到端架构有以下几个明显优势:
1. 推理速度快
只需要运行一个模型,没有多个模型之间的数据传递开销。根据官方测试数据:
- 比 dots.ocr 快 5 倍
- 比 PaddleOCR-VL-0.9B 快 2 倍
- 比 DeepSeekOCR 快 1.73 倍
在单张 H100 GPU 上,LightOn OCR 可以达到 5.71 页/秒 的处理速度,一天能处理约 49.3 万页 文档。
2. 部署简单
只需要部署一个模型,不用操心多个模型之间的版本兼容、接口适配等问题。对于追求快速落地的开发者来说,这能省去大量的工程工作。
3. 全局理解能力强
端到端模型可以同时看到整张图片,利用全局信息来理解局部内容。而流水线方案在版面分析阶段就把图片切成了若干区域,后续的识别模型只能看到局部,可能会丢失一些跨区域的上下文信息。
4. 易于微调
如果你有特定领域的文档需要处理,可以用少量标注数据对 LightOn OCR 进行微调。而流水线方案的每个环节都是独立的,微调起来会复杂很多。
2.4 性能对比:数据说话
空口无凭,我们来看看 LightOn OCR 在公开基准测试上的表现。
OlmOCR-Bench 基准测试
OlmOCR-Bench 是目前评估 OCR 模型的主流基准之一,它包含 1402 份 PDF 文档,涵盖了各种复杂的排版情况。
|
模型 |
参数量 |
得分 |
相对速度 |
|
LightOn OCR |
1B |
76.1 |
1.0× |
|
Qwen3-VL-2B |
2B |
60.1 |
0.8× |
|
DeepSeek OCR |
3B |
74.2 |
0.58× |
|
dots.ocr |
3B |
76.3 |
0.15× |
|
PaddleOCR-VL |
0.9B |
75.8 |
0.37× |
从表中可以看到:
- LightOn OCR 以 1B 参数达到了 76.1 的得分,超越了 2B 参数的 Qwen3-VL-2B 整整 16 分
- 与 3B 参数的 dots.ocr 得分相当(76.1 vs 76.3),但速度快了 5 倍以上
- 在相近参数量级(1B vs 0.9B)的比较中,LightOn OCR 也略胜 PaddleOCR-VL
成本效益分析
假设你要处理 100 万页文档,我们来算一笔账:
- 使用 LightOn OCR(本地部署):
- 硬件成本:一张消费级显卡(如 RTX 4070)约 4000 元人民币
- 处理时间:约 2-3 天(24 小时运行)
- 电费:约 30-50 元
- 总成本:一次性投入约 4000 元(显卡可重复使用)
- 使用商业 API(如 GPT-4o):
- 假设每页消耗 2000 token,单价 $0.01/1K token
- 100 万页 × 2000 token × $0.01/1K = $20,000
- 总成本:约 14 万元人民币
差距是不是很惊人?这就是本地部署开源模型的魅力所在。
第三章:本地部署实战教程
说了这么多原理,现在让我们动手把 LightOn OCR 跑起来。站长莫潇羽会尽量写得详细一些,确保小白也能顺利完成部署。
3.1 硬件要求
在开始之前,先确认一下你的硬件是否满足要求:
最低配置:
- GPU:4GB 显存以上(如 GTX 1650、RTX 3050)
- 内存:16GB RAM
- 硬盘:至少 10GB 可用空间
- 操作系统:Linux(推荐 Ubuntu 22.04/24.04)、macOS、Windows(WSL2)
推荐配置:
- GPU:8GB 显存以上(如 RTX 3070、RTX 4060)
- 内存:32GB RAM
- 硬盘:SSD,20GB 以上可用空间
如果没有 GPU:
LightOn OCR 也支持 CPU 推理,但速度会慢很多。如果你只是想体验一下,或者处理少量文档,CPU 也是可以的。对于 Apple Silicon Mac 用户,可以使用 MPS 加速。
3.2 环境准备
方案一:使用 vLLM(推荐)
vLLM 是目前最流行的 LLM 推理引擎之一,LightOn OCR 在 vLLM v0.11.1 及以上版本中已经获得官方支持。
步骤 1:创建虚拟环境
# 使用 uv(推荐,速度快)
uv venv --python 3.12 --seed
source .venv/bin/activate
# 或者使用 conda
conda create -n lightonocr python=3.12 -y
conda activate lightonocr
步骤 2:安装 vLLM
# 使用 uv 安装
uv pip install vllm>=0.11.2
# 或者使用 pip
pip install vllm>=0.11.2
步骤 3:安装额外依赖
uv pip install pypdfium2 pillow requests
# 或
pip install pypdfium2 pillow requests
步骤 4:启动 vLLM 服务
vllm serve lightonai/LightOnOCR-1B-1025 \
--limit-mm-per-prompt '{"image": 1}' \
--mm-processor-cache-gb 0 \
--no-enable-prefix-caching
首次运行时,vLLM 会自动从 Hugging Face 下载模型(约 2GB),请确保网络畅通。如果下载速度慢,可以设置 Hugging Face 镜像:
export HF_ENDPOINT=https://hf-mirror.com
服务启动后,你会看到类似这样的输出:
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
方案二:使用 Transformers
如果你更喜欢直接使用 Hugging Face Transformers,也是可以的:
步骤 1:安装依赖
pip install git+https://github.com/huggingface/transformers
pip install pillow pypdfium2 torch accelerate
步骤 2:编写推理代码
import torch
from transformers import LightOnOcrForConditionalGeneration, LightOnOcrProcessor
# 设置设备
device = "mps" if torch.backends.mps.is_available() else "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float32 if device == "mps" else torch.bfloat16
# 加载模型
model = LightOnOcrForConditionalGeneration.from_pretrained(
"lightonai/LightOnOCR-1B-1025",
torch_dtype=dtype
).to(device)
processor = LightOnOcrProcessor.from_pretrained("lightonai/LightOnOCR-1B-1025")
# 准备输入
url = "https://your-document-image-url.jpg" # 替换成你的图片 URL
conversation = [{"role": "user", "content": [{"type": "image", "url": url}]}]
inputs = processor.apply_chat_template(
conversation,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
return_tensors="pt",
)
inputs = {k: v.to(device=device, dtype=dtype) if v.is_floating_point() else v.to(device)
for k, v in inputs.items()}
# 生成输出
output_ids = model.generate(inputs, max_new_tokens=4096)
output_text = processor.batch_decode(output_ids, skip_special_tokens=True)[0]
print(output_text)
方案三:使用 llama.cpp(适合 CPU 和 Apple Silicon)
对于没有 NVIDIA GPU 的用户,llama.cpp 是一个很好的选择:
步骤 1:下载 GGUF 模型
从 Hugging Face 下载量化后的模型文件:
# 创建模型目录
mkdir -p models
# 下载模型文件(以 Q8_0 量化为例)
wget -P models/ https://huggingface.co/ggml-org/LightOnOCR-1B-1025-GGUF/resolve/main/LightOnOCR-1B-1025-Q8_0.gguf
wget -P models/ https://huggingface.co/ggml-org/LightOnOCR-1B-1025-GGUF/resolve/main/mmproj-LightOnOCR-1B-1025-Q8_0.gguf
步骤 2:启动 llama.cpp 服务
llama-server \
--host 0.0.0.0 \
--port 4183 \
-m "models/LightOnOCR-1B-1025-Q8_0.gguf" \
--mmproj "models/mmproj-LightOnOCR-1B-1025-Q8_0.gguf" \
-c 8192 \
--n_predict 8192 \
--temp 0.2 \
--top-p 0.9 \
--repeat-penalty 1.0 \
--cache-type-k q8_0 \
--threads 16 \
-ub 2048 -b 2048 \
--jinja \
-ngl -1
参数说明:
-c 8192:上下文长度--threads 16:使用 16 个 CPU 线程-ngl -1:将所有层加载到 GPU(如果有的话)
3.3 调用示例
不管你选择哪种部署方式,都可以通过 HTTP API 来调用模型。以下是一个完整的 Python 调用示例:
import base64
import requests
import pypdfium2 as pdfium
import io
from PIL import Image
# 配置
ENDPOINT = "http://localhost:8000/v1/chat/completions" # vLLM 端口
MODEL = "lightonai/LightOnOCR-1B-1025"
def pdf_page_to_base64(pdf_path: str, page_num: int = 0) -> str:
"""将 PDF 页面转换为 base64 编码的图片"""
pdf = pdfium.PdfDocument(pdf_path)
page = pdf[page_num]
# 200 DPI 渲染(scale = 200/72 ≈ 2.77)
pil_image = page.render(scale=2.77).to_pil()
# 转换为 base64
buffer = io.BytesIO()
pil_image.save(buffer, format="PNG")
image_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
return image_base64
def image_to_base64(image_path: str) -> str:
"""将图片文件转换为 base64"""
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode('utf-8')
def ocr_image(image_base64: str) -> str:
"""调用 LightOn OCR 进行识别"""
payload = {
"model": MODEL,
"messages": [{
"role": "user",
"content": [{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_base64}"}
}]
}],
"max_tokens": 4096,
"temperature": 0.2,
"top_p": 0.9,
}
response = requests.post(ENDPOINT, json=payload)
return response.json()['choices'][0]['message']['content']
# 使用示例
if __name__ == "__main__":
# 处理 PDF 文件
pdf_base64 = pdf_page_to_base64("document.pdf", page_num=0)
result = ocr_image(pdf_base64)
print("=== PDF 识别结果 ===")
print(result)
# 处理图片文件
img_base64 = image_to_base64("receipt.jpg")
result = ocr_image(img_base64)
print("\n=== 图片识别结果 ===")
print(result)
3.4 搭建 Web 演示界面
如果你想要一个图形化的操作界面,可以用 Gradio 快速搭建一个 Web 应用。站长莫潇羽为大家准备了一个简单的示例:
import gradio as gr
import requests
import base64
import io
from PIL import Image
import pypdfium2 as pdfium
ENDPOINT = "http://localhost:8000/v1/chat/completions"
MODEL = "lightonai/LightOnOCR-1B-1025"
def process_file(file):
"""处理上传的文件"""
if file is None:
return "请先上传文件"
file_path = file.name
# 判断文件类型
if file_path.lower().endswith('.pdf'):
# 处理 PDF
pdf = pdfium.PdfDocument(file_path)
page = pdf[0]
pil_image = page.render(scale=2.77).to_pil()
else:
# 处理图片
pil_image = Image.open(file_path)
# 转换为 base64
buffer = io.BytesIO()
pil_image.save(buffer, format="PNG")
image_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
# 调用 OCR
payload = {
"model": MODEL,
"messages": [{
"role": "user",
"content": [{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_base64}"}
}]
}],
"max_tokens": 4096,
"temperature": 0.2,
"top_p": 0.9,
}
try:
response = requests.post(ENDPOINT, json=payload)
result = response.json()['choices'][0]['message']['content']
return result
except Exception as e:
return f"处理出错:{str(e)}"
# 创建 Gradio 界面
with gr.Blocks(title="LightOn OCR 文档解析") as demo:
gr.Markdown("""
# 📄 LightOn OCR 文档解析工具
上传 PDF 文件或图片,自动解析为结构化的 Markdown 文本。
支持的格式:PDF、PNG、JPG、JPEG
---
""")
with gr.Row():
with gr.Column():
file_input = gr.File(
label="上传文件",
file_types=[".pdf", ".png", ".jpg", ".jpeg"]
)
submit_btn = gr.Button("开始解析", variant="primary")
with gr.Column():
output = gr.Markdown(label="解析结果")
submit_btn.click(
fn=process_file,
inputs=[file_input],
outputs=[output]
)
gr.Markdown("""
---
提示:
- PDF 文件默认只处理第一页
- 建议上传清晰的文档图片以获得最佳效果
- 处理复杂表格时,请确保表格边框清晰
技术支持:源码七号站 | 站长:莫潇羽
""")
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
保存为 app.py,然后运行:
pip install gradio
python app.py
打开浏览器访问 http://localhost:7860,就能看到一个简洁美观的 Web 界面了。
3.5 常见问题排查
问题 1:显存不足(CUDA out of memory)
解决方案:
- 使用更低精度的模型(如 BF16 → FP16 → INT8)
- 减小批处理大小
- 使用 llama.cpp 的 GGUF 量化模型
问题 2:模型下载失败
解决方案:
- 设置 Hugging Face 镜像:
export HF_ENDPOINT=https://hf-mirror.com - 手动下载模型文件到本地,然后指定本地路径
问题 3:中文识别效果不理想
LightOn OCR 的训练数据以英文为主,对中文的支持可能不如专门针对中文优化的模型。如果你主要处理中文文档,可以考虑:
- 使用 LightOn OCR 的微调版本(如果有的话)
- 结合其他中文 OCR 工具一起使用
- 自己准备中文数据进行微调
问题 4:Apple Silicon Mac 运行慢
解决方案:
- 确保使用了 MPS 加速:
device = "mps" - 使用 llama.cpp 并开启 Metal 加速
- 使用 Q8_0 或 Q4_K_M 量化模型以减少内存占用
第四章:实战应用场景
4.1 RAG 知识库构建
这是 LightOn OCR 最典型的应用场景。在构建 RAG(检索增强生成)系统时,文档解析的质量直接影响最终的问答效果。
传统流程的痛点:
- PDF 文档使用 PyPDF2 或 pdfminer 提取文本,表格变成乱码
- 扫描件需要先用 Tesseract OCR 识别,但错误率高
- 多栏排版的文档,文本顺序完全混乱
- 页眉页脚和正文混在一起,污染知识库
使用 LightOn OCR 的新流程:
import os
from pathlib import Path
import pypdfium2 as pdfium
from langchain.text_splitter import MarkdownTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
def build_knowledge_base(pdf_folder: str, output_path: str):
"""使用 LightOn OCR 构建知识库"""
documents = []
# 遍历 PDF 文件
for pdf_file in Path(pdf_folder).glob("*.pdf"):
print(f"处理文件:{pdf_file.name}")
pdf = pdfium.PdfDocument(str(pdf_file))
for page_num in range(len(pdf)):
# 渲染页面为图片
page = pdf[page_num]
pil_image = page.render(scale=2.77).to_pil()
# 调用 LightOn OCR(这里假设已经封装好了 ocr_image 函数)
markdown_text = ocr_image(pil_image)
# 添加元数据
documents.append({
"content": markdown_text,
"metadata": {
"source": pdf_file.name,
"page": page_num + 1
}
})
# 文本分块
splitter = MarkdownTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = []
for doc in documents:
splits = splitter.split_text(doc["content"])
for split in splits:
chunks.append({
"content": split,
"metadata": doc["metadata"]
})
# 向量化并存储
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
vectorstore = FAISS.from_texts(
texts=[c["content"] for c in chunks],
embedding=embeddings,
metadatas=[c["metadata"] for c in chunks]
)
vectorstore.save_local(output_path)
print(f"知识库已保存到:{output_path}")
# 使用示例
build_knowledge_base("./documents", "./knowledge_base")
效果提升:
使用 LightOn OCR 处理后的文档:
- 表格被正确识别为 Markdown 表格格式,可以被正确分块和检索
- 多栏文档的阅读顺序正确
- 页眉页脚被正确识别,可以选择性地过滤掉
- 公式被转换为 LaTeX 格式,保持了语义完整性
4.2 财务票据自动化处理
发票、收据、报销单等财务票据的处理是很多企业的日常工作。传统方式需要人工录入,效率低且容易出错。
使用 LightOn OCR 的自动化流程:
import json
import re
def extract_invoice_info(image_path: str) -> dict:
"""从发票图片中提取关键信息"""
# 调用 OCR 获取 Markdown 文本
markdown_text = ocr_image(image_to_base64(image_path))
# 定义要提取的字段
fields = {
"invoice_number": r"发票号码[::]\s*(\d+)",
"date": r"开票日期[::]\s*([\d年月日\-/]+)",
"total_amount": r"价税合计[((]大写[))][::]\s*[¥¥]?([\d,.]+)",
"seller_name": r"销售方[名称]*[::]\s*(.+)",
"buyer_name": r"购买方[名称]*[::]\s*(.+)",
}
result = {}
for field_name, pattern in fields.items():
match = re.search(pattern, markdown_text)
if match:
result[field_name] = match.group(1).strip()
else:
result[field_name] = None
# 提取表格中的商品明细(假设是 Markdown 表格格式)
table_pattern = r"\|(.+)\|"
table_rows = re.findall(table_pattern, markdown_text)
if len(table_rows) > 2: # 至少有表头和一行数据
result["items"] = []
headers = [h.strip() for h in table_rows[0].split("|")]
for row in table_rows[2:]: # 跳过表头和分隔行
values = [v.strip() for v in row.split("|")]
if len(values) == len(headers):
result["items"].append(dict(zip(headers, values)))
return result
# 使用示例
invoice_info = extract_invoice_info(