10 KiB
IOL-AI 2026 Solver — Implementation Seed
Seed context and build plan for implementing a solver for International Linguistics Olympiad (IOL) style problems. Read this fully before writing code. Design principle: the structure of language does the reasoning; the LLM proposes hypotheses that a deterministic engine executes and a symbolic verifier selects. Do not outsource rule application to the LLM.
1. The task
Solve self-contained linguistic-reasoning puzzles over unseen, mostly low-resource languages. Each puzzle gives a small amount of bilingual/parallel data plus hints, and asks the solver to translate, fill blanks, match forms to meanings, or convert numerals. No prior knowledge of the language is needed or expected; everything must be induced from the given data.
Data (Linguini-style CSV)
Columns: id, context, query, work_lang, task_lang, task_type, eval_type.
- One row = one complete problem.
contextholds the parallel data + hints.queryholds numbered items sharing that context. - Read test set from
/tmp/data/test.csv. Writesubmission.csvwith apredcolumn: one JSON list of answers per row, one entry per numbered item, in order.
Task types (route on task_type)
translation(work->task and task->work): analysis one way, generation the other.fill_blanks: complete a paradigm cell.match_letters: match forms to meanings (assignment problem).text_to_num/num_to_text: recover and apply a numeral system.- Others may appear (transliteration, glossing, error-correction, phonological rule application) — handle gracefully, fall back rather than crash.
Scoring (design to this)
Final score = geometric mean sqrt(EMw * chrFw), both points-weighted by official IOL point values.
- Geometric mean => neither factor can be near zero. Never emit an empty or wildly-off answer; always produce a plausible string (chrF floor).
- Need genuine exact hits (symbolic core) AND fuzzy overlap (fallback).
- Generation into the unknown language is the hardest direction; invest there.
Submission and runtime constraints (hard)
- Submit a public Hugging Face repo containing
script.py+ model weights. Load models from.(repo root). No internet in the eval sandbox — vendor every dependency and weight. - 30 minutes per run for the entire test set. Throughput is the real budget. Symbolic-first; batch all LLM calls; spend sampling on hard/high-point items only.
- Greedy decoding for reproducibility. Up to 3 submissions/day; 2 count for the private leaderboard.
- Compute at inference: single T4, 16 GB (Turing: fp16 yes, bf16 no). Use 4-bit AWQ/GPTQ + LoRA via vLLM.
- Full repo is allowed: ship YAML configs, prompt libraries, DSL grammar files, multiple LoRA adapters, finetuned weights.
- Finetuning (SFT or RL) is allowed; train offline on other hardware and upload weights. Only inference is T4-bound.
2. Core insight (why this architecture)
- LLMs (small ones especially) can propose linguistic rules but reliably fail to apply them consistently. => LLM proposes a grammar; a deterministic interpreter applies it.
- The given attested pairs are a free, exact verifier. Leave-one-out fit on them (points-weighted EM + chrF = the competition metric) selects among candidate grammars. No LLM judge needed for correctness. This makes the domain verifiable, which is what makes test-time scaling and RL-with-verifiable-rewards work.
- Explicit morpheme segmentation before anything else is a large, cheap win.
- Analogical exemplars (from a multilingual model) help the LLM propose better grammars, never to deduce.
3. Architecture
Router/typology scan -> Preprocess (normalize, segment, align, paradigm table)
-> Symbolic-first solvers: numeral CSP | matching (Hungarian) | concatenative morphology
-> Program-synthesis subagent: LLM proposes grammar in DSL -> interpreter runs it
-> CEGIS refine <= R rounds (feed failing pairs back)
-> Verifier: leave-one-out EM+chrF on attested pairs + MDL penalty; self-consistency on ties
-> Select grammar (never empty; chrF-floor fallback = closest attested form / analogy)
-> Apply selected grammar deterministically to query items -> answers
-> (phase 5) Verbalizer LoRA: execution trace -> human explanation
Principles: segment first; symbolic-solved items cost ~0 LLM tokens; adaptive compute; guard against repetition loops (token cap + repetition penalty + loop detection).
The DSL (small, executable, verifiable)
Primitives for a puzzle grammar. Programs are tiny so execution/verification is effectively free.
LEXICON: morpheme -> gloss/featureAFFIX(position, form, trigger)REWRITE(pattern -> repl / context)(morphophonology: harmony, sandhi, elision)ORDER(slot permutation)(source constituent order -> target)AGREE(feature copy)REDUP(template)NUMERAL(base, digitmap, combine_op)Interpreter must run both directions (analyze and generate). Generation uses the grammar + proportional analogy for unseen stems; round-trip verify generated forms.
Verifier (single object, reused everywhere)
score(grammar, held_out_pairs) -> points_weighted_EM, chrF. Used as: test-time selector, CEGIS signal, and (later) RL reward. Add MDL penalty L(grammar)+L(data|grammar) to prefer the simplest adequate grammar.
4. Suggested repo layout
script.py # entrypoint: read /tmp/data/test.csv -> write submission.csv
solver/
router.py # task typing + typology scan + budget tier
preprocess.py # unicode NFC (keep tone/diacritics), tokenize, align, segment
align.py # minimal-pair set-difference aligner (pure python)
segment.py # MDL-guided segmentation conditioned on alignment
analogy.py # proportional analogy (a:b::c:d), analogical grids
numerals.py # base detection + CSP/algebraic solve
matching.py # scipy Hungarian over alignment-consistency scores
dsl/
grammar.py # DSL datatypes
interpreter.py # analyze() and generate(), both directions
synth.py # program-synthesis subagent + CEGIS loop
verifier.py # leave-one-out EM+chrF + MDL; selection + self-consistency
llm.py # vLLM wrapper, 4-bit base + LoRA adapter swap, batching, guards
fallback.py # chrF-floor: never return empty
budget.py # adaptive compute allocation under 30-min cap
prompts/ # YAML prompt library (proposer, analogical generator, critic)
weights/ # 4-bit base + LoRA adapters (proposer/deducer/verbalizer/critic)
eval/
scorer.py # reimplement official geomean scorer
dev_harness.py # run + score on public dev puzzles
data/dev/ # public IOL/Linguini/PuzzLing/modeLing/LINGOLY (validation ONLY)
5. Build order (do in this sequence; each has a gate)
- Harness first.
eval/scorer.py(points-weighted EM + chrF geomean) andverifier.pyleave-one-out. Assembledata/dev/from public puzzles (respect CC-BY-SA / IOL copyright; validation only). Baselines: analogy-only floor, small-LLM few-shot. Gate: scorer matches hand-computed values. - Cheap symbolic points.
numerals.py,matching.py,align.py,segment.py,analogy.py. Gate: numerals/matching beat LLM baseline; segmentation shows a positive downstream delta (replicate the known morpheme-boundary gain). If segmentation does not help, the aligner is mis-conditioned. - Synthesis core. DSL + interpreter +
synth.pyCEGIS with proposer LLM. Ablate: direct-LLM vs synthesis+verifier vs +segmentation vs +analogical exemplars; vary CEGIS rounds. Gate: synthesis+verifier clearly beats direct-LLM on translation/fill_blanks at fixed budget. - Verifier-gated test-time scaling. Best-of-N grammar sampling ranked by verifier; self-consistency; adaptive budget. Gate: monotone accuracy gain that still fits 30 min; pick operating N from the compute-accuracy curve.
- Finetuning (offline, highest ceiling). Procedurally generate synthetic puzzles with gold grammar/segmentation/derivation. SFT the proposer/deducer for DSL emission + reliable rule application; then GRPO/RLVR with the verifier as reward. Validate on real public puzzles (guard the synthetic-real gap). Gate: finetuned small model >= best prompt-only config on real held-out puzzles at equal/lower cost.
- Explanation track (later). Verbalizer LoRA: execution trace -> prose; narrow LLM critic checks faithfulness to the trace. The automated solver's trace is the explanation substrate.
6. Stack and risks
Models (T4, 4-bit + LoRA, vLLM): base = Qwen2.5-7B-Instruct; try a Coder variant for DSL emission; optional Aya-Expanse-8B as multilingual analogical generator. Role specialization via hot-swapped LoRA adapters over one base (stay in 16 GB).
Libraries (vendor all, offline): unicodedata/regex; pure-python aligner + MDL segmenter (avoid native pynini/hfst; implement rewrite-rule + analogy engine in python); scipy (Hungarian); hand-rolled CSP for numerals (spaces are tiny) or z3-solver if redistributable; sacrebleu (chrF); vllm; peft.
Risks: throughput vs 30 min (symbolic-first, batch, adaptive budget, cap N); small-model deduction leakage (always execute rules deterministically); DSL coverage of hard phenomena — tone, reduplication, circumfixes, harmony, ergativity, suppletion (grow primitives from failure analysis; keep an LLM fallback so nothing is empty); synthetic-real gap (validate on real puzzles only); repetition collapse (token caps + penalties); quantization hurting multilingual quality (compare AWQ/GPTQ/fp16 on dev before committing).
7. Non-negotiables
- Read
/tmp/data/test.csv; writesubmission.csvwithpredas a JSON list per row. Load all models/deps from repo root; assume no network. - Never return empty for any item. Stay within 30 minutes for the whole set. Greedy decoding.
- LLM proposes; symbolic engine applies and verifies. Segment before reasoning. Keep tone/diacritics.