absir-arabic-ocr-mini
absir-arabic-ocr-mini is the second version of absir-arabic-ocr-1.6B: a page-level OCR model for printed Arabic documents, less than half the size (0.7B parameters). It is more accurate than the 1.6B on every text score below and on KITAB table recognition (TEDS 85.4 against 64.6); on Misraj's table structure the two are level. It reads a full page image and returns the text in reading order, with light HTML structure:
<p>paragraphs and<h1>to<h6>headings<strong>,<sup>(note markers),<br>and<hr><table>for printed tables and tables of contents- the footnote block wrapped in
<footnotes>
Diacritics (tashkeel) are kept.
absir-arabic-ocr-mini is based on nvidia/Nemotron-3.5-Parse with 0.7B parameters (0.44B vision encoder, 10-layer mBART decoder). The model went through supervised fine-tuning on 58,700 page images from about 3,400 books, plus rendered pages, then few rounds of GRPO reinforcement learning to reduce repetition and loops.
Examples
Real outputs of this model (greedy decoding, as in Usage), with the HTML rendered and every difference from the print highlighted: red for a misread word, amber where the model changed the print's spelling. On older prints the model often confuses hamza and ya: it adds hamzas the print leaves out (الى → إلى, ان → أن) and writes the print's final ى as ي (فى → في). This is probably learned from the training labels. Both pages are from public-domain books on Wikimedia Commons; neither page's text is in the training labels.
Sources: Qasim Amin, Tahrir al-Mar'a, Cairo 1899, p. 36 (Commons, public domain); Ibn al-Nadim, al-Fihrist, ed. G. Flügel, Leipzig 1871, p. 40 (Commons, public domain).
Usage
import torch
from PIL import Image
from transformers import AutoModel, AutoProcessor
repo = "g3ida/absir-arabic-ocr-mini"
model = AutoModel.from_pretrained(repo, trust_remote_code=True, dtype=torch.bfloat16).to("cuda").eval()
processor = AutoProcessor.from_pretrained(repo, trust_remote_code=True)
PROMPT = "</s><s><no_bbox><no_classes><output_markdown><predict_no_text_in_pic>"
def enlarge(im):
# The model was trained on pages enlarged to fill 1664x2048; the processor only ever shrinks.
s = min(1664 / im.width, 2048 / im.height)
return im.resize((round(im.width * s), round(im.height * s)), Image.LANCZOS) if s > 1 else im
image = enlarge(Image.open("page.png").convert("RGB"))
inputs = processor(images=[image], text=PROMPT, return_tensors="pt", add_special_tokens=False).to("cuda")
with torch.inference_mode():
out = model.generate(**inputs, max_new_tokens=4096, do_sample=False, repetition_penalty=1.0)
print(processor.batch_decode(out, skip_special_tokens=True)[0])
Use the prompt above exactly: it is the one the model was trained with. The base model's other prompts (bounding boxes, layout classes) were not trained for Arabic here.
Recommended decoding: greedy, repetition_penalty=1.0, max_new_tokens=4096. If a page uses up all 4096 tokens or ends in a repeating tail, read it again with repetition_penalty=1.2, and if it loops again, cut the text where the repetition starts. All the scores below use this retry; it changes a handful of pages per thousand.
vLLM: the architecture needs NVIDIA's Nemotron vLLM plugin. Install it as described in the base model card, then serve this repository the same way (vllm serve g3ida/absir-arabic-ocr-mini --trust-remote-code --chat-template chat_template.jinja ...) and send the prompt above as the text part of the message, with the image enlarged as in enlarge(). Served this way on one RTX 3090, it read the 400 Misraj pages in 5.6 minutes (16 requests at a time).
Evaluation
Scores below were run following rule: greedy decoding, repetition_penalty=1.0, max_new_tokens=4096. If a page uses up all 4096 tokens or ends in a repeating tail, read it again with repetition_penalty=1.2, and if it loops again, cut the text where the repetition starts.
Other models numbers are copied from the benchmark papers and from the Nuqta-Arabic-OCR model card; this model's numbers were measured with the same data and scoring code. Pages were enlarged as in Usage.
KITAB-Bench OCR, hindawi subset (200 book pages)
Hindawi is the only full-page printed-document subset of KITAB-Bench's OCR track. Scored with KITAB-Bench's preprocess_arabic_text and torchmetrics CharErrorRate / WordErrorRate over all 200 pages; lower is better.
| Model | CER | WER |
|---|---|---|
| Gemini-2.0-Flash | 0.01 | 0.04 |
| absir-arabic-ocr-mini | 0.019* | 0.069* |
| Nuqta-Arabic-OCR 4B (recommended input) | 0.029 | – |
| absir-arabic-ocr-1.6B | 0.046* | 0.145* |
| Azure OCR | 0.06 | 0.28 |
| Nuqta-Arabic-OCR 4B (images as given) | 0.090 | – |
| Qari | 0.11 | 0.15 |
| Surya | 0.15 | 0.20 |
| Qwen2.5-VL-7B | 0.27 | 0.42 |
| GPT-4o | 0.34 | 0.56 |
* The absir models output HTML tags and the hindawi ground truth is plain text, so tags are replaced by a space before scoring (re.sub(r"<[^>]+>", " ", pred)).
Misraj-DocOCR (400 modern document pages)
Scored with the recipe the Nuqta-Arabic-OCR card uses. Nothing is clipped: a runaway page counts in full.
| Model | Size | CER ↓ | WER ↓ | chrF ↑ | TEDS ↑ | MARS ↑ |
|---|---|---|---|---|---|---|
| Nuqta-Arabic-OCR 4B (recommended input) | 4.75B | 0.121 | 0.246 | 89.4 | 76.1 | 82.8 |
| Baseer v2 | not stated | 0.12 | 0.19 | 88.9 | 67 | 77.8 |
| Gemini-2.5-Pro | closed | 0.31 | 0.37 | 89.6 | 52 | 70.8 |
| Azure Document Intelligence | closed | 0.27 | 0.44 | 82.5 | 42 | 62.2 |
| dots.ocr | 3B | 0.40 | 0.50 | 78.4 | 40 | 59.2 |
| absir-arabic-ocr-mini | 0.7B | 0.190 | 0.272 | 84.4 | 28.5 | 56.4 |
| GPT-5 | closed | 0.62 | 0.86 | 61.6 | 48 | 54.8 |
| absir-arabic-ocr-1.6B | 1.6B | 0.552 | 0.715 | 63.9 | 29.4 | 46.6 |
| QARI | – | 0.64 | 0.76 | 64.5 | 21 | 42.8 |
On text, absir-arabic-ocr-mini is third behind Nuqta 4B and Baseer v2 (CER 0.190, WER 0.272), ahead of Gemini-2.5-Pro and Azure. It is weak on Misraj's table structure: on 24 of the 59 pages with a table in the reference it writes the cells as paragraphs instead of a <table>, which TEDS scores as 0. The absir-arabic-ocr-1.6B row is re-scored here with this recipe; its card reported a per-page mean (CER 0.58) instead.
KITAB-Bench table recognition (241 HTML tables)
TEDS, higher is better. Published models were prompted with KITAB-Bench's table prompt; the absir models are scored with the prompt they were trained on.
| Model | TEDS |
|---|---|
| GPT-4o | 85.8 |
| absir-arabic-ocr-mini | 85.4 |
| Gemini-2.0-Flash | 83.1 |
| AIN-7B | 75.9 |
| GPT-4o-mini | 69.3 |
| absir-arabic-ocr-1.6B | 64.6 |
| Qwen2.5-VL-7B | 59.3 |
| Qwen2-VL-7B | 57.8 |
| Surya | 50.2 |
| EasyOCR (Docling) | 49.1 |
| Tesseract (Docling) | 28.2 |
Limitations
- Trained mostly on book pages. Handwriting, scene text, single-line crops and pages in other scripts are out of scope; on pages with mostly Latin text or long tables of numbers it can fall into a repetition loop (the retry in Usage catches most of these).
- Hamza and ya follow modern spelling rather than the print: on older books it may add a hamza to a bare alef (الى → إلى) and write a final ى as ي, probably because many training labels were written that way.
- Like any model with a language decoder, it may occasionally replace a hard-to-read word with a fluent but different one. Treat the output as a draft for critical use.
License
The weights are released under the OpenMDW-1.1 license, inherited from nvidia/Nemotron-3.5-Parse (see LICENSE). The tokenizer is MIT-licensed (see TOKENIZER_ATTRIBUTION.md); our only change to it is the normalizer, set from NFKC to NFC so that ﷺ and ﷻ are not expanded into words. Third-party notices are in THIRD_PARTY_NOTICES.md.
Benchmarks referenced
- KITAB-Bench: arXiv:2502.14949, OCR track (hindawi subset) and table recognition.
- Misraj-DocOCR / Baseer: arXiv:2509.18174.
- Nuqta-Arabic-OCR: model card and scoring code and predictions.