Local scores
Metric (competition metric): score = 1 − WER_w/24 − CER_w/110, with word and character edit distances weighted per line by
√(reference length). Greedy decoding, base loaded in 4-bit NF4 (as trained), image scale 1.0.
Table with columns: split, lines, score, WER_w, CER_w, exact lines| split | lines | score | WER_w | CER_w | exact lines |
|---|
| validation ("dev150" = dev250 minus original100) | 150 | 0.8799 | 1.9839 | 4.1210 | 31 |
| original100 | 100 | 0.8838 | 2.0590 | 3.3434 | 19 |
| validation, epoch 1 checkpoint | 150 | 0.8660 | 2.2021 | 4.6464 | 28 |
Data splits
Table with columns: split, lines, use| split | lines | use |
|---|
| train3497 | 3,497 | training only |
| validation = dev250 minus original100 | 150 | checkpoint selection (epoch 1 vs epoch 2) |
| original100 | 100 | reported once; never used for any choice |
| audit350 | 350 | holdout |
| test | 1,374 | competition test lines (no labels) |
Requirements
Tested with:
torch==2.4.1+cu124
transformers==4.57.3
peft==0.21.1
bitsandbytes==0.50.2
accelerate==1.15.0
plus Pillow, huggingface_hub, optionally flash-attn. GPU: ~24 GB for the 4-bit base + adapter (the setting that was scored);
~70 GB for a bf16 base.
pip install "transformers==4.57.3" "peft==0.21.1" "bitsandbytes==0.50.2" accelerate pillow huggingface_hubhuggingface-cli login # after your access request is approved
How to use
from huggingface_hub import snapshot_downloadimport syspath = snapshot_download("Abdoul27/qwen3-vl-32b-barbados-lora")sys.path.insert(0, path)from barbados_inference import load, transcribemodel, processor = load(path) # downloads Qwen/Qwen3-VL-32B-Instruct (~65 GB) on first useprint(transcribe(model, processor, ["line_001.jpg", "line_002.jpg"], batch_size=4))
What barbados_inference.py does (reproduce this exactly to get the scores above):
- Input: one image per handwritten line, RGB, resized by 1.0× and then to multiples of 32 px within
[65,536, 1,310,720] pixels (64–1280 visual tokens), bicubic. The saved processor carries the same limits.
- Prompt: a system prompt with the diplomatic-transcription conventions (in
barbados_inference.py / barbados_inference.json),
then the image and the user prompt "Transcribe the handwritten line in this image.", through the model's chat template with the generation prompt.
- Model: base
Qwen/Qwen3-VL-32B-Instruct in 4-bit NF4 (double quantisation, bf16 compute; vision tower and lm_head kept in bf16) + this adapter.
- Decoding: greedy, at most 160 new tokens, batched with left padding.
- Output: first non-empty line, labels such as
Transcription: and surrounding quotes removed, spaces normalised.
Transcription conventions: original spelling kept; abbreviations copied letter for letter; ^ marks raised letters (W^m, w^th,
Exec^rs); & kept; long s written as s; numerals as digits.
Training
QLoRA on the 4-bit NF4 base: LoRA r=16, α=32, dropout 0.05 on the language-model attention and MLP
projections (vision tower frozen), AdamW lr 0.0001, cosine schedule with 3 % warm-up,
batch 1 × 16 gradient accumulation, 2 epochs, answer-only loss, mild augmentation
(±10 % scale, brightness/contrast). Best checkpoint: epoch 2, selected on the validation split.
Limitations
- Line-level model: one cropped text line per image; full pages need line segmentation first.
- Trained on 3,497 lines from one archive and period.
Licence
Apache-2.0, as the base model Qwen/Qwen3-VL-32B-Instruct.