百度 Unlimited-OCR 快速上手指南#
本章基于官方源码README和infer.py脚本整理,提供三种部署方式:Transformers适合快速体验,SGLang适合高性能服务部署,vLLM适合成熟生产环境。PDF需先用PyMuPDF转图片(DPI=300),内置infer.py脚本支持一键批量推理。
1. 环境要求#
项目 |
要求 |
|---|---|
Python |
3.12.3(官方测试版本) |
CUDA |
12.9 |
GPU |
必须NVIDIA GPU(bfloat16支持) |
操作系统 |
Linux推荐(vLLM/SGLang生产环境) |
2. 图像模式说明#
Unlimited-OCR支持两种图像推理模式,针对不同场景优化:
模式 |
base_size |
image_size |
crop_mode |
ngram_window |
适用场景 |
|---|---|---|---|---|---|
gundam |
1024 |
640 |
✅ 开启(裁剪) |
128 |
单张图片高精度识别 |
base |
1024 |
1024 |
❌ 关闭 |
1024 |
多页PDF/长文档解析 |
选择原则:单张图片用gundam(裁剪后聚焦核心区域,精度更高);多页PDF或批量处理必须用base(不裁剪保证整页信息完整,长ngram_window保证跨页连贯性)。
3. 通用前置处理#
Unlimited-OCR当前不支持直接输入PDF文件,无论使用哪种推理方式,都需要先将PDF转换为图片。
3.1 PDF转图片标准代码#
import os
import tempfile
import fitz # PyMuPDF
def pdf_to_images(pdf_path, dpi=300):
"""将PDF逐页转换为PNG图片,返回图片路径列表"""
doc = fitz.open(pdf_path)
tmp_dir = tempfile.mkdtemp(prefix='pdf_ocr_')
mat = fitz.Matrix(dpi / 72, dpi / 72)
paths = []
for i, page in enumerate(doc):
out = os.path.join(tmp_dir, f'page_{i+1:04d}.png')
page.get_pixmap(matrix=mat).save(out)
paths.append(out)
doc.close()
return paths
3.2 为什么需要转图片#
模型视觉编码器DeepEncoder接收的输入是图像格式,而非原生PDF
DPI=300是平衡识别精度和处理速度的推荐值(源码默认值)
base模式下1024×1024分辨率与DeepEncoder训练时的输入规格匹配
4. Transformers方式(快速上手)#
Transformers方式是最简单的上手路径,适合快速体验模型效果、开发调试和小批量文档处理。
4.1 适用场景#
场景 |
说明 |
|---|---|
快速体验 |
第一次接触Unlimited-OCR,想马上看到效果 |
小批量处理 |
处理几份到几十份文档,不需要高并发 |
开发调试 |
集成到Python项目中,进行功能开发和调试 |
个人学习 |
学习研究模型原理,修改代码做实验 |
4.2 依赖安装#
官方测试精确版本:
pip install torch==2.10.0 torchvision==0.25.0
pip install transformers==4.57.1
pip install Pillow==12.1.1 matplotlib==3.10.8
pip install einops==0.8.2 addict==2.4.0 easydict==1.13
pip install pymupdf==1.27.2.2 psutil==7.2.2
4.3 单图推理(gundam模式)#
import torch
from transformers import AutoModel, AutoTokenizer
model_name = 'baidu/Unlimited-OCR'
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModel.from_pretrained(
model_name,
trust_remote_code=True,
use_safetensors=True,
torch_dtype=torch.bfloat16,
)
model = model.eval().cuda()
# 单图:gundam模式(image_size=640, crop_mode=True)
model.infer(
tokenizer,
prompt='<image>document parsing.',
image_file='your_image.jpg',
output_path='your/output/dir',
base_size=1024, image_size=640, crop_mode=True,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=128,
save_results=True,
)
4.4 多页PDF推理(base模式)#
# 多页/PDF:base模式(image_size=1024, crop_mode=False, ngram_window=1024)
image_paths = pdf_to_images('your_doc.pdf', dpi=300)
model.infer_multi(
tokenizer,
prompt='<image>Multi page parsing.',
image_files=image_paths,
output_path='your/output/dir',
image_size=1024,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=1024,
save_results=True,
)
5. SGLang方式(高性能服务部署)#
SGLang方式提供高性能推理服务,适合需要高吞吐、流式输出的服务化部署场景。
5.1 适用场景#
场景 |
说明 |
|---|---|
大批量文档处理 |
处理成百上千份文档,需要高吞吐量 |
服务化部署 |
作为后端HTTP服务提供OCR能力 |
高并发请求 |
同时响应多个用户的OCR请求 |
流式输出需求 |
需要实时展示识别进度的场景 |
5.2 环境准备#
官方推荐使用uv管理虚拟环境,需要安装项目自带的定制SGLang wheel:
uv venv --python 3.12
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 安装项目附带的定制SGLang wheel
uv pip install wheel/sglang-0.0.0.dev11416+g92e8bb79e-py3-none-any.whl
uv pip install kernels==0.11.7
uv pip install pymupdf==1.27.2.2 requests
wheel文件位于Unlimited-OCR项目的
wheel/目录下。
5.3 启动SGLang服务(完整参数)#
python -m sglang.launch_server \
--model baidu/Unlimited-OCR \
--served-model-name Unlimited-OCR \
--attention-backend fa3 \
--page-size 1 \
--mem-fraction-static 0.8 \
--context-length 32768 \
--enable-custom-logit-processor \
--disable-overlap-schedule \
--skip-server-warmup \
--host 0.0.0.0 \
--port 10000
关键参数说明:
--attention-backend fa3:使用FlashAttention-3后端--page-size 1:单页KV cache分配--mem-fraction-static 0.8:预分配80%显存--context-length 32768:最大上下文32768 token--enable-custom-logit-processor:启用去重logit处理器(必须)--port 10000:默认端口10000
服务启动后可通过 http://127.0.0.1:10000/health 检查健康状态。
5.4 客户端调用示例#
import base64
import json
import requests
from sglang.srt.sampling.custom_logit_processor import DeepseekOCRNoRepeatNGramLogitProcessor
server_url = "http://127.0.0.1:10000"
def encode_image(image_path):
import os
ext = os.path.splitext(image_path)[1].lower()
mime = "image/jpeg" if ext in (".jpg", ".jpeg") else f"image/{ext.lstrip('.')}"
with open(image_path, "rb") as f:
data = base64.b64encode(f.read()).decode("utf-8")
return {"type": "image_url", "image_url": {"url": f"data:{mime};base64,{data}"}}
def build_content(prompt, image_paths):
return [{"type": "text", "text": prompt}] + [encode_image(p) for p in image_paths]
def generate(prompt, image_paths, image_mode, ngram_window):
payload = {
"model": "Unlimited-OCR",
"messages": [{"role": "user", "content": build_content(prompt, image_paths)}],
"temperature": 0,
"skip_special_tokens": False,
"images_config": {"image_mode": image_mode},
"custom_logit_processor": DeepseekOCRNoRepeatNGramLogitProcessor.to_str(),
"custom_params": {"ngram_size": 35, "window_size": ngram_window},
"stream": True,
}
response = requests.post(
f"{server_url}/v1/chat/completions",
headers={"Content-Type": "application/json"},
data=json.dumps(payload), timeout=1200, stream=True,
)
for line in response.iter_lines(chunk_size=1, decode_unicode=True):
if not line or not line.startswith("data: "):
continue
data = line[len("data: "):]
if data == "[DONE]":
break
event = json.loads(data)
delta = event["choices"][0].get("delta", {}).get("content", "")
if delta:
print(delta, end="", flush=True)
# 单图(gundam模式,ngram_window=128)
generate("document parsing.", ["your_image.jpg"], image_mode="gundam", ngram_window=128)
# 多页PDF(base模式,ngram_window=1024)
generate("Multi page parsing.", pdf_to_images("your_doc.pdf", dpi=300), image_mode="base", ngram_window=1024)
6. vLLM方式(生产级部署)#
vLLM是更成熟的推理引擎,官方已提供官方支持,适合大规模生产环境。
6.1 适用场景#
场景 |
说明 |
|---|---|
大规模生产部署 |
已有vLLM基础设施的团队 |
Docker化部署 |
容器化部署、K8s编排 |
高并发服务 |
需要vLLM成熟的调度和批处理能力 |
6.2 Docker镜像#
根据GPU平台选择对应镜像:
默认(CUDA 13.0):
docker pull vllm/vllm-openai:unlimited-ocr
Hopper架构GPU(H100等,CUDA 12.9):
docker pull vllm/vllm-openai:unlimited-ocr-cu129
6.3 官方Recipe#
详细部署指南请参考官方vLLM recipe:
Recipe: https://recipes.vllm.ai/baidu/Unlimited-OCR
7. infer.py批量推理脚本#
项目内置infer.py脚本,可一键启动SGLang服务器并并发处理图片目录或PDF文件,无需手动管理服务生命周期。
7.1 功能特性#
✅ 自动启动/停止SGLang服务器(复用已有服务)
✅ 支持图片目录批量处理(递归扫描)
✅ 支持PDF文件自动转图片逐页处理
✅ 多线程并发请求(默认8并发)
✅ 失败自动重试(最多5次,502错误指数退避)
✅ 大文件优先调度(按文件大小降序,优化GPU利用率)
✅ TPS统计和性能报告
✅ 结果保存为Markdown文件
7.2 使用方式#
处理图片目录:
python infer.py \
--image_dir ./examples/images \
--output_dir ./outputs \
--concurrency 8 \
--image_mode gundam
处理PDF文件:
python infer.py \
--pdf ./examples/document.pdf \
--output_dir ./outputs \
--concurrency 8 \
--image_mode base
7.3 完整参数说明#
参数 |
默认值 |
说明 |
|---|---|---|
|
"" |
图片目录路径(与–pdf二选一) |
|
"" |
PDF文件路径(与–image_dir二选一) |
|
./outputs |
输出目录(结果保存为.md文件) |
|
8 |
并发请求数 |
|
0 |
CUDA_VISIBLE_DEVICES GPU编号 |
|
baidu/Unlimited-OCR |
模型路径或HuggingFace ID |
|
gundam |
图像模式:gundam/base |
|
./log/sglang_server.log |
SGLang服务日志路径 |
7.4 输出示例#
Mode: pdf_pages, requests=15, concurrency=8, image_mode=base
Server ready (42s)
[1] page_0001.png: 2847 tokens, 3.2s
[2] page_0002.png: 3156 tokens, 3.5s
...
============================================================
Concurrent Results:
Requests: 15/15
Total tokens: 45230
Wall time: 18.52s
System TPS: 2442.18 tokens/s
Avg tokens/request: 3015
Avg decode_time/request: 3.38s
============================================================
8. OmniDocBench评估后处理#
在OmniDocBench基准上评估时,需要对模型输出进行后处理,移除<|det|>检测标记:
import re
DET_RE = re.compile(r'<\|det\|>([^<\s]+)(?:\s*\[[^\]]*\])?\s*<\|/det\|>(.*)', re.DOTALL)
def remove_det(raw: str) -> str:
"""移除<|det|>标记,同一块内的行用\\n连接,不同块之间用\\n\\n分隔"""
blocks = []
cur = None
for line in raw.splitlines():
line = line.rstrip()
if not line:
continue
m = DET_RE.match(line)
if m:
category, content = m.group(1).strip(), m.group(2).strip()
if category == 'image':
continue
if cur is not None:
blocks.append(cur)
cur = [content] if content else []
continue
if cur is None:
cur = []
cur.append(line)
if cur is not None:
blocks.append(cur)
return '\n\n'.join('\n'.join(b) for b in blocks).strip()
9. 三种方式对比表#
对比维度 |
Transformers方式 |
SGLang方式 |
vLLM方式 |
|---|---|---|---|
定位 |
快速上手/开发调试 |
高性能服务部署 |
成熟生产级部署 |
部署复杂度 |
低,pip install后直接运行 |
中,需安装定制wheel+启动服务 |
中,Docker一键部署 |
依赖安装 |
torch+transformers+10个精确版本包 |
定制SGLang wheel+kernels+pymupdf |
Docker镜像(含全部依赖) |
API接口 |
原生Python函数调用 |
OpenAI-compatible HTTP API |
OpenAI-compatible HTTP API |
流式输出 |
需自行实现 |
原生支持 |
原生支持 |
并发处理 |
单线程/单批次 |
服务端支持高并发 |
成熟批处理调度 |
批量推理 |
需自行循环调用 |
客户端需自行实现 |
服务端批处理 |
一键批量脚本 |
❌ 无 |
✅ infer.py内置 |
❌ 需自行实现 |
生产就绪度 |
⭐ 仅开发调试 |
⭐⭐⭐ 中小规模服务 |
⭐⭐⭐⭐⭐ 大规模生产 |
部署成本 |
最低 |
中等 |
最低(Docker) |
10. 方式选择建议#
🟢 选Transformers方式如果你:#
是第一次使用Unlimited-OCR,想快速体验效果
只需要处理少量文档(几份到几十份)
在开发调试阶段,需要频繁修改代码
做个人学习研究或原型验证
不想额外安装和配置服务端组件
🔵 选SGLang方式如果你:#
需要部署为HTTP服务供内部系统调用
有中等规模批量处理需求(上百份文档)
需要使用内置infer.py一键批量推理
需要流式输出实时展示结果
团队对SGLang栈比较熟悉
🟣 选vLLM方式如果你:#
大规模生产环境部署(K8s/Docker)
已有vLLM基础设施和运维经验
需要最高并发和最成熟的调度能力
追求稳定可靠的生产级服务
💡 推荐路径#
学习验证阶段:Transformers方式快速跑通单图示例
批量处理阶段:使用infer.py(SGLang后端)一键处理目录/PDF
生产上线阶段:切换到vLLM Docker镜像部署
章节导航#
← 上一章:性能数据与基准测试