Views
No views yet
| field | content | example |
|---|---|---|
registration_no | digits and letters | 2572U00739 |
roll_no | digits only | 7200739 |
course_code | a letter followed by digits | U12028 |
marks_obtained | a number | 45 |
<blank> — the field is empty (nothing written)<strikethrough> — a value was written and then crossed out<unclear> is described in the prompt convention but had no training examples in
this release, so the model is not expected to emit it.)| field | accuracy |
|---|---|
| overall | 0.979 |
| course_code | 0.995 |
| marks_obtained | 0.980 |
| roll_no | 0.980 |
| registration_no | 0.960 |
1import torch
2from PIL import Image
3from peft import PeftModel
4from transformers import AutoModelForImageTextToText, AutoProcessor
5
6BASE = "Qwen/Qwen3.5-2B"
7ADAPTER = "jhanwarsid/qwen3.5-2b-omr-lora"
8
9CATEGORIES = {"<blank>", "<strikethrough>", "<unclear>"} # outputs meaning "review"
10PROMPTS = {
11 "registration_no": "This image is a single field cropped from a student OMR sheet containing a handwritten registration number (digits and letters, e.g. 2572U00739). Transcribe it exactly as written, outputting only the value with no spaces, quotes, labels, or explanation. If the field is empty with nothing written, output <blank>. If a value was written and then struck through or crossed out, output <strikethrough>.",
12 "roll_no": "This image is a single field cropped from a student OMR sheet containing a handwritten roll number (digits only, e.g. 7200739). Transcribe it exactly as written, outputting only the value with no spaces, quotes, labels, or explanation. If the field is empty with nothing written, output <blank>. If a value was written and then struck through or crossed out, output <strikethrough>.",
13 "course_code": "This image is a single field cropped from a student OMR sheet containing a handwritten course code (a letter followed by digits, e.g. U12028). Transcribe it exactly as written, outputting only the value with no spaces, quotes, labels, or explanation. If the field is empty with nothing written, output <blank>. If a value was written and then struck through or crossed out, output <strikethrough>.",
14 "marks_obtained": "This image is a single field cropped from a student OMR sheet containing the handwritten marks obtained (a number, e.g. 45). Transcribe it exactly as written, outputting only the value with no spaces, quotes, labels, or explanation. If the field is empty with nothing written, output <blank>. If a value was written and then struck through or crossed out, output <strikethrough>.",
15}
16
17processor = AutoProcessor.from_pretrained(BASE, trust_remote_code=True)
18model = AutoModelForImageTextToText.from_pretrained(
19 BASE, dtype=torch.bfloat16, trust_remote_code=True
20)
21model = PeftModel.from_pretrained(model, ADAPTER).eval()
22# model = model.to("cuda") # or "mps"
23
24def read_field(image_path: str, field: str, max_new_tokens: int = 24) -> str:
25 img = Image.open(image_path).convert("RGB")
26 messages = [{
27 "role": "user",
28 "content": [
29 {"type": "image", "image": img},
30 {"type": "text", "text": PROMPTS[field]},
31 ],
32 }]
33 text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
34 inputs = processor(text=[text], images=[[img]], return_tensors="pt").to(model.device)
35 out = model.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False)
36 value = processor.tokenizer.decode(
37 out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True
38 ).strip()
39 return value # a value, or a category token in CATEGORIES (-> manual review)
40
41print(read_field("roll_no.jpg", "roll_no"))r=16, alpha=32, dropout 0.05, target_modules="all-linear")<blank> / <strikethrough>