DeepEncoder ONNX fp32 (parity 1.0000000) + extras + parity fixtures + model card
Browse files- README.md +77 -0
- control_doc.png +0 -0
- deepencoder_extras.npz +3 -0
- deepencoder_fp32.onnx +3 -0
- deepencoder_ref_in.npy +3 -0
- deepencoder_ref_out.npy +3 -0
README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
base_model: baidu/Unlimited-OCR
|
| 4 |
+
tags:
|
| 5 |
+
- onnx
|
| 6 |
+
- webgpu
|
| 7 |
+
- ocr
|
| 8 |
+
- vision
|
| 9 |
+
- document-parsing
|
| 10 |
+
- onnxruntime-web
|
| 11 |
+
- browser
|
| 12 |
+
library_name: onnxruntime
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Unlimited-OCR DeepEncoder — ONNX (browser-ready vision stack)
|
| 16 |
+
|
| 17 |
+
The **complete vision encoder of [baidu/Unlimited-OCR](https://huggingface.co/baidu/Unlimited-OCR)**
|
| 18 |
+
(the DeepSeek-OCR family DeepEncoder: **SAM ViT-B → CLIP-L fusion → linear projector**) exported as a
|
| 19 |
+
single ONNX graph, verified numerically identical to the PyTorch reference
|
| 20 |
+
(**torch-vs-onnxruntime cosine 1.0000000**, maxAbsDiff 5e-5).
|
| 21 |
+
|
| 22 |
+
Paired with the language-model GGUF, this runs the full Unlimited-OCR pipeline **entirely in a
|
| 23 |
+
browser tab** — image in, det-boxed markdown out, no server. Reference implementation:
|
| 24 |
+
[NakliTechie/gemma4-webgpu](https://github.com/NakliTechie/gemma4-webgpu) (hand-written WGSL
|
| 25 |
+
WebGPU engine with DeepSeek-V2-MoE decoder support; see `ocr-demo.html`). Measured on Apple
|
| 26 |
+
Metal-3: vision 1.5 s (onnxruntime-web WebGPU EP) + decode at ~125 tok/s → **single page OCR'd
|
| 27 |
+
in < 3 s in-tab**.
|
| 28 |
+
|
| 29 |
+
## Files
|
| 30 |
+
|
| 31 |
+
| file | what |
|
| 32 |
+
|---|---|
|
| 33 |
+
| `deepencoder_fp32.onnx` | SAM→CLIP→projector, opset 18, static `[1,3,1024,1024]` → `[1,256,1280]` (fp32, 1.6 GB) |
|
| 34 |
+
| `deepencoder_extras.npz` | `image_newline`, `view_seperator` embeddings (`[1280]` f32 each) — spliced host-side, not part of the graph |
|
| 35 |
+
| `deepencoder_ref_in.npy` / `deepencoder_ref_out.npy` | parity fixtures (seed-42 input + reference output) — verify your runtime reproduces cosine ≈ 1.0 |
|
| 36 |
+
| `control_doc.png` | the ground-truth test document used in the e2e verification |
|
| 37 |
+
|
| 38 |
+
## I/O contract
|
| 39 |
+
|
| 40 |
+
- **Input** `pixel_values` `[1,3,1024,1024]` f32 — RGB, normalized `(x/255 − 0.5)/0.5` (mean/std 0.5, per the upstream processor config).
|
| 41 |
+
- **Output** `vision_embeds` `[1,256,1280]` f32 — 256 vision tokens (16×16 grid) already projected to the decoder's hidden size.
|
| 42 |
+
|
| 43 |
+
### Splicing into the decoder sequence (single 1024² global view)
|
| 44 |
+
|
| 45 |
+
```
|
| 46 |
+
[BOS(0)]
|
| 47 |
+
+ 16 rows × ( 16 patch embeds [row-major] + image_newline )
|
| 48 |
+
+ view_seperator → 273 embedding rows total
|
| 49 |
+
+ prompt token ids
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
The 273 rows replace `<image>` placeholder tokens (id 128815) — feed them as `inputs_embeds`.
|
| 53 |
+
|
| 54 |
+
### ⚠ The prompt matters more than you think
|
| 55 |
+
|
| 56 |
+
Use this model family's canonical prompt: **`<image>document parsing.`**
|
| 57 |
+
DeepSeek-OCR-v1 phrasings fail on Unlimited-OCR — `<image>\nFree OCR.` produces an **immediate EOS
|
| 58 |
+
even in the bf16 reference**, and `<|grounding|>Convert the document to markdown.` makes it recite
|
| 59 |
+
instruction boilerplate. (Verified against the full-precision HF stack; see the engine repo's
|
| 60 |
+
`reference/pytorch/hf_image_control.py`.)
|
| 61 |
+
|
| 62 |
+
## The rest of the pipeline
|
| 63 |
+
|
| 64 |
+
- **Decoder GGUF** (DeepSeek-V2 MoE, 64×550M, 12 layers — *no MLA despite the family name*:
|
| 65 |
+
`use_mla: false`, plain Llama MHA): community K-quants at
|
| 66 |
+
[sahilchachra/Unlimited-OCR-GGUF](https://huggingface.co/sahilchachra/Unlimited-OCR-GGUF)
|
| 67 |
+
(Q4_K_M 1.95 GB works with the engine's in-shader q4k/q8 storage).
|
| 68 |
+
- **Browser engine**: [NakliTechie/gemma4-webgpu](https://github.com/NakliTechie/gemma4-webgpu) —
|
| 69 |
+
WGSL kernels incl. on-GPU top-6 MoE routing and batched expert GEMVs; crossLabDiff-verified
|
| 70 |
+
against the HF bf16 reference (per-layer sweep, argmax match).
|
| 71 |
+
|
| 72 |
+
## Provenance & license
|
| 73 |
+
|
| 74 |
+
Weights are a mechanical export of [baidu/Unlimited-OCR](https://huggingface.co/baidu/Unlimited-OCR)
|
| 75 |
+
(MIT, © 2026 Baidu — notice retained per license). Export script:
|
| 76 |
+
`reference/pytorch/export_deepencoder_onnx.py` in the engine repo. fp32; an fp16 (~800 MB) pass is
|
| 77 |
+
planned — mind LayerNorm precision if you convert yourself.
|
control_doc.png
ADDED
|
deepencoder_extras.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8ad4355b1a1db528afdbd2560d628656b9fbd8fa3ec2d9a2c99b216baeda522f
|
| 3 |
+
size 10780
|
deepencoder_fp32.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6a88301420fa7f306193aef1fca2bd229c2e97382c3d6c1f468adba686c4a5a2
|
| 3 |
+
size 1604047237
|
deepencoder_ref_in.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:37b05b437b993b85c8675d24e9134e8612db2c6f6df758496d186e53cba56e83
|
| 3 |
+
size 12583040
|
deepencoder_ref_out.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f26707d3018950a9f6877e348cecd39613bb995ef74a1f41e9e5572461d2c750
|
| 3 |
+
size 1310848
|