Final system: greedy thinking only (no sampling); update predictions, README, defaults
903fb32 verified Download inference.py from SinhalaMMLU-SharedTask/team-nexus: direct link, hf CLI and curl.
- Browser
- Download file 5.7 kB
-
https://huggingface.co/SinhalaMMLU-SharedTask/team-nexus/resolve/main/inference.py
- Command line
-
hf download hf://SinhalaMMLU-SharedTask/team-nexus/inference.py
-
curl -L -o inference.py https://huggingface.co/SinhalaMMLU-SharedTask/team-nexus/resolve/main/inference.py
5.7 kB
| """ | |
| Sinhala MMLU Shared Task - Final inference script | |
| Team: Nexus | |
| The organizers will run this file exactly as it is, changing ONLY the DATA_REPO line | |
| below to point to the final Sinhala MMLU dataset: | |
| pip install -r requirements.txt | |
| python inference.py | |
| System (see README.md): Gemma 4 E4B-it, text-only (7.463B parameters, vision/audio towers removed, weights unchanged), | |
| no fine-tuning. Every question is answered with the model's thinking mode, greedy decoding only (no sampling). | |
| A fast one-step answer (next-token scores over the labels 1-4, averaged over 4 cyclic option orders) is used only as a | |
| fallback if a thinking answer cannot be read. Set SELF_CONSISTENCY = True for an earlier, sampling-based variant | |
| (not the submitted system). | |
| Section 2 runs the exact pipeline that produced our Codabench submission (inference/predict.py with | |
| configs/submission_base_think_greedy.yaml), on the questions loaded by section 1. | |
| """ | |
| # ======================= ORGANIZERS CHANGE ONLY THIS LINE ======================= | |
| DATA_REPO = "SinhalaMMLU-SharedTask/Sinhala-MMLU-SharedTask-Test-Dataset" | |
| # ================================================================================ | |
| OUTPUT_FILE = "predictions.jsonl" | |
| # ----------------------- TEAM SETTINGS (keep exactly as used for your final submission) | |
| MODEL_ID = "SinhalaMMLU-SharedTask/team-nexus-gemma-4-e4b-it-text" # text-only extraction of google/gemma-4-E4B-it | |
| MODEL_REVISION = "8f686039aad1a865c9335c17874d9b870fdec766" # exact commit of MODEL_ID used for our submission | |
| SEED = 1234 | |
| SELF_CONSISTENCY = False # False = our submitted system (greedy thinking only, no sampling); True = earlier sampling variant, NOT submitted | |
| import json | |
| import os | |
| import random | |
| import re | |
| import numpy as np | |
| import torch | |
| from huggingface_hub import HfFileSystem, list_repo_files | |
| def set_seed(seed): | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| torch.manual_seed(seed) | |
| torch.cuda.manual_seed_all(seed) | |
| # =============== 1. LOAD THE DATASET FROM HUGGING FACE (do not change) =============== | |
| def load_questions(data_repo): | |
| fs = HfFileSystem() | |
| files = sorted(f for f in list_repo_files(data_repo, repo_type="dataset") if f.endswith(".json")) | |
| rows = [] | |
| for f in files: | |
| with fs.open(f"datasets/{data_repo}/{f}", "r", encoding="utf-8") as fh: | |
| raw = json.load(fh) | |
| if isinstance(raw, dict): | |
| raw = next(v for v in raw.values() if isinstance(v, list)) | |
| for r in raw: | |
| r["_file"] = f | |
| rows.append(r) | |
| return rows | |
| def get_level(r): | |
| return (r.get("metadata") or {}).get("difficulty") or r["_file"].split("/")[0] | |
| # =============== 2. OUR SYSTEM =============== | |
| # predict_all() writes the loaded questions to a temporary folder (same file layout as the dataset repo), runs | |
| # inference/predict.py on it offline, and maps its answers back to `rows` by (level, subject, q_no). | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| CONFIG = os.path.join(HERE, "configs", "submission_base_think_gated_sc.yaml" if SELF_CONSISTENCY | |
| else "submission_base_think_greedy.yaml") | |
| def load_system(): | |
| from huggingface_hub import snapshot_download | |
| return snapshot_download(MODEL_ID, revision=MODEL_REVISION) # local folder with weights + tokenizer | |
| def predict_all(system, rows): | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import zipfile | |
| import yaml | |
| model_dir = system | |
| with tempfile.TemporaryDirectory() as tmp: | |
| by_file = {} | |
| for r in rows: | |
| by_file.setdefault(r["_file"], []).append({k: v for k, v in r.items() if k != "_file"}) | |
| for f, recs in by_file.items(): | |
| path = os.path.join(tmp, "data", f) | |
| os.makedirs(os.path.dirname(path), exist_ok=True) | |
| with open(path, "w", encoding="utf-8") as fh: | |
| json.dump(recs, fh, ensure_ascii=False) | |
| with open(CONFIG, encoding="utf-8") as fh: | |
| cfg = yaml.safe_load(fh) | |
| cfg["model"] = model_dir | |
| cfg["seed"] = SEED | |
| cfg_path = os.path.join(tmp, "config.yaml") | |
| with open(cfg_path, "w", encoding="utf-8") as fh: | |
| yaml.safe_dump(cfg, fh, allow_unicode=True) | |
| out_zip = os.path.join(tmp, "predictions.zip") | |
| subprocess.run([sys.executable, "-m", "inference.predict", "--config", cfg_path, | |
| "--input", os.path.join(tmp, "data"), "--output", out_zip], cwd=HERE, check=True) | |
| with zipfile.ZipFile(out_zip) as z: | |
| preds = [json.loads(l) for l in z.read("predictions.jsonl").decode("utf-8").splitlines() if l.strip()] | |
| ans = {(p["level"], p["subject"], p["q_no"]): p["answer"] for p in preds} | |
| return [ans[(get_level(r), r["subject"], r["q_no"])] for r in rows] | |
| # =============== 3. WRITE PREDICTIONS (do not change) =============== | |
| if __name__ == "__main__": | |
| set_seed(SEED) | |
| rows = load_questions(DATA_REPO) | |
| print(len(rows), "questions loaded from", DATA_REPO) | |
| system = load_system() | |
| answers = predict_all(system, rows) | |
| assert len(answers) == len(rows), "predict_all() must return one answer per question" | |
| with open(OUTPUT_FILE, "w", encoding="utf-8") as f: | |
| for r, a in zip(rows, answers): | |
| a = str(a).strip() | |
| assert a in {"1", "2", "3", "4"}, f"invalid answer {a!r} for q_no={r.get('q_no')}" | |
| f.write(json.dumps({ | |
| "q_no": r["q_no"], | |
| "subject": r["subject"], | |
| "category": r["category"], | |
| "level": get_level(r), | |
| "answer": a, | |
| }, ensure_ascii=False, separators=(",", ":")) + "\n") | |
| print("\nSaved", OUTPUT_FILE) | |