QCRI/Fanar-2-Oryx-IVU, an Arabic-first
vision-language model, trained on a deliberately mixed diet of real
handwriting so it reads ink instead of reciting a dataset.| input | ground truth | Warraq output | |
|---|---|---|---|
| Cheque legal amount, photographed crop (read whole-image) | «أربعة آلاف وستمائة وخمسة عشر» | «أربعة آلاف وستمائة وخمسة عشر .» | ✅ exact |
| School sentences on ruled paper, phone photo — line 1 of 3 | «سوف يزرع الفلاح البطاطس في الخريف .» | «- سوف يزرع الفلاح البطاطس في الخريف .» | ✅ exact |
| 12-line poem on ruled notebook paper, phone photo — one of 12 auto-split lines | «سهلنا والجبل منبت للرجال» | «سهلنا والجبل منبت للرّجال» | ✅ exact |
| Same school photo — line 3 (one letter missed, shown for honesty) | «لا تحاولوا أن تتسلقوا هذه الشجرة العالية .» | «- لا تحاولوا أن تسلقوا هذه الشجرة العالية .» | ⚠️ one letter |
| model | CER ↓ | WER ↓ | exact lines |
|---|---|---|---|
| Warraq (this adapter) | 3.86% | 16.55% | 29.29% |
| Arabic-English-handwritten-OCR-v3 (best other model) | 5.86% | 18.30% | 28.81% |
| Fanar-2-Oryx-IVU (same base, zero-shot) | 50.98% | 82.58% | 0.10% |

Fair-comparison note, read it: Warraq's training data includes the KHATT training split, so its KHATT-test score is an in-domain result. The other models never saw KHATT — they are measured zero-shot under the same prompt, decoding and normalization. The table answers "who reads this handwriting best today", not "whose base model is smartest". Full protocol, all 9 models, distribution stats and charts: evaluation report on GitHub · raw numbers:benchmark.json.
1from transformers import AutoModelForImageTextToText, AutoProcessor
2from peft import PeftModel
3from PIL import Image
4
5BASE = "QCRI/Fanar-2-Oryx-IVU"
6processor = AutoProcessor.from_pretrained(BASE)
7model = AutoModelForImageTextToText.from_pretrained(BASE, device_map="auto")
8model = PeftModel.from_pretrained(model, "mabdulaziz499/Warraq-Arabic-HTR-7B")
9
10image = Image.open("line.jpg") # one handwritten LINE works best
11messages = [{"role": "user", "content": [
12 {"type": "image", "image": image},
13 {"type": "text", "text": "اكتب النص المكتوب بخط اليد في هذه الصورة كما هو تماما."},
14]}]
15inputs = processor.apply_chat_template(
16 messages, add_generation_prompt=True, tokenize=True,
17 return_dict=True, return_tensors="pt").to(model.device)
18out = model.generate(**inputs, max_new_tokens=128, do_sample=False)
19print(processor.decode(out[0][inputs["input_ids"].shape[1]:],
20 skip_special_tokens=True))| Method | QLoRA (4-bit NF4 base, bf16 compute), LoRA r=16 α=32, attention+MLP |
| Trainable | ≈40M parameters (0.48% of Fanar-2-Oryx-IVU) |
| Data | 24,487 lines: KHATT v1.0 + OnlineKhatt + Muharaf + hard-degraded synthetic (gray paper, watermarks, deep low-res, JPEG — cheque-like conditions) |
| Steps | 4000 (≈2.6 epochs), cosine schedule |
| Leakage guard | every training line whose exact text appears in the eval set is dropped |
| Text order | all sources auto-checked for visual-order (reversed) ground truth and normalized to logical order |
QCRI/Fanar-2-Oryx-IVU by QCRI. Training data
credits: KHATT v1.0 (research terms), OnlineKhatt, Muharaf. If you use
Warraq, please also cite KHATT (Mahmoud et al., Pattern Recognition 2014)
and the base model.