- 人工智能
- 计算机视觉
- OCR
- 多模态
- 大模型
【免费下载链接】Unlimited-OCR-2
Unlimited-OCR-2 是百度推出的 OCR-3.0 时代超长文档解析模型,它的语言骨干采用了基于 DeepSeek-V2 的12 层 64 专家 MoE 架构,并搭配独创的page2d 双轴位置编码与块级稀疏注意力(SR-SWA),让"每解码一步的成本几乎不随文档页数增长"成为可能。本文将带你从配置参数到源码实现,完整拆解这套架构的设计思路。🔍
一、项目速览:它到底是什么?
先快速认识一下 Unlimited-OCR-2 的能力边界(详见 README.md):
- 定位:从"长文档"走向"无限页"的解析模型,支持把整本书、上百页 PDF 一次性丢进去解析;
- 关键机制 SR-SWA(Sparse Reference Sliding Window Attention):把文本-视觉的注意力交互压缩到固定大小的"工作参考集"(例如 512 个 token),使解码延迟和内存占用基本恒定;
- 双推理入口:
infer(单页,默认 gundam 动态切块)与infer_multi(多页,base 全局视图),实现在 modeling_unlimitedocr.py 中。
整个仓库的核心文件分工如下,建议先建立这个地图:
| 文件 | 角色 |
|---|---|
| config.json | 全量超参:MoE、注意力、page2d、稀疏注意力配置都在这里 |
| configuration_deepseek_v2.py | DeepseekV2Config配置类,定义所有 MoE 参数 |
| _sparse_base_impl.py | 基础实现:MoE、注意力、Lightning Indexer、page2d RoPE |
| modeling_deepseekv2.py | DASH 可微稀疏路由的"薄补丁层" |
| dash_attention.py | entmax 软选择路由器,训练阶段可微分 |
| sparse_gather_triton.py / sparse_gather_e2e_triton.py | Triton 块级稀疏注意力内核 |
| deepencoder.py | 视觉编码器(deeplip_b_l,CLIP-L 底座,1024 输入) |
二、64 专家 MoE:专家阵容一览
Unlimited-OCR-2 的语言模型是典型的DeepSeek-V2 风格混合专家(MoE):每个 token 只激活一小部分专家,用"稀疏计算"换取"参数容量"。打开 config.json,关键参数一目了然:
| 参数 | 值 | 含义 |
|---|---|---|
n_routed_experts | 64 | 每层 64 个可路由专家 |
n_shared_experts | 2 | 每层 2 个共享专家(每个 token 都参与) |
num_experts_per_tok | 6 | 每个 token 从 64 个专家中贪心选 6 个 |
moe_intermediate_size | 896 | 单个专家的 FFN 中间维度 |
intermediate_size | 6848 | 稠密层 FFN 维度(对比用) |
first_k_dense_replace | 1 | 第 1 层用稠密 FFN,其后 11 层全是 MoE |
moe_layer_freq | 1 | 每层都是专家层,无间隔 |
topk_method | greedy | 直接取打分最高的 6 个专家 |
scoring_func | softmax | 门控权重经 softmax 归一化 |
aux_loss_alpha | 0.001 | 负载均衡辅助损失权重 |
也就是说,模型共12 层(num_hidden_layers: 12),其中 11 层是"64 选 6"的 MoE 层,1 层是稠密层。🎯
路由专家 + 共享专家如何协作?
MoE 前向逻辑在 DeepseekV2MoE 中,可以概括为三步:
- 门控打分:
MoEGate(_sparse_base_impl.py#L522)对每个 token 的隐状态打分,softmax 归一化后贪心取 Top-6 专家; - 专家计算:被选中的 6 个专家各自做 MLP 变换,输出按门控权重加权求和。推理时走
moe_infer的"排序-分组-批量"策略,把发给同一专家的 token 聚合后一次性算完,避免 64 次小矩阵乘; - 共享专家兜底:2 个共享专家(合并为一个中间维 896×2=1792 的大 MLP)对所有token 无条件生效,输出与路由结果相加。
这种"少数专家负责个性、共享专家负责共性"的结构,是 DeepSeek-V2 的招牌设计,既保留了 MoE 的扩展性,又避免了纯路由专家"专家间知识割裂"的问题。训练时还会叠加aux_loss_alpha=0.001的负载均衡损失,防止个别专家被过度选中。
算一笔参数账
以单层为例:64 个路由专家 × 3 个矩阵 × (1280×896) ≈0.22B参数,而单个 token 每步只激活 6/64 ≈ 9.4% 的专家 FFN。这正是 MoE 的精髓——总参数大、单步计算小,让模型"记得住"上百页文档里五花八门的版式模式,却不需要为每页内容付出全部算力。💰
三、为什么选 DeepSeek-V2 作语言骨干?
Unlimited-OCR-2 没有照搬完整版 DeepSeek-V2,而是裁出了一个"瘦身版",配置类见 DeepseekV2Config:
- 12 层、隐藏维 1280、10 个注意力头:比 DeepSeek-V2 原版(61 层、7168 维)小一个数量级,但保留了其架构精髓——MoE + 块稀疏注意力 + YARN 长上下文;
- 上下文长度 131072:通过
rope_scaling(YARN,factor=4,original_max_position_embeddings: 32768,rope_theta: 500000)从 32K 外推到 128K。上百页文档 + 解析文本全部塞进一个窗口,是"无限页"能力的基础; - 词表 129280:为视觉 token 预留了充足空间,其中
<image>的 token id 为 128815、<PAGE>页标记为 128827(见 config.json 的sparse_attention_config); - 注意力实现:
use_mla: false,采用普通多头注意力 + KV 缓存,注意力层类为 SlidingWindowLlamaAttention,它内嵌了一个Lightning Indexer(DeepseekV2Indexer),这正是下一节稀疏注意力的"导航员"。
💡 一个值得注意的细节:
num_key_value_heads(10)等于num_attention_heads(10),所以这里用的是标准 MHA 而非 GQA——在 1280 的小隐藏维下,KV 压缩收益有限,反而保留全头注意力更简单直接。
四、page2d 位置编码:让"第几页"拥有独立坐标轴
这是 Unlimited-OCR-2 最有原创性的部分。先说 1D 位置编码为什么不行 👇
1D RoPE 的困境
普通 RoPE 只有一个"序号"轴。但文档解析有一个特殊结构:第 k 页的解析文本,总是排在该页图像 token 之后很远的地方——中间隔着后续所有页的图像。页数越多,"文本回看本页图像"的距离就越长,而且这个距离随文档增长而线性变大。单轴 RoPE 不得不用自己频谱的最远端去分辨"跨千 token 的页内关系",长文档下精度崩塌。
源码里的注释把这个痛点说得非常直白(DeepseekV2IndexerRotary2D 的类文档):
"the response text of page k sits thousands of tokens after page k's image tokens, and that gap GROWS with the page count"
双轴拆分:(token 轴, 页轴)
page2d 的做法是把 128 维 RoPE 的频率对按对(frequency pair)切给两个轴:
| 轴 | 频率对 | base (theta) | 作用 |
|---|---|---|---|
| token 轴 | 56 对 | sparse_rope_tok_theta=10000 | 编码"页内偏移",页内距离只有几百,与总页数无关 |
| page 轴 | 1 对 | sparse_rope_page_theta=256 | 专门编码"第几页" |
关键参数(config.json):
sparse_rope_mode: "page2d"与sparse_main_rope_mode: "page2d":主分支注意力和稀疏索引器共用同一套 2D 坐标系;sparse_rope_page_pairs: 1:page 轴只占 1 个频率对(2 维);sparse_rope_page_mod: 2:页坐标取page % 2,把页号折叠成 0/1 的奇偶标记——page 轴不再线性编码"第几页",而是表达"同一页 / 相邻(不同)页"的语义,避免上百页后频率回卷;sparse_rope_tok_freq_mode: "resample":token 轴在降维后重新采样整个频谱,保证高频和低频分量都被保留。
实现核心是 DeepseekV2IndexerRotary2D.forward:分别计算角度 = 页内序号 × inv_tok和页号 × inv_page,拼接成cat(tok, page)再cat(ang, ang)成 cos/sin。坐标构建逻辑在 _build_page_rope_pos:扫描<PAGE>标记的累计计数来定位每一页,tok_pos是页内运行计数(而非全局下标减段起点),page_pos保证第 k 页的图像 token 与第 k 页的解析文本共享同一个页号。
解码时如何增量推进?
解码是逐 token 的,page 轴坐标不能每步重算。_main_rope_coords 里有个精巧的状态机:KV cache 上挂着每层的{page, tok}状态,每生成一个 token——若是<PAGE>标记就page+1且 token 坐标跳回该页 prefill 段起点,否则tok+1。整套机制与 prefill 共享同一坐标系(KV cache 里存的是已旋转过角度的 K),保证生成过程中位置语义无缝延续。⚙️
五、SR-SWA:块级稀疏注意力如何落地
page2d 解决了"坐标系"问题,真正省算力的是块级稀疏注意力:
- 分块:Key 序列按
sparse_block_size: 32切成块; - 打分:每个注意力层内置一个 1 头 × 128 维的轻量 Indexer,用 page2d 坐标打分,算出每个 query 对各 block 的分数(块内取 max);
- 选择:每个 query 保留
sparse_topk_blocks: 16个块,其中sparse_local_block: 4个本地块(即 4×32=128 token 的本地窗口,对应sliding_window_size: 128),其余 12 个是"远端参考块"(dash_topk_blocks: 12); - 计算:只对被选中的块做注意力,由 triton_gather_attention 这类 Triton 内核完成,避免物化整块 [S×S] 注意力矩阵。
这样,无论文档多长,每个 query 的注意力读集恒定在 16 块 × 32 token = 512 token——这正是 README 中"fixed-size set of working references (e.g., 512 tokens)"的由来,也是解码延迟不随页数增长的根本原因。
更妙的是页感知候选约束(image_bucket_constraint: true):候选域不是"所有块",而是"本页的图像块 + 本地窗口 + 全局兜底"(见 _build_page_aware_ids),第 k 页的文本天然优先读第 k 页的图像,跨页串扰被结构性屏蔽。
训练阶段则换成可微的DASH 路由(dash_attention.py):用 entmax15 软选择 + log(先验) 偏置,让路由权重直接从语言模型损失里获得梯度,无需 KL 教师监督;推理时切回硬 Top-K(configure_dash_inference),与 vLLM 插件行为对齐。
六、核心结论清单
- ✅64 路由 + 2 共享专家、6 选 1:11/12 层均为 MoE,总参数大、单步激活小,
greedyTop-6 + softmax 门控,配 0.001 负载均衡损失; - ✅DeepSeek-V2 瘦身骨干:12 层 / 1280 维 / 128K 上下文(YARN 4 倍外推),保留 MoE + Indexer + 稀疏注意力的架构骨架;
- ✅page2d 双轴 RoPE:token 轴(theta=10000,页内偏移)+ page 轴(theta=256,page_mod=2 奇偶标记),彻底解耦"页内距离"与"总页数";
- ✅SR-SWA 恒定读集:32 token 块粒度、Top-16 块(=512 token)+ 128 本地窗口,解码成本与文档长度脱钩;
- ✅页感知隔离:候选域限制在本页图像块内,从结构上防止跨页内容互相污染。
想动手验证的话,直接阅读 config.json 对照本文表格逐项核对,再顺着 modeling_deepseekv2.py 的注释追进 _sparse_base_impl.py 的DeepseekV2MoE与DeepseekV2IndexerRotary2D,就能亲手跑通这条从 MoE 到 page2d 的完整链路。🚀
- 人工智能
- 计算机视觉
- OCR
- 多模态
- 大模型
【免费下载链接】Unlimited-OCR-2
相关推荐
page2d RoPE 详解:Unlimited-OCR-2-8bit 用 2D 页内坐标重构位置编码的巧思
page2d RoPE 详解:Unlimited OCR 2 8bit 用 2D 页内坐标重构位置编码的巧思 📄 Unlimited OCR 2 8bit 是
人工智能大模型多模态OCR计算机视觉模型量化本地部署读懂Unlimited-OCR-2-6bit的page2d RoPE:二维页面位置编码如何让模型跨页不迷路
读懂Unlimited OCR 2 6bit的page2d RoPE:二维页面位置编码如何让模型跨页不迷路 Unlimited OCR 2 6bit 是基于 M
人工智能多模态计算机视觉OCR模型量化本地部署拆解Unlimited-OCR-2-6bit的内在:DeepSeek MoE语言模型+SAM/CLIP双视觉塔架构全景指南
拆解Unlimited OCR 2 6bit的内在:DeepSeek MoE语言模型+SAM/CLIP双视觉塔架构全景指南 Unlimited OCR 2 6b
人工智能多模态计算机视觉OCR模型量化本地部署
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考