alt.freeweights.ocr / Unlimited-OCR-2
From: baidu <huggingface.co/baidu>Newsgroups: alt.freeweights.ocrSubject:

Unlimited-OCR-2

Date: 2026-11-14Commit: 0480966Signed: 2DC28CC7B26A283B ✓

Image text to text model with 3.3B parameters. Safetensors weights, 6.87 GB in all. Published by baidu under MIT.

3.3B params6.87GBUnlimited-OCR-2safetensorspermissive
FactsParams3.3BSize6.87 GBFormatssafetensorsTaskimage text to textLicenseMITFrom sourcepermissive
$ fw get baidu/Unlimited-OCR-2
# manifest sha256 ca5d500cac2d… · 6.87 GB · 26 files
$ fw verify ./Unlimited-OCR-2 baidu/Unlimited-OCR-2
From sourceHosted (signed)baidu/Unlimited-OCR-2Last check: 2026-11-14 06:34 UTC

Get help: custom fine-tune or private deploy. We review your setup before we quote.

Works with

Overview

Size
6.87 GB
Weights
6.69 GB (safetensors)
Parameters
3.3B
Formats
safetensors
Task
image text to text
License
MIT (permissive)
Files
26, each with a sha256
Publisher
baidu
Added
2026-11-14
Section
alt.freeweights.ocr
Lineage

Original release from the publisher.

Where these bytes come from
Publisher at the pinned commit→You

Sources are tried in order. A file counts only when its size and sha256 match the manifest. Sources are checked when you ask for them, not on a timer.

Sources
BadgeHostLast checkResult
From sourcehuggingface.co2026-11-14 06:34 UTCpassed

Model card

From the publisher at commit 0480966. Shown as plain text with links; images open at the publisher.

Image: Baidu Inc.


Unlimited OCR Works 2#

GitHub Hugging Face

arXiv Twitter Follow

Pioneering the OCR-3.0 Era: From Long- to Unlimited-Horizon Parsing.#

Image: Unlimited OCR 2 overview

Release#

  • [2026/11/02] 📄 The paper of Unlimited OCR 2 is now available on arXiv.
  • [2026/10/27] 📊 We release MarathonDocBench, a new benchmark for ultra-long document parsing.
  • [2026/10/27] 🤝 Thanks to the ModelScope community for their support. Our model is now available at ModelScope.
  • [2026/10/27] 🤝 Thanks to the Baidu Cloud team for their support. Our model is now available on Baidu Cloud.
  • [2026/10/27] 🤝 Thanks to AK for creating a new demo for us. Try it at Unlimited-OCR-2.
  • [2026/10/27] 🚀 We release Unlimited OCR 2, achieving unlimited-horizon parsing with SR-SWA.
  • [2026/07/21] 🤝 Thanks to the ms-swift community for their support, our model now supports training with ms-swift.
  • [2026/07/03] 🤝 Thanks to the Baidu Cloud team for their support. Our model is now available on Baidu Cloud.
  • [2026/06/28] 🤝 Thanks to the vLLM community and Tianyu Guo for their support, our model now supports vLLM inference.
  • [2026/06/24] 🤝 Thanks to AK for creating a demo for us. It is now available at Hugging Face Spaces.
  • [2026/06/23] 📄 Our paper is now available on arXiv.
  • [2026/06/23] 🤝 Thanks to the ModelScope community for their support. Our model is now available at ModelScope.
  • [2026/06/22] 🚀 We present Unlimited-OCR, aiming to push Deepseek-OCR one step further.

What's New in 2#

  • Sparse Reference Sliding Window Attention (SR-SWA): Compresses text-visual attention interactions from ultra-long sequences down to a fixed-size set of working references (e.g., 512 tokens). This bounds computational complexity, keeping per-step decoding latency and memory footprint nearly constant regardless of document length.
  • From Long- to Unlimited-Horizon Parsing: Powered by SR-SWA, Unlimited-OCR 2 achieves true, unbounded document parsing within a finite context window—effectively eliminating quadratic attention scaling and memory bottlenecks as documents grow.
  • Ultra-Long Document Parsing SOTA: Achieves state-of-the-art performance across both dozens-of-pages benchmarks (e.g., MPDocBench) and extreme hundred-page benchmarks (e.g., MarathonDocBench).

Image: Unlimited OCR 2 Performance

Inference#

Unlimited OCR 2 supports Transformers (native, for quick tests) and SGLang (recommended for serving).

Transformers#

Tested with Python 3.10, torch==2.13.0, transformers==4.52.1, huggingface-hub==0.36.0, tokenizers==0.21.4, on an NVIDIA A800-80GB:

pip install torch==2.13.0 torchvision pillow transformers==4.52.1 huggingface-hub==0.36.0 \
  tokenizers==0.21.4 addict==2.4.0 einops==0.8.2 easydict==1.13

Load the model once:

import torch
from transformers import AutoModel, AutoTokenizer

model_name = "baidu/Unlimited-OCR-2"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModel.from_pretrained(model_name, trust_remote_code=True, use_safetensors=True,
                                  torch_dtype=torch.bfloat16).eval().cuda()

Multi-page inference (infer_multi). All pages of a document are parsed in one request, so the model can use cross-page context. Pass the page images in page order:

pages = [f"your_doc/page_{i}.jpg" for i in range(1, 8)]

text, num_tokens = model.infer_multi(tokenizer, image_files=pages,
                                     output_path="output/multi", save_results=True)

The prompt is built automatically as "<PAGE><image>" * num_pages + "Multi page parsing.", and each page is encoded as one global view (base mode). The output contains one <PAGE> per input page, in the same order as image_files.

Single-page inference (infer). A single page is encoded with dynamic tiling (gundam mode) by default:

text = model.infer(tokenizer, image_file="your_doc/page_1.jpg",
                   output_path="output/single", save_results=True)
SGLang#

Set up the environment (uv-managed virtualenv, Python 3.10) and install the customized SGLang wheel sglang-0.5.20.dev13+g75b9b06b02-py3-none-any.whl, plus PyMuPDF for PDF-to-image conversion:

uv venv --python 3.10
source .venv/bin/activate

uv pip install wheel/sglang-0.5.20.dev13+g75b9b06b02-py3-none-any.whl
uv pip install pymupdf==1.27.2.2
uv pip install fastokens==0.3.2

Start the SGLang server:

# Page-window scheduling for very long documents (the KV tail of the previous window is reused).
export SGLANG_UOCR_EANABLE_DOC_LIMIT=1          # 1 = enable, 0 = whole document in one window
export SGLANG_UOCR_DOC_GUNDAM_PAGE_WINDOW=10    # pages per window (gundam mode)
export SGLANG_UOCR_DOC_BASE_PAGE_WINDOW=10      # pages per window (base mode)
export SGLANG_UOCR_MAX_PAGE_TOKENS=20000        # per-page output cap; must be > 0
# Chunk cap for the SAM attention bias. The built-in default (512) allows a single
# ~462 MiB allocation and can OOM; 64 is equivalent with a lower peak.
export SGLANG_OPT_UOCR_SAM_REL_POS_BIAS_MB=64
# Pass large crop tensors through /dev/shm instead of pickling them into the
# tokenizer -> scheduler frame.
export SGLANG_UOCR_SHM_WRAP_MODEL_DATA=1
export SGLANG_UOCR_SHM_WRAP_MIN_MB=1
export SGLANG_VLM_CACHE_SIZE_MB=0
# Reduces fragmentation failures on the large contiguous allocations.
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True

python -m sglang.launch_server \
    --model-path baidu/Unlimited-OCR-2 \
    --served-model-name Unlimited-OCR-2 \
    --chat-template unlimited-ocr \
    --tokenizer-backend fastokens \
    --tokenizer-worker-num 8 \
    --mem-fraction-static 0.7 \
    --max-running-requests 64 \
    --max-prefill-tokens 2048 \
    --enable-custom-logit-processor \
    --enable-streaming-session \
    --allow-auto-truncate \
    --disable-radix-cache \
    --mm-preprocess-cache-size-mb 0 \
    --cuda-graph-backend-decode full --cuda-graph-max-bs-decode 64 \
    --cuda-graph-backend-prefill full \
    --cuda-graph-max-bs-prefill 16384 \
    --cuda-graph-bs-prefill 1024 2048 \
    --cuda-graph-config '{"prefill": {"backend": "full", "full_prefill_max_req": 64}}' \
    --host 0.0.0.0 \
    --port 10000

Notes on the knobs that matter for memory:

  • --mem-fraction-static is the share reserved for weights + KV. 0.75 leaves too little headroom at 32+ concurrent requests; 0.7 is stable.
  • --max-prefill-tokens drives a temporary tensor of roughly [tokens, context/32], so memory grows linearly with it: 4096 -> 2048 halves that peak.
  • The largest --cuda-graph-bs-prefill bucket must equal --max-prefill-tokens. A smaller one makes oversized batches fall back to eager; a larger one is never used and only wastes capture memory.
  • --cuda-graph-config's full_prefill_max_req is the request-slot count for the full-prefill CUDA graph. The default (8) makes 16/32 concurrency fall back to eager.
  • A smaller page window lowers peak memory but hurts cross-page merging, since blocks that continue across a window boundary lose their context.

To parse a whole document in one window instead (SGLANG_UOCR_EANABLE_DOC_LIMIT=0).

Send requests to the OpenAI-compatible API:

import base64
import json
import os
import tempfile

import fitz
import requests
from sglang.srt.sampling.custom_logit_processor import DeepseekOCRNoRepeatNGramLogitProcessor

server_url = "http://127.0.0.1:10000"
NGRAM_PROCESSOR = DeepseekOCRNoRepeatNGramLogitProcessor.to_str()

session = requests.Session()
session.trust_env = False


def pdf_to_images(pdf_path, dpi=300):
    doc = fitz.open(pdf_path)
    tmp_dir = tempfile.mkdtemp(prefix="pdf_ocr_")
    mat = fitz.Matrix(dpi / 72, dpi / 72)
    image_paths = []
    for i, page in enumerate(doc):
        image_path = os.path.join(tmp_dir, f"page_{i + 1:04d}.png")
        page.get_pixmap(matrix=mat).save(image_path)
        image_paths.append(image_path)
    doc.close()
    return image_paths


def encode_image(image_path):
    ext = os.path.splitext(image_path)[1].lower()
    mime = "image/jpeg" if ext in (".jpg", ".jpeg") else f"image/{ext.lstrip('.')}"
    with open(image_path, "rb") as f:
        data = base64.b64encode(f.read()).decode("utf-8")
    return {"type": "image_url", "image_url": {"url": f"data:{mime};base64,{data}"}}


def build_content(image_paths):
    prompt = "<PAGE><image>" * len(image_paths) + "Multi page parsing."
    return [encode_image(path) for path in image_paths] + [{"type": "text", "text": prompt}]


def generate(image_paths, crop_mode=True, tokens_per_page=8000):
    # A wider n-gram window for multi-page documents, as in our evaluation setup.
    window_size = 1024 if len(image_paths) > 1 else 128
    payload = {
        "model": "Unlimited-OCR-2",
        "messages": [{"role": "user", "content": build_content(image_paths)}],
        # Must be positive: it is the global output budget for the whole document.
        "max_tokens": tokens_per_page * len(image_paths),
        "temperature": 0,
        "skip_special_tokens": False,
        "images_config": {"crop_mode": crop_mode},  # True = gundam (tiles), False = base
        "custom_logit_processor": NGRAM_PROCESSOR,
        "custom_params": {
            "ngram_size": 35,
            "window_size": window_size,
            "page_token_id": 128827,   # <PAGE> marker id (= sparse_attention_config.page_token_id)
            "eos_token_id": 1,         # = eos_token_id in config.json
            "max_page_tokens": 20000,  # per-page output cap, <= 0 disables the page guard
        },
        "stream": True,
    }
    response = session.post(
        f"{server_url}/v1/chat/completions",
        headers={"Content-Type": "application/json"},
        data=json.dumps(payload),
        timeout=6000,
        stream=True,
    )
    response.raise_for_status()

    chunks = []
    for line in response.iter_lines(decode_unicode=True):
        if not line or not line.startswith("data:"):
            continue
        data = line[len("data:"):].strip()
        if data == "[DONE]":
            break
        event = json.loads(data)
        choices = event.get("choices") or []  # the final chunk carries usage only
        if not choices:
            continue
        delta = (choices[0].get("delta") or {}).get("content") or ""
        if delta:
            print(delta, end="", flush=True)
            chunks.append(delta)
    return "".join(chunks)


# Multi page: all pages of a document, parsed in one request
pages = [f"your_doc/page_{i}.jpg" for i in range(1, 8)]
generate(pages)

# Single page
generate(["your_doc/page_1.jpg"])

# PDF
generate(pdf_to_images("your_doc.pdf", dpi=300))

Visualization#

Unlimited-horizon parsing in action: a full-length book parsed in a single request (replay).

Image: Harry Potter replay

Acknowledgement#

We would like to thank Deepseek-OCR, Deepseek-OCR-2, PaddleOCR for their valuable models and ideas, and SGLang for the serving framework.

Citation#

@misc{wei2026unlimitedocrworks2,
      title={Unlimited OCR Works 2}, 
      author={Baidu ERNIE Team},
      year={2026},
      eprint={2610.39308},
      archivePrefix={arXiv},
      primaryClass={cs.CL},
      url={https://arxiv.org/abs/2610.39308}, 
}

@misc{yin2026unlimitedocrworks,
      title={Unlimited OCR Works}, 
      author={Youyang Yin and Huanhuan Liu and YY and Qunyi Xie and Chaorun Liu and Shiqi Yang and Shaohua Wang and Zhanlong Liu and Hao Zou and Jinyue Chen and Shu Wei and Jingjing Wu and Mingxin Huang and Zhen Wu and Guibin Wang and Tengyu Du and Lei Jia},
      year={2026},
      eprint={2606.23050},
      archivePrefix={arXiv},
      primaryClass={cs.CV},
      url={https://arxiv.org/abs/2606.23050}, 
}

Files

26 files · 6.87 GBWeights 6.69 GB (safetensors). Sizes and sha256 from the signed manifest.
Show all 26 files with their sha256
FileSizesha256
.gitattributes2.05 KB505093a0ff67f0590597fef4771d75d600f1f3b99a8b925f32280655a00a9a69
README.md14.1 KB2944554a0649f4a2c0c99dac1cd1b129609042d1f1c9f17fdf9781215c7b9a6c
Unlimited-OCR-2.pdf1.52 MB1eb5885f4ddfa4ec6fbff375092377f30b5d6a5e034ec4936213f125bf2f9444
_sparse_base_impl.py222 KB86da9c5638704bb9338575040568a97b3e10820bbeb426f51c07e866f3423ccd
assets/HarryPotter.gif156 MB572305c08be5a87c14b0c211d3ef28398a00818b341bfcfdb8152678bffa8ea5
assets/Unlimited-OCR2.png1.08 MBe231defdf9aebbf8d6cf6a6dc15ded22412629a2cbf196436e2d9b58973aa678
assets/leaderboard.png1.48 MBaca406f669dba1af337d7ac9b7be6dafad89b3afbf3570567c578b50dfeb9e8b
assets/logo.png130 KBe1c533934d3d5abaa1666c8ce858d4f2195b14471c7e3b8f3da772972359652d
config.json5.53 KB607d130a70d5af5a35329aa237acd68651f45504c62cc7ced981066f4e781126
configuration_deepseek_v2.py10.7 KBb8470dd616ba8745fce6e27b093aef73a098863cc891b2477dcf9326a36000f7
conversation.py9.25 KBec7b6ce89bcda643de1f43269ffa66a7b2e65dc3ed30e427958f776546b4ba03
dash_attention.py71.5 KB960b460acd816df8e561e73dccd5683acb95445eddc723c4f0d6ed1f462b2f77
deepencoder.py37.9 KB419b63388c1645b9b72c716070cdca36cd0be6047049424dc75941d3a00aaf1f
generation_config.json111 Bdcd0479f3a12e5e4413d956197f8a4074408e4901834b38c7e036519134e05af
model-00001-of-00002.safetensors5.00 GB4c40b740f209fd7682040d4ebf19409208acde5c401ccd2dde426d0f41542f18
model-00002-of-00002.safetensors1.69 GB9490b82fa47f89e5110eb5577f8ab1b6694c12121905dbc086ddb10207a4ba0c
model.safetensors.index.json254 KBdc60a31ecb77eb03e166345d18cbe25bc71d2a19cc6fc089d8a9ac1c7f209671
modeling_deepseekv2.py25.6 KB24a15dfd47578ab24a7a4d4e977dc5d7a23dfef0a2a4c4bf73fcf3e2ce7acaf2
modeling_unlimitedocr.py55.7 KBf6df813cef23cc28b1daca40fd8cb20740d05a238e7b9dfa2334531fdcf39f1f
packing_patch.py8.11 KBe60d842c210c9f1d6cd2ae328cf9127a75f7941a0cea2a8e9abc14662f770c6c
sparse_gather_e2e_triton.py18.1 KB58f1bc46093d47b00744970677e66bfbd7485a2d13810f46d13d867ceda13dd4
sparse_gather_triton.py23.9 KBc3de717ffaca40240c665b8d645f15a9d1999feeabaa94beb35caad877c2f0f4
special_tokens_map.json549 B9e89493d7938e7710c524dbaff613c3648f0a018262417af78505128004e5cb4
tokenizer.json9.98 MBc55c165e32c5a67830362a53e1f548c8930dcc8469efa30ff3252a982799c589
tokenizer_config.json167 KBceba7d221f265cca4c98b5e0a1d48c10107270b7b29c12396610d6d0fd64b126
wheel/sglang-0.5.20.dev13+g75b9b06b02-py3-none-any.whl15.3 MB576c71dab3cacad843f6870739494e13b2e8169a69cc038f84395d6503e801ea
VersionsEach time the pinned upstream commit or file list changed in this repo. Newest first.
Upstream commitDateContents
0480966938 pinned now2026-11-14 06:34 UTC26 files · 6.87 GB

Use it

$ fw get baidu/Unlimited-OCR-2
# manifest sha256 ca5d500cac2d… · 6.87 GB · 26 files
$ fw verify ./Unlimited-OCR-2 baidu/Unlimited-OCR-2
fw.pyChecks the signature and every sha256, tries each source in order, resumes.
$ python3 fw.py get https://freeweights.allternit.com/manifests/baidu/Unlimited-OCR-2.json --dir ./Unlimited-OCR-2 $ python3 fw.py verify ./Unlimited-OCR-2 ./baidu__Unlimited-OCR-2.json
hfThe Hugging Face CLI with one setting. Same repo id.
$ HF_ENDPOINT=https://freeweights.allternit.com hf download baidu/Unlimited-OCR-2 --revision 0480966938291445591f69f08a13b041c073a96a --local-dir ./Unlimited-OCR-2
transformersLoad the weights in Python.
import os os.environ["HF_ENDPOINT"] = "https://freeweights.allternit.com" from transformers import AutoModelForImageTextToText, AutoProcessor processor = AutoProcessor.from_pretrained("baidu/Unlimited-OCR-2", revision="0480966938291445591f69f08a13b041c073a96a") model = AutoModelForImageTextToText.from_pretrained("baidu/Unlimited-OCR-2", revision="0480966938291445591f69f08a13b041c073a96a", device_map="auto")
vLLMServe an OpenAI-compatible API.
$ HF_ENDPOINT=https://freeweights.allternit.com vllm serve baidu/Unlimited-OCR-2 --revision 0480966938291445591f69f08a13b041c073a96a

License

Name
MIT License
Id
MIT
Class
Permissive
Redistribution
yes
Listing
Hosted (signed)
Decided
Checked and recorded in the license audit. 2026-11-14
Text in
README.md
Text sha256
2944554a0649f4a2c0c99dac1cd1b129609042d1f1c9f17fdf9781215c7b9a6c
Terms gate
No extra terms beyond the license.

Read the license text

Licenses are checked against the license table. A custom license passes only after a person reads it.

Provenance

From: baidu <huggingface.co/baidu>Newsgroups: alt.freeweights.ocrSubject: Unlimited-OCR-2Date: 2026-11-14Commit: 0480966Signed: 2DC28CC7B26A283B ✓
Upstream
baidu/Unlimited-OCR-2
Pinned commit
0480966938291445591f69f08a13b041c073a96a
Manifest
Unlimited-OCR-2.json · .minisig
Manifest sha256
ca5d500cac2d3f179c34cab9e7826daf50db8a1471616a5ed7ec8ccb7bbf9b4e
Signature
minisign, Ed25519, key 2DC28CC7B26A283B
Created
2026-11-14 06:34 UTC
Generator
freeweights-manifest/0.1.0
Takedowns
None.

How to verify

$ curl -O https://freeweights.allternit.com/manifests/baidu/Unlimited-OCR-2.json $ curl -O https://freeweights.allternit.com/manifests/baidu/Unlimited-OCR-2.json.minisig $ minisign -Vm Unlimited-OCR-2.json -P RWQ7KGqyx4zCLXtUFOqvfv8L3g+8fpKJ1FsuxPyOYMF+4KufbUxKq1Oq $ shasum -a 256 <file> # compare with the Files tab

A manifest whose signature fails must be rejected. A file whose size or sha256 does not match must be discarded. Verify a download

Model tree

4 models in the catalog name this one as their parent.

Fine-tunes
1
Quantizations
3
Get it
Download
$ HF_ENDPOINT=https://freeweights.allternit.com hf download baidu/Unlimited-OCR-2
Open in Freeweights Studio

Pull, verify and run it in the Allternit app on Desktop, web or phone.

Signed manifest
minisign, key 2DC28CC7B26A283B. Unlimited-OCR-2.json. Provenance. Takedown history: none.

Variants

3 quantized or adapter builds of Unlimited-OCR-2. Each has its own license check and page.

From: mlx-community <huggingface.co/mlx-community>Subject: Unlimited-OCR-2-4bit
From: mlx-community <huggingface.co/mlx-community>Subject: Unlimited-OCR-2-6bit
From: mlx-community <huggingface.co/mlx-community>Subject: Unlimited-OCR-2-8bit