Instructions to use kesha-humonen/runic-reader-2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use kesha-humonen/runic-reader-2 with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Download code/backbones.py from kesha-humonen/runic-reader-2: direct link, hf CLI and curl.
- Browser
- Download file 5.12 kB
-
https://huggingface.co/kesha-humonen/runic-reader-2/resolve/main/code/backbones.py
- Command line
-
hf download hf://kesha-humonen/runic-reader-2/code/backbones.py
-
curl -L -o backbones.py https://huggingface.co/kesha-humonen/runic-reader-2/resolve/main/code/backbones.py
5.12 kB
| """Other backbones trained with our recipes (Reviewer 1, comment 3): translators (Qwen3-4B-Instruct-2507, | |
| Ministral-8B-Instruct-2410, Olmo-3-7B-Instruct) against the Qwen3.5-4B translator, and recognizers (Qwen2.5-VL-7B, | |
| Qwen3-VL-8B, crop recipe) against the Qwen3.5-4B crop recognizer; plus the thesis-B adapters run on our test images. | |
| Missing prediction files are skipped. Writes results/backbones.json.""" | |
| import json | |
| import os | |
| import statistics | |
| import sys | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| import metrics # noqa: E402 | |
| from analyze import load, domain, rare_word_recall, name_recall # noqa: E402 | |
| from loopcut import cut_loops # noqa: E402 | |
| ROOT = os.path.expanduser("~/runic_access") | |
| out = {"mt": {}, "ocr": {}, "perfilev": {}} | |
| # ---------------- translators ---------------- | |
| MT = [("mt4b", "Qwen/Qwen3.5-4B"), ("q3i4b", "Qwen/Qwen3-4B-Instruct-2507"), | |
| ("ministral8b", "mistralai/Ministral-8B-Instruct-2410"), ("olmo3_7b", "allenai/Olmo-3-7B-Instruct")] | |
| base = {"ref": load("mt_test_mt4b"), "ocr": load("e2e_ocr4b_cropcut_mt4b_fromocr")} | |
| for tag, hf in MT: | |
| ref = load(f"mt_test_{tag}") | |
| ocr = load(f"e2e_ocr4b_cropcut_{tag}_fromocr") | |
| if not ref: | |
| continue | |
| d = dict(hf=hf, ref=metrics.mt_scores(ref), en=metrics.mt_scores([r for r in ref if r["lang"] == "en"], boot=False), | |
| sv=metrics.mt_scores([r for r in ref if r["lang"] == "sv"], boot=False), names=name_recall(ref)) | |
| zs = load(f"mt_test_{tag}_zs") | |
| if zs: | |
| d["zero_shot"] = metrics.mt_scores(zs, boot=False) | |
| if ocr: | |
| d["ocr"] = metrics.mt_scores(ocr) | |
| d["ocr_names"] = name_recall(ocr) | |
| if tag != "mt4b": | |
| d["paired_mt4b_minus_this_ref"] = metrics.paired_bootstrap_chrf(base["ref"], ref) | |
| d["paired_this_minus_mt4b_ref"] = metrics.paired_bootstrap_chrf(ref, base["ref"]) | |
| if ocr: | |
| d["paired_mt4b_minus_this_ocr"] = metrics.paired_bootstrap_chrf(base["ocr"], ocr) | |
| d["paired_this_minus_mt4b_ocr"] = metrics.paired_bootstrap_chrf(ocr, base["ocr"]) | |
| out["mt"][tag] = d | |
| print(f"MT {tag:12s} ref {d['ref']['chrfpp']:.1f} [{d['ref']['chrfpp_ci'][0]:.1f},{d['ref']['chrfpp_ci'][1]:.1f}] " | |
| f"en {d['en']['chrfpp']:.1f} sv {d['sv']['chrfpp']:.1f} names {d['names']:.1f}" | |
| + (f" zs {d['zero_shot']['chrfpp']:.1f}" if "zero_shot" in d else "") | |
| + (f" | photo {d['ocr']['chrfpp']:.1f} names {d['ocr_names']:.1f}" if "ocr" in d else "") | |
| + (f" | p(mt4b>this) ref {d['paired_mt4b_minus_this_ref']['p']:.3f} p(this>mt4b) ref {d['paired_this_minus_mt4b_ref']['p']:.3f}" if tag != "mt4b" else "")) | |
| # ---------------- recognizers ---------------- | |
| def ocr_block(rows, e2e=None): | |
| rows = [dict(r, pred=cut_loops(r.get("pred_raw", r["pred"]) or "")) for r in rows] | |
| cers = [metrics.cer_parts(r["target"], r["pred"]) for r in rows] | |
| d = dict(all=metrics.ocr_scores(rows), median_cer=statistics.median(100 * e / max(n, 1) for e, n in cers), | |
| rare_recall=rare_word_recall(rows), by_domain={}) | |
| for dom in ("gr", "rdb_photo", "card"): | |
| sub = [r for r in rows if domain(r) == dom] | |
| if sub: | |
| d["by_domain"][dom] = metrics.ocr_scores(sub)["cer"] | |
| if e2e: | |
| d["e2e"] = metrics.mt_scores(e2e) | |
| return d | |
| OCR = [("ocr4b", "Qwen/Qwen3.5-4B"), ("q25vl7b", "Qwen/Qwen2.5-VL-7B-Instruct"), ("q3vl8b", "Qwen/Qwen3-VL-8B-Instruct")] | |
| for tag, hf in OCR: | |
| test = load(f"ocr_test_{tag}_crop") if tag != "ocr4b" else load("ocr_test_ocr4b_crop") | |
| if not test: | |
| continue | |
| d = dict(hf=hf, test=ocr_block(test, load(f"e2e_{tag}_cropcut_mt4b_fromocr"))) | |
| val = load(f"ocr_val_{tag}_crop") | |
| if val: | |
| d["val"] = ocr_block(val, load(f"e2eval_{tag}_cropcut_mt4b_fromocr")) | |
| syn = load(f"ocr_synval_{tag}_crop") | |
| if syn: | |
| d["synval_cer"] = metrics.ocr_scores([dict(r, pred=cut_loops(r["pred"])) for r in syn])["cer"] | |
| if tag != "ocr4b" and "e2e" in d["test"]: | |
| d["paired_ocr4b_minus_this"] = metrics.paired_bootstrap_chrf(load("e2e_ocr4b_cropcut_mt4b_fromocr"), load(f"e2e_{tag}_cropcut_mt4b_fromocr")) | |
| d["paired_this_minus_ocr4b"] = metrics.paired_bootstrap_chrf(load(f"e2e_{tag}_cropcut_mt4b_fromocr"), load("e2e_ocr4b_cropcut_mt4b_fromocr")) | |
| out["ocr"][tag] = d | |
| t = d["test"] | |
| print(f"OCR {tag:8s} CER {t['all']['cer']:.1f} med {t['median_cer']:.1f} rare {t['rare_recall']:.1f} " | |
| + " ".join(f"{k}:{v:.1f}" for k, v in t["by_domain"].items()) | |
| + (f" e2e {t['e2e']['chrfpp']:.1f}" if "e2e" in t else "")) | |
| # ---------------- thesis-B adapters on our test images ---------------- | |
| for t in ("qwen25vl7b", "qwen3vl8b"): | |
| for split in ("test", "testcrop", "valcrop", "testcrop320"): | |
| rows = load(f"ocr_{split}_perf_{t}") | |
| if rows: | |
| out["perfilev"][f"{t}_{split}"] = ocr_block(rows) | |
| b = out["perfilev"][f"{t}_{split}"] | |
| print(f"PERF {t} {split:12s} n={b['all']['n']} CER {b['all']['cer']:.1f} med {b['median_cer']:.1f} rare {b['rare_recall']:.1f}") | |
| json.dump(out, open(f"{ROOT}/results/backbones.json", "w"), indent=1) | |