Model reference · open weights
Unlimited-OCR is an open-weight language model from Baidu. Unlimited-OCR (BF16) weighs 6.7 GB; the smallest configuration that runs it is RTX 3060 12 GB.
Summary of the baidu/Unlimited-OCR model card, 2026-10-01
What it is
| Released by | Baidu |
|---|---|
| Released | 2026-06-19 |
| Parameters | 3.3B |
| VRAM | 6.7 GB for the weights |
What it runs on
| Card | Requests at once | Context max | Memory | |
|---|---|---|---|---|
| 8K each | 32K each | |||
| RTX 3060 12 GB | 5 | 1 | all 32K | 11.6 GB |
| RTX 4060 Ti 16 GB | 12 | 3 | all 32K | 15.4 GB |
| RTX 3090 24 GB | 28 | 7 | all 32K | 23.4 GB |
| RTX 4090 24 GB | 28 | 7 | all 32K | 23.4 GB |
| RTX 5090 32 GB | 43 | 10 | all 32K | 31.0 GB |
| L40S 48 GB | 69 | 17 | all 32K | 44.0 GB |
| A100 80 GB | 137 | 34 | all 32K | 78.2 GB |
| H100 80 GB | 128 | 32 | all 32K | 78.1 GB |
| RTX PRO 6000 Blackwell 96 GB | 159 | 39 | all 32K | 93.8 GB |
| DGX Spark (GB10) 128 GB unified | 186 | 46 | all 32K | 107 GB |
| H200 141 GB | 246 | 61 | all 32K | 138 GB |
| B200 180 GB | 319 | 79 | all 32K | 176 GB |
| 2× RTX 3060 12 GB tensor parallel | 23 | 5 | all 32K | 11.6 GB a card |
| Requests at once | 8K tokens each | 32K tokens each |
|---|---|---|
| 1 | 9.4 GB | 10.9 GB |
| 5 | 11.4 GB | 19.0 GB |
| 8 | 12.9 GB | 25.0 GB |
| 16 | 17.0 GB | 41.1 GB |
| 32 | 25.0 GB | 73.3 GB |
| 64 | 41.1 GB | 138 GB |
One card, with vLLM's small-card settings.
From the model card
Inference using Huggingface transformers on NVIDIA GPUs. Requirements tested on python 3.12.3 + CUDA12.9:
torch==2.10.0
torchvision==0.25.0
transformers==4.57.1
Pillow==12.1.1
matplotlib==3.10.8
einops==0.8.2
addict==2.4.0
easydict==1.13
pymupdf==1.27.2.2
psutil==7.2.2
import os
import torch
from transformers import AutoModel, AutoTokenizer
model_name = 'baidu/Unlimited-OCR'
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,
)
model = model.eval().cuda()
# ── Single image supports two configs: gundam or base ──
# gundam: base_size=1024, image_size=640, crop_mode=True
# base: base_size=1024, image_size=1024, crop_mode=False
model.infer(
tokenizer,
prompt='document parsing.',
image_file='your_image.jpg',
output_path='your/output/dir',
base_size=1024, image_size=640, crop_mode=True,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=128,
save_results=True,
)
# ── Multi page / PDF only uses base (image_size=1024) ──
model.infer_multi(
tokenizer,
prompt='Multi page parsing.',
image_files=['page1.png', 'page2.png', 'page3.png'],
output_path='your/output/dir',
image_size=1024,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=1024,
save_results=True,
)
# ── PDF (convert pages to images, then multi-page parsing) ──
import tempfile, fitz # PyMuPDF
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)
paths = []
for i, page in enumerate(doc):
out = os.path.join(tmp_dir, f'page_{i+1:04d}.png')
page.get_pixmap(matrix=mat).save(out)
paths.append(out)
doc.close()
return paths
model.infer_multi(
tokenizer,
prompt='Multi page parsing.',
image_files=pdf_to_images('your_doc.pdf', dpi=300),
output_path='your/output/dir',
image_size=1024,
max_length=32768,
no_repeat_ngram_size=35, ngram_window=1024,
save_results=True,
)
Please refer to the official vLLM recipe for deployment details:
Recipe: https://recipes.vllm.ai/baidu/Unlimited-OCR
Use the following Docker images depending on your GPU platform:
Default (CUDA 13.0):
docker pull vllm/vllm-openai:unlimited-ocr
For Hopper GPUs (CUDA 12.9)
docker pull vllm/vllm-openai:unlimited-ocr-cu129
Set up the environment (uv-managed virtualenv). Install the local SGLang wheel first,
then pin kernels==0.9.0 and install PyMuPDF for PDF-to-image conversion:
uv venv --python 3.12
source .venv/bin/activate
uv pip install wheel/sglang-0.0.0.dev11416+g92e8bb79e-py3-none-any.whl
uv pip install kernels==0.11.7
uv pip install pymupdf==1.27.2.2
Start the SGLang server:
python -m sglang.launch_server \
--model baidu/Unlimited-OCR \
--served-model-name Unlimited-OCR \
--attention-backend fa3 \
--page-size 1 \
--mem-fraction-static 0.8 \
--context-length 32768 \
--enable-custom-logit-processor \
--disable-overlap-schedule \
--skip-server-warmup \
--host 0.0.0.0 \
--port 10000
Send streaming 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"
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(prompt, image_paths):
return [{"type": "text", "text": prompt}] + [encode_image(path) for path in image_paths]
def generate(prompt, image_paths, image_mode, ngram_window):
payload = {
"model": "Unlimited-OCR",
"messages": [{"role": "usQuoted from the model card on Hugging Face. The full card is behind the Hugging Face link above.