ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Unlimited-OCR-2-bf16 输出协议详解:<PAGE>/<BLOCK>/<FORK> 标签与 Markdown 转换指南

Unlimited-OCR-2-bf16 输出协议详解:<PAGE>/<BLOCK>/<FORK> 标签与 Markdown 转换指南
  • OCR
  • 计算机视觉
  • 多模态
  • 人工智能
  • 本地部署

【免费下载链接】Unlimited-OCR-2-bf16

项目地址:https://ai.gitcode.com/hf_mirrors/mlx-community/Unlimited-OCR-2-bf16
点击查看免费下载

📌 本文带你彻底看懂Unlimited-OCR-2-bf16这套 OCR 大模型的输出协议:<PAGE>、<BLOCK>、<FORK>三类标签分别承担什么职责、坐标如何归一化,以及如何把原始输出转换(Converter)成干净的 Markdown 文档。

1. Unlimited-OCR-2-bf16 是什么

Unlimited-OCR-2-bf16 是百度 Unlimited-OCR-2 视觉语言 OCR 模型的 MLX bfloat16(未量化)版本,由 mlx-vlm 转换而来。它把整页文档图像解析为带版面结构的文本,而不是简单的一行行文字。

也就是说:你给它一页 PDF 截图,它还给你"标题在哪、公式在哪、图片在哪"的结构化文档。

关键源码入口:

  • 模型定义:modeling_unlimitedocr.py
  • 视觉编码器(SAM + CLIP):deepencoder.py
  • 稀疏注意力(DASH):dash_attention.py
  • 模型配置:config.json

2. 输出协议三层结构:页 → 块 → 文本

Unlimited-OCR-2 的原始输出是一套自定义标签协议,层级如下:

层级标签职责
页级<PAGE>分隔每一页的输出,一页对应一个<PAGE>段
块级<BLOCK>声明一个版面块:类型标签 + 坐标框
块内容label[x0, y0, x1, y1]<FORK>text标签与框之后,<FORK>后接该块的实际文本

一个简化的输出示例(真实输出中还有更完整的<|ref|>包裹形式):

<PAGE> <|ref|><|det|>title[50, 40, 950, 110]<|/det|><FORK>第三章 注意力机制 <|ref|><|det|>text[60, 130, 940, 400]<|/det|><FORK>注意力机制是现代模型的核心……

2.1 块的两种写法

解析函数 re_match() 同时支持两种块写法:

  1. ref + det 双标签:<|ref|>…<|/ref|><|det|>label[x0, y0, x1, y1]<|/det|>—— 用于引用块(如图片、公式)
  2. 纯 det 标签:<|det|>label[x0, y0, x1, y1]<|/det|>—— 普通文本块

label是块的类型(如title、text、image、formula),后面的[x0, y0, x1, y1]就是包围框坐标。

2.2 坐标:0–999 归一化坐标系

这是新手最容易踩的坑:框内坐标不是像素,而是归一化到0–999的相对坐标。保存结果时会按比例还原为真实像素(见 draw_bounding_boxes()):

真实 x = x / 999 × 图片宽度 真实 y = y / 999 × 图片高度

所以在下游脚本里做坐标换算时,除以999而不是图片尺寸。

3.<PAGE>标签:输入和输出共用同一个标记

<PAGE>在这套模型里是"双角色"标记,这也是 config.json 中page_token_id: 128827的用途所在:

  • 输入侧:多页推理时,prompt 会自动展开为"<PAGE><image>" × 页数 + 指令(见 _uocr_generate 上方的 infer() 文档)。默认指令就是Multi page parsing.
  • 输出侧:模型每解析完一页就输出一个<PAGE>,下游按它切分页面。

<PAGE>还服务于稀疏注意力:page2d RoPE 和 DASH block-sparse attention 依据<PAGE>标记统计查询 token 属于哪一页,从而让"第 1 页的 token 只关注第 1 页的图",实现多页并行推理时的注意力隔离(详见 dash_attention.py)。

4. 跨页块:cross_* 与 append_* 前缀

遇到跨越页面边界的块(典型如跨页表格、长公式)时,模型会用带前缀的块标签表达延续关系:

  • cross_*:该块跨页断开了,后续页会有对应片段
  • append_*:该块是前一页块的续写

也就是说,转换 Markdown 时不能假设"一个块一定完整在某一页内",需要按前缀把前后两页的片段拼接起来。

5. 页数守卫:模型如何保证输出页数正确

_uocr_page_count_guard() 在解码每一步对 logits 做干预,保证输出协议不出错:

  1. 输出的<PAGE>数超过输入页数 → 强制生成 EOS,立即收尾
  2. 当前页超过max_page_tokens(默认 20000)token → 强制输出下一个<PAGE>或 EOS
  3. 页数还没生成够 → 禁止 EOS,必须继续

这解释了为什么你在实际使用中几乎不会遇到"半截页面"的输出。此外可选的 NoRepeatNGram(_uocr_no_repeat_ngram())可以防止长文档中重复段落。

6. 从原始输出到 Markdown:转换规则

保存结果的入口是 _uocr_save_results(),转换逻辑可以归纳为 5 步:

  1. 按<PAGE>切页:outputs.split('<PAGE>')[1:],与输入图片一一配对
  2. 正则提取块:用 re_match() 找出所有 ref/det 块
  3. 图片块裁图:label == 'image'的块按坐标裁出原图区域,存为images/page_N_idx.jpg,并把对应标签替换成 Markdown 图片语法![](images/page_N_0.jpg)
  4. 其他块画框:title等标签在原图上画出彩色检测框,输出result_with_boxes_N.jpg便于人工核对
  5. 落盘两个文件:
    • result.md:按<PAGE>\n分节的 Markdown 成品
    • result_raw.md:原始协议输出,留作调试

7. 动手实践:mlx-vlm 一行命令跑通

先在 Mac/MLX 环境安装支持该模型的 mlx-vlm 分支(见 README.md):

pip install -U "git+https://github.com/shuuul/mlx-vlm.git"

单页推理(gundam 模式:1024 全局视图 + 最多 16 个局部裁剪):

mlx_vlm.generate --model mlx-community/Unlimited-OCR-2-bf16 --image page.png \ --prompt "Multi page parsing." --max-tokens 8192 --temperature 0

多页一次请求(每页一个 1024 基础视图):

mlx_vlm.generate --model mlx-community/Unlimited-OCR-2-bf16 --image p1.png p2.png \ --prompt "Multi page parsing." --max-tokens 16384 --temperature 0

⚠️ 建议固定--temperature 0(贪心解码),--max-tokens按每页约 2000–5000 token 预留,避免截断<PAGE>段。

拿到 stdout 后,就可以对照第 6 节的规则自行解析,或调用仓库内置的_uocr_save_results得到result.md。

8. 常见坑速查

现象原因处理建议
输出里没有<PAGE>单页输入时 prompt 只有一个标记按"整段即一页"处理即可
框画歪了把 0–999 坐标当成像素按x/999×宽换算
表格缺右半跨页块被拆到下一页按cross_*/append_*前缀拼接
长文档出现复读解码重复启用no_repeat_ngram_size参数

9. 源码索引(延伸阅读)

  • 推理主流程与标签展开:modeling_unlimitedocr.py
  • 块解析正则:modeling_unlimitedocr.py
  • 坐标换算与画框:modeling_unlimitedocr.py
  • 页数守卫:modeling_unlimitedocr.py
  • Markdown 落盘:modeling_unlimitedocr.py
  • 稀疏注意力(page2d RoPE / DASH):dash_attention.py
  • 视觉塔(SAM/CLIP):deepencoder.py
  • 注意力与 token 配置:config.json

10. 小结

Unlimited-OCR-2-bf16 的输出协议本质上是一个三段式结构:

  • <PAGE>切页(输入输出共用,且驱动稀疏注意力)
  • <BLOCK>/<|det|>定位(类型标签 + 0–999 归一化坐标框)
  • <FORK>承载文本(cross_*/append_*处理跨页延续)

理解了这三层,再把 0–999 坐标换算回像素、图片块裁切内嵌,原始输出就能稳定地转成结构化 Markdown——这就是从"模型吐出的一串标签"到"可读文档"的完整链路。

  • OCR
  • 计算机视觉
  • 多模态
  • 人工智能
  • 本地部署

【免费下载链接】Unlimited-OCR-2-bf16

项目地址:https://ai.gitcode.com/hf_mirrors/mlx-community/Unlimited-OCR-2-bf16
点击查看免费下载

相关推荐

上一篇:重新定义Windows远程桌面:从限制到自由的体验革命
下一篇:XOutput:5分钟解决游戏手柄兼容性问题,让老设备焕发新生

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进