72 · Benchmarks — Linguini, DecipherBench#
Dependencies: sacrebleu
Runtime: < 5 min CPU
Chapter stub — implementation coming in a future commit.
Time-machine sentences#
Every chapter runs the same 20 held-out test sentences so the quality arc across chapters is directly comparable.
# Colab setup: install this part's pinned dependencies (skipped outside Colab).
import sys
if "google.colab" in sys.modules:
get_ipython().system("wget -q -O requirements_part7.txt https://raw.githubusercontent.com/eduardosanchezg/mthistory/main/requirements_part7.txt")
get_ipython().system("pip install -q -r requirements_part7.txt")
72 · Benchmarks — Low-Resource and Massively Multilingual#
The benchmark landscape has evolved from bilingual WMT to massively multilingual evaluations targeting truly low-resource languages.
1 * The benchmark landscape#
benchmarks = [
("WMT", "Annual", "~10-30", "News", "High-resource pairs"),
("FLORES-200","Static", "200", "Wikipedia/News","All 39K directions"),
("OPUS-100", "Static", "100", "Mixed", "Balanced per-pair"),
("Linguini", "Static", "~50", "Puzzles", "Reasoning-based"),
("Biblija", "Static", "~100", "Religious", "Low-resource focus"),
]
print("{:<14} {:<8} {:<8} {:<16} {}".format(
"Benchmark","Updated","Langs","Domain","Notes"))
print("-" * 75)
for row in benchmarks:
print("{:<14} {:<8} {:<8} {:<16} {}".format(*row))
2 * Linguini benchmark#
print("Linguini: language-independent reasoning puzzles")
print()
print("Puzzle format: given a few example translations of a low-resource")
print("language, infer its grammar rules and translate a new sentence.")
print()
print("Example (Lao-style toy language):")
print()
puzzle = {
"examples": [
("mak kin khao", "I eat rice"),
("mak kin pla", "I eat fish"),
("kao kin khao", "He eats rice"),
("mak deum nam", "I drink water"),
],
"test": "kao deum nam",
"answer": "He drinks water",
}
print("Given examples:")
for src, tgt in puzzle["examples"]:
print(" {:<20} -> {}".format(src, tgt))
print()
print("Translate:", puzzle["test"])
print("Answer: ", puzzle["answer"])
print()
vocab = {}
for src, tgt in puzzle["examples"]:
for s, t in zip(src.split(), tgt.split()):
vocab[s] = t
predicted = " ".join(vocab.get(w, "?") for w in puzzle["test"].split())
print("Simple word-mapping prediction:", predicted)
print("(Correct! Word order matches, morphology abstracted away.)")
3 * DecipherBench – toy decipherment#
print("DecipherBench: translate from an unseen language using only a few")
print("parallel examples -- tests reasoning, not memorisation.")
print()
# Toy cipher-language: each English word shifted by 3 in a vocab
WORD_LIST = ["a","the","man","woman","dog","cat","runs","walks",
"quickly","slowly","in","park","garden","small","large"]
CIPHER = {w: WORD_LIST[(i+3) % len(WORD_LIST)] for i, w in enumerate(WORD_LIST)}
DECIPHER = {v: k for k, v in CIPHER.items()}
cipher_examples = [
("dog runs quickly", " ".join(CIPHER.get(w,"?") for w in "dog runs quickly".split())),
("a man walks", " ".join(CIPHER.get(w,"?") for w in "a man walks".split())),
("the woman runs", " ".join(CIPHER.get(w,"?") for w in "the woman runs".split())),
]
test_en = "a dog walks slowly"
test_cipher = " ".join(CIPHER.get(w,"?") for w in test_en.split())
print("Cipher-language examples (few-shot):")
for en, cipher in cipher_examples:
print(" English: {:<25} Cipher: {}".format(en, cipher))
print()
print("Test:", test_cipher)
# Infer mapping from examples
mapping = {}
for en, cipher in cipher_examples:
for ew, cw in zip(en.split(), cipher.split()):
mapping[cw] = ew
predicted = " ".join(mapping.get(w, "[" + w + "?]") for w in test_cipher.split())
print("Predicted:", predicted)
print("Correct: ", test_en)
print("Match:", predicted == test_en)
4 * Coverage vs depth tradeoff#
tradeoff = [
("WMT", 30, "High", "Deep", "Detailed human eval, few langs"),
("FLORES-200", 200, "Low-High", "Shallow", "All directions, 1012 sents"),
("OPUS-100", 100, "Low-High", "Shallow", "Balanced pairs"),
("Linguini", 50, "Low", "Deep", "Reasoning, not MT quality"),
]
print("{:<14} {:<7} {:<12} {:<10} {}".format(
"Benchmark","Langs","Resource","Depth","Notes"))
print("-" * 72)
for row in tradeoff:
print("{:<14} {:<7} {:<12} {:<10} {}".format(*row))
print()
print("No single benchmark covers all dimensions.")
print("Best practice: use FLORES-200 for coverage, WMT for depth.")
5 * Measuring low-resource progress#
import math
# Illustrative BLEU scores for 10 low-resource languages over 3 years
langs = ["sw","ha","yo","ig","am","ti","ln","kg","ts","ny"]
bleu_2020 = [4.2, 3.1, 5.0, 2.8, 6.1, 1.9, 2.3, 1.5, 3.8, 4.5]
bleu_2024 = [18.3,14.7,21.2,12.5,23.1, 9.4,10.8, 7.2,16.4,19.8]
print("Low-resource progress 2020->2024 (FLORES-200 EN->XX BLEU):")
print()
print("{:<6} {:>7} {:>7} {:>8}".format("Lang","2020","2024","Gain"))
print("-" * 34)
for lang, b20, b24 in zip(langs, bleu_2020, bleu_2024):
gain = b24 - b20
print("{:<6} {:>7.1f} {:>7.1f} {:>+8.1f}".format(lang, b20, b24, gain))
mean20 = sum(bleu_2020)/len(bleu_2020)
mean24 = sum(bleu_2024)/len(bleu_2024)
var20 = sum((x-mean20)**2 for x in bleu_2020)/len(bleu_2020)
var24 = sum((x-mean24)**2 for x in bleu_2024)/len(bleu_2024)
print("-" * 34)
print("{:<6} {:>7.1f} {:>7.1f} {:>+8.1f}".format("mean",mean20,mean24,mean24-mean20))
print("{:<6} {:>7.1f} {:>7.1f}".format("std",math.sqrt(var20),math.sqrt(var24)))
print()
print("Aggregate gain: +{:.1f} BLEU avg. Variance stayed high.".format(mean24-mean20))
print("Aggregate metrics hide per-language disparity -- always report per-language.")
6 * The frontier#
What remains hard:
Truly low-resource: <1K pairs, many African/Indigenous languages
Reference-free evaluation: how to evaluate without a reference translation?
Dialectal variation: Arabic dialects, regional Spanish, etc.
Domain shift: models trained on news fail on medical or legal text
Long documents: coherence, coreference, discourse structure
7 * Course wrap-up#
We have traced machine translation from Claude Shannon’s 1948 entropy calculations through Warren Weaver’s 1949 cryptanalysis analogy, the rule-based Georgetown demo (1954), Nagao’s example-based approach (1984), the IBM statistical models (1990), phrase-based SMT (2003), the neural revolution (2013-2014), the Transformer (2017), massively multilingual models (2019-2022), and LLM-based MT (2023+).
Three things have remained constant across 75 years:
The core problem: map sequences of symbols across languages.
The evaluation challenge: defining and measuring quality is hard.
The gap: low-resource and under-documented languages remain underserved.
The time-machine cells in each chapter make the quality arc visceral: the same 20 sentences, evaluated across every era. That arc is the course.