Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
232 commits
Select commit Hold shift + click to select a range
13b0585
Add Unlimited OCR
guarin Jun 23, 2026
3d0a006
update
guarin Jun 23, 2026
16a7260
add CLIP
guarin Jun 23, 2026
ebf9b3b
add r-swa
guarin Jun 23, 2026
a531dd8
fix tests
guarin Jun 23, 2026
8cd0c32
update expected values
guarin Jun 23, 2026
83ab5d8
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 23, 2026
b6a226e
enable _can_compile_fullgraph
guarin Jun 23, 2026
e2d8d50
fix downsample outputs
guarin Jun 23, 2026
e5f2c46
use temp repo for tests
guarin Jun 23, 2026
0e47343
fix mlp_layer_types None
guarin Jun 23, 2026
a26c74a
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 23, 2026
38f3199
add partial conversion mapping
guarin Jun 23, 2026
6c42faa
handle sparse layers
guarin Jun 23, 2026
1263664
update conversion mapping
guarin Jun 23, 2026
b7c0276
update num_hidden_layers
guarin Jun 23, 2026
34abc9f
ignore lm_head
guarin Jun 23, 2026
6cf169b
update conversion mapping
guarin Jun 23, 2026
0366fc3
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 23, 2026
73281a7
draft docs
guarin Jun 23, 2026
ec0c401
Merge branch 'main' into add-unlimited-ocr
guarin Jun 23, 2026
8ecbf2c
add default config values
guarin Jun 24, 2026
96a794a
update text config handling
guarin Jun 24, 2026
d4aa878
update post init
guarin Jun 24, 2026
bffafd0
update
guarin Jun 24, 2026
16dcdbb
fix to dtype
guarin Jun 24, 2026
3bba66b
update docs
guarin Jun 24, 2026
c81df8b
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 24, 2026
ab76c3a
update MODELS_WITH_INCORRECT_HUB_TOKENIZER_CLASS
guarin Jun 24, 2026
8ed54f3
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 24, 2026
f608f97
update conversion mapping to unlimted_ocr
guarin Jun 24, 2026
a62fdc2
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 24, 2026
f346381
add num_local_patches
guarin Jun 24, 2026
b91da12
update num_local_patches handling
guarin Jun 24, 2026
4c3dc45
inline _preprocess
guarin Jun 24, 2026
0270a2f
update tests
guarin Jun 24, 2026
91e5996
update docs
guarin Jun 24, 2026
e084630
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 24, 2026
15150c8
add multi page test
guarin Jun 24, 2026
76307e9
update pad_to_square
guarin Jun 24, 2026
07782c9
update tile handling
guarin Jun 24, 2026
64ab0cd
update tile handling
guarin Jun 24, 2026
0ec1eb0
update multi page test
guarin Jun 24, 2026
0e9d3ad
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 24, 2026
5b40b2a
update docs
guarin Jun 24, 2026
975c5b2
add cache
guarin Jun 24, 2026
2d4d952
update test
guarin Jun 25, 2026
927be91
add better error message
guarin Jun 25, 2026
50f717a
add reference_sliding_attention
guarin Jun 25, 2026
390b786
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jun 25, 2026
a9eb8ae
update
guarin Jun 25, 2026
c204543
refactor
guarin Jun 25, 2026
a67620e
optimize
guarin Jun 25, 2026
34c8d1d
fix-repo
guarin Jun 25, 2026
3dffb4d
update docs
guarin Jun 25, 2026
1d9a231
update tests
guarin Jun 25, 2026
62883fc
rename to local_patches_grid
guarin Jun 25, 2026
37da184
add comment
guarin Jun 25, 2026
95c7f1e
update comment
guarin Jun 25, 2026
f37b18e
rename
guarin Jun 25, 2026
62065bc
cleanup
guarin Jun 25, 2026
bec037c
add architecture to docs
guarin Jun 25, 2026
1ea87e3
fix modular generation
guarin Jun 25, 2026
033041e
remove mask helper
guarin Jun 25, 2026
f5b37fa
add image processing tests
guarin Jun 25, 2026
7b4db92
remove redundant var
guarin Jun 25, 2026
8a2a582
Merge branch 'main' into add-unlimited-ocr
guarin Jun 25, 2026
d91e66c
Merge branch 'main' into add-unlimited-ocr
guarin Jun 26, 2026
031cfd3
fix-repo
guarin Jun 26, 2026
6b14e3d
update docstring
guarin Jun 26, 2026
d2a6e77
Merge branch 'add-unlimited-ocr' of https://github.com/guarin/transfo…
guarin Jun 26, 2026
2d0505d
add broken static layer
guarin Jun 26, 2026
f2f5cab
make static cache work
guarin Jun 26, 2026
c60d24c
test
guarin Jun 27, 2026
e21c1d9
cleanup
guarin Jun 29, 2026
6dc6d88
cleanup dynamic
guarin Jun 29, 2026
c28f1da
Merge branch 'main' into add-unlimited-ocr
guarin Jun 30, 2026
0d85b89
update
guarin Jul 1, 2026
3fddfb5
update static reference sliding window cache
guarin Jul 1, 2026
c8e1e2b
move create mask to top level
guarin Jul 1, 2026
85b2e1b
move cache to model files
guarin Jul 1, 2026
1e8df96
remove unused config attributes
guarin Jul 1, 2026
21afbad
Merge branch 'main' into add-unlimited-ocr
guarin Jul 2, 2026
817810c
cleanup
guarin Jul 2, 2026
abdea09
fix check-repo
guarin Jul 2, 2026
f699734
handle weird resize/padding
guarin Jul 2, 2026
d86f5c9
handle past_key_values is None
guarin Jul 2, 2026
183fcf4
Merge branch 'main' into add-unlimited-ocr
guarin Jul 7, 2026
5024831
update deepseek ocr2 processing
guarin Jul 7, 2026
690cd92
update date
guarin Jul 7, 2026
9b54925
use replace_image_token
guarin Jul 7, 2026
10737af
add processing tests
guarin Jul 7, 2026
23aabee
update tests
guarin Jul 7, 2026
b7f596f
clean up test
guarin Jul 7, 2026
ba1ed65
add all imports to __init__
guarin Jul 7, 2026
6b0b7d9
updaet names
guarin Jul 7, 2026
f2d05e9
typos
guarin Jul 7, 2026
7d5658f
disable flex attn
guarin Jul 7, 2026
7739c00
enable torch export tests
guarin Jul 7, 2026
68a1f7a
update no_split_modules
guarin Jul 7, 2026
3d77c49
enable skipped tests
guarin Jul 7, 2026
7ab7f5c
update conversion mapping
guarin Jul 7, 2026
81dc956
remove PretrainedConfig
guarin Jul 7, 2026
aa3f072
add replace_image_tokens tests
guarin Jul 7, 2026
3fe8f6f
remove can_return_tuple
guarin Jul 7, 2026
a729ebc
add _input_embed_layer
guarin Jul 7, 2026
d5c0e01
update tests
guarin Jul 7, 2026
fd4bb92
update docs
guarin Jul 7, 2026
6cd1668
update docs and handle image dtype
guarin Jul 7, 2026
087b1df
Merge branch 'main' into add-unlimited-ocr
guarin Jul 7, 2026
55e6f54
fix conversion mapping
guarin Jul 7, 2026
ad5cdab
fix cache
guarin Jul 8, 2026
6e37e67
update docs
guarin Jul 8, 2026
667666a
cleanup
guarin Jul 8, 2026
cb7bc6a
drop UnlimitedOcrTextModel conversion mapping
guarin Jul 8, 2026
e1cfa15
allow mixed layer types
guarin Jul 8, 2026
66a63f1
add UnlimitedOcrSlidingWindowNoRepeatNgramLogitsProcessor
guarin Jul 8, 2026
0fdbf3c
add UnlimitedOcrGenerationConfig
guarin Jul 8, 2026
17966e5
allow custom generation config
guarin Jul 8, 2026
e388923
refactor UnlimitedOcrSlidingWindowNoRepeatNgramLogitsProcessor
guarin Jul 8, 2026
301622b
refactor UnlimitedOcrSlidingWindowNoRepeatNgramLogitsProcessor
guarin Jul 8, 2026
6b1fab5
update config docstrings
guarin Jul 8, 2026
ac7e12c
cleanup UnlimitedOcrVisionEmbeddings
guarin Jul 8, 2026
08eeed4
cleanup UnlimitedOcrVisionModel
guarin Jul 8, 2026
0acc0ce
update docs and docstrings
guarin Jul 8, 2026
93b9798
update tests
guarin Jul 8, 2026
7dc2709
update init
guarin Jul 8, 2026
3c9ab38
update docs
guarin Jul 8, 2026
7519723
add generation test
guarin Jul 8, 2026
a21362f
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 8, 2026
5236059
remove getattr
guarin Jul 8, 2026
af7f77a
update tests to use revision
guarin Jul 8, 2026
0ec84b6
update tests
guarin Jul 8, 2026
95c34af
fix-repo
guarin Jul 8, 2026
27de2f0
Merge branch 'main' into add-unlimited-ocr
guarin Jul 8, 2026
f0504a3
cleanup tests
guarin Jul 9, 2026
73c808f
update get_max_length
guarin Jul 9, 2026
ca8c3a7
update date
guarin Jul 9, 2026
8e0fbc9
add cache sliding window too small test
guarin Jul 9, 2026
7e14a2b
fix get_max_length
guarin Jul 9, 2026
cc7d26e
add comments
guarin Jul 9, 2026
bac08b3
Merge branch 'add-unlimited-ocr' of https://github.com/guarin/transfo…
guarin Jul 9, 2026
5f37dfa
update comment
guarin Jul 9, 2026
faf2f10
update test
guarin Jul 10, 2026
e39e73f
Merge branch 'main' into add-unlimited-ocr
guarin Jul 10, 2026
d8accb9
add full cache test
guarin Jul 10, 2026
461a803
Merge branch 'add-unlimited-ocr' of https://github.com/guarin/transfo…
guarin Jul 10, 2026
22c38d9
add detection docs
guarin Jul 10, 2026
238bf3e
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 10, 2026
cc6edbb
fix-repo
guarin Jul 10, 2026
d0636d6
move logits processor
guarin Jul 27, 2026
f9ad01c
update test
guarin Jul 27, 2026
6ef423e
update docstring
guarin Jul 27, 2026
f690cd6
remove import
guarin Jul 27, 2026
7196f34
inherit
guarin Jul 27, 2026
a9c0772
update docs
guarin Jul 27, 2026
5a96cc1
add _prefill
guarin Jul 28, 2026
ca08ee3
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 28, 2026
4e74380
update max_new_tokens
guarin Jul 28, 2026
ccf90da
Add return_detections
guarin Jul 28, 2026
527a69d
Add return_detections
guarin Jul 28, 2026
0601965
cleanup _preprocess
guarin Jul 28, 2026
6a81897
remove total=False
guarin Jul 28, 2026
bb13eed
remane to maximum_pad_value
guarin Jul 28, 2026
c47d816
cleanup
guarin Jul 28, 2026
2093858
add chat template
guarin Jul 28, 2026
40afe9d
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 28, 2026
9581dfc
add comment
guarin Jul 28, 2026
8fe09cb
remove decorators
guarin Jul 28, 2026
203e38c
convert to int
guarin Jul 28, 2026
f0fd46e
Merge branch 'main' into add-unlimited-ocr
guarin Jul 28, 2026
5a30585
handle cache record_past
guarin Jul 28, 2026
6e31d53
cleanup validate_inputs
guarin Jul 28, 2026
7a2d9a9
update pooler_output
guarin Jul 28, 2026
36adb9f
cleanup masking
guarin Jul 28, 2026
ca024a3
Merge branch 'main' into add-unlimited-ocr
guarin Jul 28, 2026
5b6487f
flatten images early
guarin Jul 28, 2026
c8d8626
move doc to multimodal section, fix hfoption block
guarin Jul 28, 2026
977bc70
remove no-op image_newline renaming
guarin Jul 28, 2026
ea4d55a
add license header
guarin Jul 28, 2026
fa90758
fix config and image processor docstrings
guarin Jul 28, 2026
bf24d27
remove dead _input_embed_layer from vision encoder
guarin Jul 28, 2026
922231c
reuse base decode implementations and fix batch detections
guarin Jul 29, 2026
51afb7f
only check image placeholders when images are passed
guarin Jul 29, 2026
bb9341d
fix-repo
guarin Jul 29, 2026
d4f5a8f
improve mask handling
guarin Jul 29, 2026
664f30b
replace end_prefill with set_prefill_length
guarin Jul 29, 2026
3774c0e
simplify
guarin Jul 29, 2026
96d4a29
try super.update
guarin Jul 29, 2026
3fdba03
cleanup
guarin Jul 29, 2026
745a3e2
fix kwargs
guarin Jul 29, 2026
1276563
move logits processor test to test_logits_process.py
guarin Jul 29, 2026
3e1e537
don't filter text config kwargs
guarin Jul 29, 2026
94e7e40
remove use_sliding_window
guarin Jul 29, 2026
417946d
handle patches grid
guarin Jul 29, 2026
6b5f625
update expectations
guarin Jul 29, 2026
6ffde03
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 29, 2026
df08460
remove test_all_params_have_gradient
guarin Jul 29, 2026
f835baf
refactor dynamic cache
guarin Jul 30, 2026
1657694
update check
guarin Jul 30, 2026
d7a8a18
fix offset
guarin Jul 30, 2026
0eefd0c
add reorder_cache
guarin Jul 30, 2026
1eeb9ec
handle overlapping prefill/window overlap
guarin Jul 30, 2026
774d489
fix crop
guarin Jul 30, 2026
f620836
Merge branch 'add-unlimited-ocr' of hpc-cluster-hopper-login-node-1:/…
guarin Jul 30, 2026
0ad2158
update tests
guarin Jul 30, 2026
1cf342a
fix-repo
guarin Jul 30, 2026
76076d7
cleanup
guarin Jul 31, 2026
5e21344
match static cache impl with dynamic one
guarin Jul 31, 2026
2065439
add comment
guarin Jul 31, 2026
80d08e6
update test utils
guarin Jul 31, 2026
1a4109a
clarify comment
guarin Jul 31, 2026
124ddef
Merge branch 'main' into add-unlimited-ocr
guarin Jul 31, 2026
5102060
fix-repo
guarin Jul 31, 2026
f127652
Merge branch 'main' into add-unlimited-ocr
guarin Aug 5, 2026
1172fac
Merge branch 'main' into add-unlimited-ocr
guarin Aug 21, 2026
54b13d5
update
guarin Aug 21, 2026
adb0e0e
fixes
guarin Aug 21, 2026
6c0b38c
revert
guarin Aug 21, 2026
6a087ca
cleanup docstrings
guarin Aug 24, 2026
2788fbe
Merge branch 'main' into add-unlimited-ocr
guarin Aug 25, 2026
fb34ec1
fixes
guarin Aug 25, 2026
1ab76a9
remove tensor option
guarin Aug 25, 2026
f81a69d
skip export tests for now
guarin Aug 25, 2026
0680b54
Merge branch 'main' into add-unlimited-ocr
guarin Sep 3, 2026
30f2ff2
Merge branch 'main' into add-unlimited-ocr
guarin Sep 14, 2026
21f6dbf
use config default
guarin Sep 14, 2026
9a0e9a7
re anton
guarin Sep 14, 2026
c1cb494
change order
guarin Sep 15, 2026
c8cbb0d
Merge branch 'main' into add-unlimited-ocr
guarin Sep 15, 2026
67c57c6
Remove None option
guarin Sep 15, 2026
f97ada9
Merge branch 'add-unlimited-ocr' of https://github.com/guarin/transfo…
guarin Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/en/_toctree.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,8 @@
title: TVP
- local: model_doc/udop
title: UDOP
- local: model_doc/unlimited_ocr
title: UnlimitedOcr
- local: model_doc/video_llama_3
title: VideoLlama3
- local: model_doc/video_llava
Expand Down
264 changes: 264 additions & 0 deletions docs/source/en/model_doc/unlimited_ocr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
<!--Copyright 2026 the HuggingFace Team. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be rendered properly in your Markdown viewer.

-->
*This model was published in HF papers on 2026-06-23 and contributed to Hugging Face Transformers on 2026-09-14.*


# UnlimitedOcr

## Overview

The UnlimitedOcr model was proposed in [Unlimited OCR Works](https://huggingface.co/papers/2606.23050) by Youyang Yin, Huanhuan Liu, Qunyi Xie, Chaorun Liu, Shiqi Yang, Shaohua Wang, Zhanlong Liu, Hao Zou, Jinyue Chen, Shu Wei, Jingjing Wu, Mingxin Huang, Zhen Wu, Guibin Wang, Tengyu Du, and Lei Jia from Baidu Inc.

It is a single 3B parameter model with a standard context length of 32,768 tokens.

The abstract from the paper is the following:

*Recently, end-to-end OCR models, exemplified by DeepSeek OCR, have once again thrust OCR into the spotlight. A widely held view is that employing a large language model (LLM) as the decoder allows the model to leverage the prior distribution of language, leading to improved OCR performance. However, the downside is equally evident: as the output sequence lengthens, the accumulated KV cache drives up memory consumption and progressively slows down generation. This stands in stark contrast to humans, who exhibit no such decline in efficiency during long-horizon copying tasks. In this technical report, we propose Unlimited OCR, a model designed to emulate human parsing working memory. Taking DeepSeek OCR as the baseline, we replace all attention layers in the decoder with our proposed Reference Sliding Window Attention (R-SWA), which reduces attention computation costs while maintaining a constant KV cache throughout the entire decoding process. By combining the high compression rate of DeepSeek OCR's encoder with our constant KV cache design, Unlimited OCR can transcribe dozens of pages of documents in a single forward pass under a standard maximum length of 32K. More importantly, R-SWA is a general-purpose parsing attention mechanism — beyond OCR, it is equally applicable to tasks such as ASR, translation, etc. Codes and model weights are publicly available at http://github.com/baidu/Unlimited-OCR*

<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/unlimited_ocr_architecture.png" width="600">

Unlimited-OCR supports two inference configurations: the default "gundam" mode uses 640x640 tiles with dynamic cropping for high-resolution documents, and "base" mode uses a single 1024x1024 global view for standard-resolution inputs. To enable base mode set `crop_to_patches=False` in the processor, or pass it via `processor_kwargs` when using [`~ProcessorMixin.apply_chat_template`].

The vision tower follows the two-stage approach from [DeepSeek-OCR-2](./deepseek_ocr2): a SAM ViT-B encoder feeds into a CLIP ViT encoder. Unlike DeepSeek-OCR-2, the CLIP features are additionally concatenated with the SAM features to yield the final image tokens. Unlimited-OCR also omits the learnable patch queries from DeepSeek-OCR-2.

The text model is identical to DeepSeek-OCR-2 with the additional Reference Sliding Window Attention (R-SWA). R-SWA applies only to generated tokens. All image and prompt tokens remain fully visible throughout decoding, so long documents do not lose context from earlier pages.

This model was contributed by [guarin](https://huggingface.co/guarin).
The original code can be found [here](https://github.com/baidu/Unlimited-OCR).

> [!TIP]
> The original implementation runs the model with [torch.autocast](https://pytorch.org/docs/stable/amp.html#torch.autocast) in bfloat16. Wrap the forward and generate calls in an autocast context to reproduce its outputs.
>
> ```python
> with torch.autocast(device_type=model.device.type, dtype=torch.bfloat16):
> output = model.generate(**inputs)
> ```

<hfoptions id="usage">
<hfoption id="Single-page OCR">

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model = AutoModelForImageTextToText.from_pretrained("baidu/Unlimited-OCR", device_map="auto")
processor = AutoProcessor.from_pretrained("baidu/Unlimited-OCR")

image = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_suggestion_form.jpg"
messages = [
{
"role": "user",
"content": [{"type": "image", "url": image}, {"type": "text", "text": "document parsing."}],
}
]
inputs = processor.apply_chat_template(
messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt"
).to(model.device, model.dtype)

output = model.generate(**inputs, max_new_tokens=512)
processor.decode(output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True)
# image [383, 87, 497, 171]\ntext [333, 201, 558, 230]R&D QUALITY IMPROVEMENT\nSUGGESTION/SOLUTION FORM...

# All bounding boxes are in (x1, y1, x2, y2) format with coordinates normalized to [0, 999]
```

### Batch processing

For batch processing, pass a list of messages. Set `padding=True` for the processor if images have different sizes.

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model = AutoModelForImageTextToText.from_pretrained("baidu/Unlimited-OCR", device_map="auto")
processor = AutoProcessor.from_pretrained("baidu/Unlimited-OCR")

image1 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_suggestion_form.jpg"
image2 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_receipt.jpeg"
messages = [
[
{
"role": "user",
"content": [{"type": "image", "url": image}, {"type": "text", "text": "document parsing."}],
}
]
for image in [image1, image2]
]
inputs = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
return_tensors="pt",
processor_kwargs={"padding": True},
).to(model.device, model.dtype)

output = model.generate(**inputs)
processor.decode(output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True)
# image [383, 87, 497, 171]\ntext [333, 201, 558, 230]R&D QUALITY IMPROVEMENT\nSUGGESTION/SOLUTION FORM...

# All bounding boxes are in (x1, y1, x2, y2) format with coordinates normalized to [0, 999]
```

### Region detections

Set `skip_special_tokens=False` to wrap all detections and region types in `<|det|>...<|/det|>` markers. This is useful for further post-processing of the output, for example to plot the detected bounding boxes on the image. Each detection is wrapped as `<|det|>region_type [x1, y1, x2, y2]<|/det|>text...` with coordinates normalized to a `[0, 999]` range. Set `return_detections=True` to get an additional list of dictionaries with all detections parsed as `{"region_type": region_type, "box": [x1, y1, x2, y2], "text": "..."}`.

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model = AutoModelForImageTextToText.from_pretrained("baidu/Unlimited-OCR", device_map="auto")
processor = AutoProcessor.from_pretrained("baidu/Unlimited-OCR")

image = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_suggestion_form.jpg"
messages = [
{
"role": "user",
"content": [{"type": "image", "url": image}, {"type": "text", "text": "document parsing."}],
}
]
inputs = processor.apply_chat_template(
messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt"
).to(model.device, model.dtype)

output = model.generate(**inputs)
decoded, detections = processor.decode(output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=False, return_detections=True)
# <|det|>image [383, 87, 497, 171]<|/det|>\n<|det|>text [333, 201, 558, 230]<|/det|>R&D QUALITY IMPROVEMENT\nSUGGESTION/SOLUTION FORM...

# Visualization
import random
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from transformers.image_utils import load_image

image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_suggestion_form.jpg")
width, height = image.size

figure, axis = plt.subplots(figsize=(10, 12))
axis.imshow(image)
for detection in detections:
region_type = detection["region_type"]
x1, y1, x2, y2 = detection["box"]
x1, y1, x2, y2 = int(x1) / 999 * width, int(y1) / 999 * height, int(x2) / 999 * width, int(y2) / 999 * height
color = (random.random(), random.random(), random.random())
rectangle = patches.Rectangle((x1, y1), x2 - x1, y2 - y1, linewidth=1.5, edgecolor=color, facecolor="none")
axis.add_patch(rectangle)
axis.text(x1, y1, region_type, color="white", fontsize=8, backgroundcolor=color, verticalalignment="top")
axis.axis("off")
plt.show()
```

<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/unlimited_ocr_suggestion_form_boxes.jpg" width="600">

</hfoption>
<hfoption id="Multi-page OCR">

Multi-page documents can be parsed jointly in a single forward pass by passing all page images together. Add one image block per page to the message so the model processes all pages as a continuous document.

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model = AutoModelForImageTextToText.from_pretrained("baidu/Unlimited-OCR", device_map="auto")
processor = AutoProcessor.from_pretrained("baidu/Unlimited-OCR")

page1 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_suggestion_form.jpg"
page2 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/ocr_receipt.jpeg"

messages = [
{
"role": "user",
"content": [{"type": "image", "url": page} for page in [page1, page2]]
+ [{"type": "text", "text": "Multi page parsing."}],
}
]
inputs = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
return_tensors="pt",
processor_kwargs={"crop_to_patches": False},
).to(model.device, model.dtype)

output = model.generate(
**inputs,
no_repeat_ngram_window_size=1024, # default: 128, larger window size recommended for long documents
)
processor.decode(output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True)
# <PAGE>image [382, 87, 489, 174]\ntitle [333, 201, 556, 230]R&D QUALITY IMPROVEMENT\nSUGGESTION/SCLUTION FORM...

# All bounding boxes are in (x1, y1, x2, y2) format with coordinates normalized to [0, 999]
```

</hfoption>
</hfoptions>

## UnlimitedOcrConfig

[[autodoc]] UnlimitedOcrConfig

## UnlimitedOcrTextConfig

[[autodoc]] UnlimitedOcrTextConfig

## UnlimitedOcrVisionConfig

[[autodoc]] UnlimitedOcrVisionConfig

## UnlimitedOcrVisionEncoderConfig

[[autodoc]] UnlimitedOcrVisionEncoderConfig

## UnlimitedOcrSamVisionConfig

[[autodoc]] UnlimitedOcrSamVisionConfig

## UnlimitedOcrImageProcessor

[[autodoc]] UnlimitedOcrImageProcessor

## UnlimitedOcrProcessor

[[autodoc]] UnlimitedOcrProcessor

## UnlimitedOcrPreTrainedModel

[[autodoc]] UnlimitedOcrPreTrainedModel

## UnlimitedOcrTextPreTrainedModel

[[autodoc]] UnlimitedOcrTextPreTrainedModel

## UnlimitedOcrTextModel

[[autodoc]] UnlimitedOcrTextModel
- forward

## UnlimitedOcrVisionModel

[[autodoc]] UnlimitedOcrVisionModel
- forward

## UnlimitedOcrModel

[[autodoc]] UnlimitedOcrModel
- forward

## UnlimitedOcrForConditionalGeneration

[[autodoc]] UnlimitedOcrForConditionalGeneration
- forward
6 changes: 5 additions & 1 deletion src/transformers/cache_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1739,7 +1739,11 @@ def get_layer_types_and_kwargs(config: PreTrainedConfig) -> tuple[list[str], dic

# Prepare additional kwargs that may be needed to __init__ the cache layers
layer_kwargs = {}
if "sliding_attention" in layer_types or "hybrid_sliding" in layer_types:
if (
"sliding_attention" in layer_types
or "hybrid_sliding" in layer_types
or "reference_sliding_attention" in layer_types
):
layer_kwargs["sliding_window"] = config.sliding_window
if "chunked_attention" in layer_types:
layer_kwargs["sliding_window"] = config.attention_chunk_size
Expand Down
1 change: 1 addition & 0 deletions src/transformers/configuration_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"hybrid", # layers that combine attention + mamba/linear-attention-shaped states (zamba2, falcon_h1, zaya1)
"hybrid_sliding", # layers that combine sliding attention + linear-attention-shaped states (zaya1)
"deepseek_sparse_attention", # for models with DSA indexer (GLM MoE DSA, DeepSeek V32)
"reference_sliding_attention", # UnlimitedOcr: full attention over prefill + ring-buffered sliding window over generated tokens
"qwen_sparse_attention", # QSA with block-compressed indexer keys (Qwen4-Exp)
# Recurrent layers (mamba / mamba2 / GDN / minimax-lightning)
"linear_attention",
Expand Down
45 changes: 45 additions & 0 deletions src/transformers/conversion_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"Qwen2_5_VLModel": "Qwen2VLModel",
"Qwen2_5_VLForConditionalGeneration": "Qwen2VLForConditionalGeneration",
"Tipsv2VisionBackbone": "Tipsv2VisionModel",
"UnlimitedOcrTextModel": "qwen2_moe",
# ViT-style vision models (old HuggingFace checkpoint format → new modular format)
"ASTModel": "ViTModel",
"BeitModel": "ViTModel",
Expand Down Expand Up @@ -1605,6 +1606,50 @@ def _build_checkpoint_conversion_mapping():
),
WeightRenaming(r"decode_head\.conv_matting\.", r"decode_head.predictor."),
],
"unlimited_ocr": [
Comment thread
guarin marked this conversation as resolved.
WeightRenaming(r"(^|model\.)sam_model", r"\1vision_tower.sam_encoder"),
WeightRenaming(r"(^|model\.)vision_model", r"\1vision_tower.vision_encoder"),
WeightRenaming(r"(^|model\.)view_seperator", r"\1view_separator"),
WeightRenaming(r"(^|model\.)projector\.layers\.weight", r"\1multi_modal_projector.weight"),
WeightRenaming(r"(^|model\.)projector\.layers\.bias", r"\1multi_modal_projector.bias"),
WeightRenaming(r"(^|model\.)embed_tokens\.", r"\1language_model.embed_tokens."),
WeightRenaming(r"(^|model\.)layers\.", r"\1language_model.layers."),
WeightRenaming(r"(^|model\.)norm\.", r"\1language_model.norm."),
],
"UnlimitedOcrSamVisionEncoder": [
WeightRenaming(r"blocks\.(\d+)\.norm1\.", r"layers.\1.layer_norm1."),
WeightRenaming(r"blocks\.(\d+)\.norm2\.", r"layers.\1.layer_norm2."),
WeightRenaming(r"blocks\.(\d+)\.attn\.", r"layers.\1.attn."),
WeightRenaming(r"blocks\.(\d+)\.mlp\.", r"layers.\1.mlp."),
WeightRenaming(r"patch_embed\.proj\.", "patch_embed.projection."),
WeightRenaming(r"neck\.0\.", "neck.conv1."),
WeightRenaming(r"neck\.1\.", "neck.layer_norm1."),
WeightRenaming(r"neck\.2\.", "neck.conv2."),
WeightRenaming(r"neck\.3\.", "neck.layer_norm2."),
WeightRenaming(r"net_2\.", "proj.conv1."),
WeightRenaming(r"net_3\.", "proj.conv2."),
],
"UnlimitedOcrVisionEncoder": [
WeightRenaming(r"transformer", "encoder"),
WeightConverter(
source_patterns="qkv_proj.weight",
target_patterns=[
"q_proj.weight",
"k_proj.weight",
"v_proj.weight",
],
operations=[Chunk(dim=0)],
),
WeightConverter(
source_patterns="qkv_proj.bias",
target_patterns=[
"q_proj.bias",
"k_proj.bias",
"v_proj.bias",
],
operations=[Chunk(dim=0)],
),
],
"tipsv2": [
WeightRenaming("text_encoder", "text_model"),
WeightRenaming("vision_encoder", "vision_model"),
Expand Down
3 changes: 2 additions & 1 deletion src/transformers/generation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@
"image_sizes_videos",
"pixel_attention_mask",
"pixel_values_images",
"num_local_patches",
Comment thread
guarin marked this conversation as resolved.
"pixel_values_local",
"patches_grid",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

potentially different PR (to first cover the deepseek model) or is it only now with unlimited ocr?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

patches_grid is unlimited ocr only, pixel_values_local is also in deepseek and step3p7 but in both forwards it is only used within if pixel_values is not None: and pixel_values is dropped so it was effectively ignored.

)


Expand Down
1 change: 1 addition & 0 deletions src/transformers/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@
from .unispeech import *
from .unispeech_sat import *
from .univnet import *
from .unlimited_ocr import *
from .upernet import *
from .uvdoc import *
from .vaultgemma import *
Expand Down
Loading
Loading