Alhazen-OCR

Alhazen-OCR is an Arabic-first OCR vision-language model: a QLoRA adapter on top of Qwen3-VL-2B-Instruct, fine-tuned on context212/atlas-ocr-data β€” a license-clean mix of Arabic synthetic documents, invoices, and handwritten text (KHATT).

Named after Ibn al-Haytham (Alhazen), the 11th-century pioneer of optics.

Benchmark

Evaluated with CER/WER (lower is better) on the held-out eval split of the training data and on the external ahmedheakl/arocrbench_khatt benchmark (100 samples each, greedy decoding):

Model Eval CER ↓ Eval WER ↓ KHATT-bench CER ↓ KHATT-bench WER ↓
Qwen3-VL-2B-Instruct (base) 0.653 0.951 1.498 1.594
Alhazen-OCR (1 epoch) 0.368 0.567 2.761 1.707

Reading the numbers: fine-tuning cuts character errors nearly in half on in-distribution documents (0.65 β†’ 0.37 CER) and word errors from 0.95 β†’ 0.57. On the external KHATT handwriting benchmark the model still struggles β€” this is a first smoke run on 20k samples; scaling data and training is expected to close the gap. Published as a work-in-progress baseline.

Usage

import torch
from unsloth import FastVisionModel

model, tokenizer = FastVisionModel.from_pretrained(
    "context212/alhazen-ocr",
    load_in_4bit=True,
)
FastVisionModel.for_inference(model)

messages = [{
    "role": "user",
    "content": [
        {"type": "image", "image": image},  # a PIL.Image
        {"type": "text", "text": "Extract all the text from this image, preserving the original reading order."},
    ],
}]
inputs = tokenizer.apply_chat_template(
    messages, tokenize=True, add_generation_prompt=True,
    return_dict=True, return_tensors="pt",
).to(model.device)

with torch.inference_mode():
    out = model.generate(**inputs, max_new_tokens=512, temperature=0.0, do_sample=False)
print(tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))

Training

  • Base: unsloth/Qwen3-VL-2B-Instruct (4-bit)
  • Method: QLoRA via unsloth β€” r=16, rsLoRA, vision + language layers (17.4M trainable params, 0.81%)
  • Data: 20,000 samples from context212/atlas-ocr-data (60% synthetic documents, 20% invoices, 20% handwriting)
  • Schedule: 1 epoch, lr 2e-5, cosine, bf16, batch 16, seq 2048 β€” single A100 80GB, ~35 min
  • Checkpoint selection: per-epoch eval on held-out split + external benchmark; epoch 1 won (later epochs diverge β€” see the repo for details)

Data sources & licenses

Source License
loay/arabic-ocr-synthetic-scans-faker-300k CC-BY-4.0
KhalfounMehdi/arabic-latin-invoices-synthetic CC-BY-4.0
johnlockejrr/KHATT_v1.0_dataset MIT
sherif1313/Historical-Arabic-Handwritten-OCR Apache-2.0

Eval benchmark: ahmedheakl/arocrbench_khatt (MIT).

Limitations

  • First smoke run (20k samples, 1 epoch) β€” handwriting and out-of-distribution documents remain weak (see KHATT-bench column)
  • Trained on line/paragraph-level crops; full-page layout parsing untested
  • Arabic-first; other scripts not evaluated

Code

Training, data pipeline and evaluation: github.com/context212/atlas-ocr

Downloads last month
9
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Datasets used to train context212/alhazen-ocr