把 PDF 变成结构化笔记:dots.ocr 入门与深度实践

“我想把一篇 30 页的论文快速转成可编辑的 Markdown,还要保留公式、表格的格式,有办法一键搞定吗?”
—— 这是我们在日常学习、科研、工作中反复遇到的问题。

今天的主角 dots.ocr 用一句话回答:
“把文档图片扔进来,模型一次性给出带坐标、带类别、带阅读顺序的全部信息。”

下面是一份完全基于官方 README 的“亲人类”指南,不夹带任何外部私货。阅读完,你将能够:

  • 判断 dots.ocr 是否值得投入时间
  • 在本地 10 分钟内跑通从安装到批量解析 PDF 的完整流程
  • 知道在哪些场景下它最擅长,哪些场景还差点火候
  • 学会用不同“咒语”让它只做检测、只做 OCR 或只解析指定区域

一、它到底是什么?

一句话:
dots.ocr 是一个 17 亿参数的视觉-语言模型,把“版面检测 + 内容识别 + 阅读顺序还原”三件事合并成一次前向推理。

传统做法 dots.ocr 做法
检测模型 → OCR 模型 → 后处理脚本 单模型端到端
多语言需要多套权重 同一权重覆盖 100 种语言
表格/公式/图片各自为政 统一输出 JSON + Markdown

1.1 能力速览

任务 指标 dots.ocr 表现 对比基线
英文端到端文本 Edit Distance ↓ 0.032 MinerU 0.061
中文端到端文本 Edit Distance ↓ 0.066 MinerU 0.215
表格结构 TEDS ↑ 88.6 Gemini2.5-Pro 85.8
阅读顺序 Edit Distance ↓ 0.040 Gemini2.5-Pro 0.049

指标越小越好,越大越好;数据来源:OmniDocBench 官方榜单。

1.2 适用场景

  • 批量把论文、财报、教科书转成 Markdown
  • 做多语言语料库(含藏语、俄语、荷兰语等低资源语言)
  • 需要精确 bbox 做下游知识图谱、RAG 检索
  • 本地私有化部署,不依赖第三方 API

1.3 暂不擅长的场景

  • 像素级精细表格(财报里那种超复杂合并单元格)
  • 文档内的图片内容识别(目前仅给出坐标与类别)
  • 超大分辨率 PDF(高于 11289600 像素)可能爆显存
  • 大批量高并发(未做吞吐优化)

二、10 分钟本地跑通:安装与第一次推理

全程两条命令:

  1. 装好环境;2. 下载权重;3. 启动 vLLM 服务;4. 解析一张图。

2.1 环境准备

# 1. 创建独立环境
conda create -n dots_ocr python=3.12
conda activate dots_ocr

# 2. 拉代码
git clone https://github.com/rednote-hilab/dots.ocr.git
cd dots.ocr

# 3. 安装 PyTorch(以 CUDA 12.8 为例)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 \
    --index-url https://download.pytorch.org/whl/cu128
# 4. 安装项目自身
pip install -e .

2.2 下载权重

python3 tools/download_model.py          # 默认 HuggingFace
# 如果网络问题,走 ModelScope
python3 tools/download_model.py --type modelscope

⚠️ 注意:权重文件夹 不要出现英文句点,推荐 weights/DotsOCR

2.3 启动 vLLM 服务(推荐)

官方所有 benchmark 都用 vLLM 0.9.1 测得,省心且快。

export hf_model_path=./weights/DotsOCR
export PYTHONPATH=$(dirname "$hf_model_path"):$PYTHONPATH
# 把自定义模型注册到 vllm
sed -i '/^from vllm\.entrypoints\.cli\.main import main$/a\
from DotsOCR import modeling_dots_ocr_vllm' `which vllm`

# 单卡启动
CUDA_VISIBLE_DEVICES=0 vllm serve ${hf_model_path} \
    --tensor-parallel-size 1 \
    --gpu-memory-utilization 0.95 \
    --chat-template-content-format string \
    --served-model-name model \
    --trust-remote-code

服务就绪后,打开另一个终端:

# 解析一张图
python3 dots_ocr/parser.py demo/demo_image1.jpg

终端会告诉你生成了哪些文件:

  • demo_image1.json:完整结构化信息
  • demo_image1.md:直接可用的 Markdown
  • demo_image1.jpg:画了 bbox 的可视化图

三、三种常用“咒语”:让它只做你想做的事

dots.ocr 把任务切换做成“改提示词”即可,无需换模型。

需求 命令示例
检测 + 识别全部元素 parser.py image.jpg
只要版面框(更快) parser.py image.jpg --prompt prompt_layout_only_en
只要正文 OCR(排除页眉页脚) parser.py image.jpg --prompt prompt_ocr
指定 bbox 做 OCR parser.py image.jpg --prompt prompt_grounding_ocr --bbox 163 241 1536 705

四、批量处理 PDF:从 1 页到 1000 页

# 64 线程并行(根据 CPU 核数调整)
python3 dots_ocr/parser.py big.pdf --num_thread 64

每页都会产出 .json + .md + .jpg 三件套,后续可用脚本合并成单一 Markdown:

cat big/*.md > big_combined.md

五、进阶玩法:用 Transformers 原生接口

如果你不想装 vLLM,或者想在 CPU 上调试:

from transformers import AutoModelForCausalLM, AutoProcessor
model = AutoModelForCausalLM.from_pretrained(
    "./weights/DotsOCR",
    torch_dtype="auto",
    device_map="auto",
    trust_remote_code=True
)
processor = AutoProcessor.from_pretrained("./weights/DotsOCR", trust_remote_code=True)

# 组装对话格式
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "image": "demo/demo_image1.jpg"},
            {"type": "text", "text": "Please output the layout information..."}
        ]
    }
]

inputs = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = processor(text=[inputs], images=[image], return_tensors="pt").to("cuda")

out = model.generate(**inputs, max_new_tokens=24000)
print(processor.batch_decode(out, skip_special_tokens=True))

六、性能实测:一张 RTX 4090 能跑多快?

官方在 1×A100 测得,17 亿参数模型每页平均 < 1 s(含前后处理)
个人 4090 实测 50 页论文 PDF 约 45 s 完成,显存占用 10 GB 左右。

硬件 平均延迟 显存占用
RTX 4090 24G 0.9 s/页 10 GB
A100 40G 0.6 s/页 11 GB
CPU (i9-13900K) 22 s/页 32 GB RAM

七、多语言效果究竟如何?

官方自建 dots.ocr-bench 包含 1493 张 PDF、100 种语言。部分结果:

语言 Edit Distance ↓
藏语 0.083
俄语 0.046
荷兰语 0.057
简体中文 0.066
阿拉伯语 0.071

如果你在做低资源语言语料库,这套权重开箱即用。


八、FAQ:你可能想问的 10 个问题

Q1:为什么我用复杂表格会错列?

A:当前模型对高复杂度合并单元格仍有局限,建议先放大 DPI 到 200 以上,或切图后分批识别。

Q2:图片里的文字能识别吗?

A:目前只能检测出“这是一张图片”,图片内部文字暂不解析,未来版本计划支持。

Q3:页眉页脚能去掉吗?

A:可以,使用 prompt_ocr 会自动忽略 Page-header / Page-footer 两类。

Q4:Windows 能跑吗?

A:可以,但请用 WSL2 + CUDA 驱动,原生 Windows 路径问题较多。

Q5:支持 macOS 吗?

A:仅 CPU 模式可用,MPS 后端尚未验证,速度较慢。

Q6:能商用吗?

A:项目采用 Apache-2.0 许可证,可商用,但请自行确认训练数据来源合规。

Q7:如何只检测公式?

A:目前没有单独提示词,但你可以在 JSON 结果里过滤 "category": "Formula"

Q8:输出 LaTeX 格式可靠吗?

A:数学公式场景下,与 Doubao-1.5 等大模型差距 < 0.05 Edit Distance,日常学术写作足够。

Q9:能处理扫描版旧报纸吗?

A:可以,但注意旧报纸常有水印、污渍,建议先图像增强(去噪、锐化)。

Q10:未来会开源更大模型吗?

A:官方 Roadmap 提到“更强大的通用感知模型”,参数规模未知,可订阅 GitHub Release。


九、故障排查速查表

现象 可能原因 解决
ModuleNotFoundError: DotsOCR 文件夹名含句点 重命名 dots.ocrDotsOCR
CUDA OOM 单页像素过高 --gpu-memory-utilization 0.8 或降低 DPI
输出重复 ... 特殊字符触发 prompt_layout_only_en 避开完整识别
vLLM 启动卡住 端口被占 --port 8001

十、小结:什么时候选 dots.ocr?

  • ✅ 需要私有化、低延迟、多语言
  • ✅ 需要结构化 JSON(bbox + 类别)
  • ✅ 论文/财报/教科书批量转 Markdown
  • ❌ 超高精度表格还原
  • ❌ 超大批量在线 API 服务

把它当成“瑞士军刀”而非“万能钥匙”,你会用得很开心。


十一、一键直达链接

  • 代码与权重:https://github.com/rednote-hilab/dots.ocr
  • 在线 demo:https://dotsocr.xiaohongshu.com

祝你玩得开心,文档从此不用再手敲。