The model corrects noisy OCR while trying to preserve historical spelling, wording, punctuation, names, dates, and line breaks.
English Overproof subset of HIPE-OCRepair 2026.
1Input: ocr_hypothesis.transcription_unit
2Target: ground_truth.transcription_unit
The prompt uses available metadata such as date, language, publication title, document type, and segmentation source. It does not use CER, WER, OCR quality scores, or any ground-truth-derived information.
Lower CER/WER is better.
1import torch
2from peft import PeftModel
3from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
4
5base_model_id = "Qwen/Qwen2.5-3B-Instruct"
6adapter_id = "emanuelaboros/qwen2-5-3b-overproof-postcorrection"
7
8tokenizer = AutoTokenizer.from_pretrained(base_model_id, trust_remote_code=True)
9
10bnb_config = BitsAndBytesConfig(
11 load_in_4bit=True,
12 bnb_4bit_quant_type="nf4",
13 bnb_4bit_compute_dtype=torch.bfloat16,
14 bnb_4bit_use_double_quant=True,
15)
16
17base_model = AutoModelForCausalLM.from_pretrained(
18 base_model_id,
19 device_map="auto",
20 dtype=torch.bfloat16,
21 quantization_config=bnb_config,
22 trust_remote_code=True,
23)
24
25model = PeftModel.from_pretrained(base_model, adapter_id)
26model.eval()
27
28ocr_text = "GOOD TEMPLARS. At the quarterly meeting of tho Centennial Lodge..."
29
30messages = [
31 {
32 "role": "system",
33 "content": (
34 "You are an OCR post-correction system for historical newspaper text. "
35 "Correct OCR transcription errors while preserving the original document as faithfully as possible. "
36 "Return only the corrected transcription."
37 ),
38 },
39 {
40 "role": "user",
41 "content": f"Correct the OCR transcription below.\n\nOCR text:\n{ocr_text}",
42 },
43]
44
45prompt = tokenizer.apply_chat_template(
46 messages,
47 tokenize=False,
48 add_generation_prompt=True,
49)
50
51inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
52
53with torch.no_grad():
54 output_ids = model.generate(
55 **inputs,
56 max_new_tokens=2048,
57 do_sample=False,
58 repetition_penalty=1.05,
59 pad_token_id=tokenizer.eos_token_id,
60 )
61
62generated_ids = output_ids[0][inputs["input_ids"].shape[-1]:]
63prediction = tokenizer.decode(generated_ids, skip_special_tokens=True).strip()
64
65print(prediction)
This adapter was trained on a small English historical newspaper dataset. It may overcorrect, hallucinate plausible text, or fail to preserve the source faithfully. Generation-based CER/WER should be computed before use in benchmark submissions or corpus processing.