73 6 months ago

Samaritan Hebrew OCR model, full page

vision tools
ollama run johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0

Applications

Claude Code
Claude Code ollama launch claude --model johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0
OpenCode
OpenCode ollama launch opencode --model johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0
Hermes Agent
Hermes Agent ollama launch hermes --model johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0
OpenClaw
OpenClaw ollama launch openclaw --model johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0

Models

View all →

Readme

LightOnOCR-2-1B-Q8_0 for Samaritan Hebrew/Aramaic

LightOnOCR Banner

This model is a fine-tuned version of lightonai/LightOnOCR-2-1B-base specifically trained for page-level OCR of Samaritan manuscripts.

Model Description

This is a page-level model - it expects full pages, paragraphs or crops of lines.

Evaluation Results

Test Set Performance

Metric Base Model Fine-tuned Model Improvement
CER (Character Error Rate) 475.89% 7.68% +468.22% (+98.4%)
WER (Word Error Rate) 341.22% 15.37% +325.85% (+95.5%)
Perfect Matches 0/50 (0.00%) 3750 (74.00%) +74.00%
Character Accuracy 382.84% 59.31% -323.53%

Model Details

  • Base Model: lightonai/LightOnOCR-2-1B-base
  • Fine-tuned Model: LightOnOcr-2_samaritan
  • Test Samples: 50
  • Evaluation Date: 2026-01-23 14:19:32

Usage

Installation

# Requires transformers from source
pip install git+https://github.com/huggingface/transformers
pip install pillow torch

Python Usage

import torch
from transformers import LightOnOcrForConditionalGeneration, LightOnOcrProcessor
from PIL import Image

# Load model and processor
model_id = "johnlockejrr/LightOnOCR-2-1B-base-samaritan"
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.bfloat16 if device == "cuda" else torch.float32

processor = LightOnOcrProcessor.from_pretrained(model_id)
model = LightOnOcrForConditionalGeneration.from_pretrained(
    model_id,
    torch_dtype=dtype,
).to(device)

# Load your line image
image = Image.open("your_line_image.jpg").convert("RGB")

# Prepare input
messages = [{"role": "user", "content": [{"type": "image"}]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

inputs = processor(
    text=[text],
    images=[[image]],
    return_tensors="pt",
    padding=True,
    size={"longest_edge": 1024},
).to(device)
inputs["pixel_values"] = inputs["pixel_values"].to(dtype)

# Generate transcription
with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=4028, do_sample=False)

# Decode output
input_length = inputs["input_ids"].shape[1]
generated_ids = outputs[0, input_length:]
transcription = processor.decode(generated_ids, skip_special_tokens=True)

print(transcription)

Batch Inference

from datasets import load_dataset

# Load dataset
dataset = load_dataset("johnlockejrr/LightOnOCR-2-1B-base-samaritan", split="train[:10]")

# Process batch
images = [[img.convert("RGB")] for img in dataset["image"]]
messages = [{"role": "user", "content": [{"type": "image"}]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
texts = [text] * len(images)

inputs = processor(
    text=texts,
    images=images,
    return_tensors="pt",
    padding=True,
    size={"longest_edge": 1024},
).to(device)
inputs["pixel_values"] = inputs["pixel_values"].to(dtype)

outputs = model.generate(**inputs, max_new_tokens=4028, do_sample=False)
predictions = processor.batch_decode(outputs[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)

for pred, gt in zip(predictions, dataset["text"]):
    print(f"Prediction: {pred}")
    print(f"Ground Truth: {gt}")
    print()

Ollama Usage

ollama run johnlockejrr/LightOnOCR-2-1B-base-samaritan-Q8_0 "Transcribe this image:" /mnt/d/datasets/sam_44_mss/CBL_Ms._Heb_751_147.jpg
Added image '/mnt/d/datasets/sam_44_mss/CBL_Ms._Heb_751_147.jpg'
הן קניתי אתכם היום ואת אדמתיכם
לפרעה הא לכם זרע וזרעתם
את האדמה והיה בתבואתה ונתתם
חמישת לפרעה וארבע הידות
יהיה לכם לזרע השדה ולאכלכם
ולאשר בבתיכם ולאכל לטפכם
ויאמרו החיתנו נמצא חן בעיני
אדני והיינו עבדים לפרעה
וישם אתה יוסף לחק עד היום
הזה על אדמת מצרים לפרעה
לחמוש רק אדמת הכהנים לבדה
לא היתה לפרעה
וישב ישראל בארץ מצרים
בארץ גשן ויאחזו בה ויפרו
וירבו מאד ויחי יעקב בארץ
מצרים שבע עשרה שנה ויהיו ימי
יעקב שני חייו שבע שנים וארבעים
ומאת שנה ויקברו ימי ישראל
למות ויקרא לבנו ליוסף
ויאמר לו אם נא מצתי חן בעיניך
שים נא ידך תחת ירכי ועשית נא
עמדי חסד ואמת אל נא תקברני
במצרים ושכבתי עם אבתי ונשאתני
ממצרים וקברתני בקברתם ויאמר
אנכי אעשה כדבריך ויאמר השבע
לי וישבע לו וישתחוי ישראל על ראש
המטה

Training Details

  • Base Model: lightonai/LightOnOCR-2-1B-base
  • Training Method: Fine-tuning with frozen language model backbone
  • Optimizer: AdamW (fused)
  • Learning Rate: 6e-5 with linear decay
  • Precision: bfloat16

Limitations

  • This model is trained on line-level images only. For full-page transcription, you need to first segment the page into individual lines.
  • Performance may vary on manuscript styles not represented in the training data.
  • Old Church Slavonic has many abbreviations and special characters that may require domain-specific post-processing.

Citation

If you use this model, please cite:

@misc{lightonocr2_smp_2026,
  title = {LightOnOCR Fine-tuned for Samaritan Hebrew/Aramaic},
  author = {John Locke},
  year = {2026},
  howpublished = {\url{https://huggingface.co/johnlockejrr/LightOnOCR-2-1B-base-samaritan}}
}

And the original LightOnOCR paper:

@misc{lightonocr2_2026,
  title = {LightOnOCR: A 1B End-to-End Multilingual Vision-Language Model for State-of-the-Art OCR},
  author = {Said Taghadouini and Adrien Cavaill\`{e}s and Baptiste Aubertin},
  year = {2026},
  howpublished = {\url{https://arxiv.org/pdf/2601.14251}}
}

Acknowledgments

  • LightOn AI for the excellent LightOnOCR base model