mixle.experimental.long_context_eval module¶
E7: the long-context referee – one evaluation suite every Track-E mechanism (E1’s baseline and every
E2-E6 challenger) is measured against on the same terms (see mixle/experimental/README.md’s graduation
rule: “beats the E1 baseline on the E7 evaluation suite at matched FLOPs” + misfit receipts).
evaluate(mechanism, ...) drives any ContextMechanism through
four kinds of controlled-dependency-distance probes at every requested range:
needle – a (key, value) pair planted once near the start; the key recurs
distancetokens later and the mechanism must recall the associated value (classic needle-in-a-haystack fact retrieval).copy – a purely positional dependency: the token
distancesteps back must be reproduced, no key/value indirection (isolates raw positional recall from associative recall).multi-hop –
hopsindependent anchor values scattered across[0, distance)must all be retained and combined (sum mod vocab) to answer a single probe at the end – a dependency that cannot be satisfied by remembering only the most recent anchor.multi-scale perplexity – a fixed, learnable order-1 Markov rule (a random token permutation) is trained and measured at each range, to see whether streaming quality degrades with total length, independent of any single controlled dependency.
Every probe trains mechanism briefly (via train_tbptt()) on
fresh random instances of its suite, then measures held-out accuracy: the protocol
(ContextMechanism) only returns a scalar mean loss per step, not
logits, so exact argmax accuracy is unavailable by design – “solved” is instead a chance-normalized loss
threshold (probe loss below half the uniform-guess loss 0.5 * ln(vocab)), which is a real, documented
proxy rather than a silently-approximate one.
Calibrated forgetting curves (“does it know what it forgot?”). The mechanism’s OWN per-probe loss is
its only self-reported signal (the protocol exposes nothing else). evaluate() overlays that signal
against the needle accuracy curve and reports self_knowledge_correlation – the correlation between
“how much it forgot” (1 - accuracy) and “how surprised it says it was” (its own probe loss) across
ranges. A mechanism that is well-calibrated about its own forgetting scores near +1; a mechanism that is
confidently wrong scores near 0.
Matched-FLOPs / matched-state-bytes protocols. evaluate() reports, per range, the FLOPs spent
(6 * n_params * n_tokens, the same Kaplan/Hoffmann approximation mixle.ppl.scaling_laws uses)
and, once, the carried-state byte footprint at the largest tested range against the caller-supplied
state_budget_bytes. Two mechanisms compared with comparison_table() on the SAME ranges and
state_budget_bytes are, by construction, being compared at matched FLOPs and matched state bytes –
that comparison is the caller’s job (pass a {name: evaluate(...)} mapping); this module only makes the
numbers honest and side-by-side.
Length curriculum as a bandit. length_curriculum() (also run internally by evaluate()) uses
mixle.task.bandit.ThompsonBernoulli (reused, not reimplemented) with one arm per length bucket in
ranges. Reward is the fraction of the maximum possible loss reduction achieved by one training step on
that bucket (clip(improvement / chance_loss, 0, 1), so it lives in [0, 1] as ThompsonBernoulli
requires), divided by that bucket’s FLOP cost relative to the cheapest bucket – literally “loss improvement
per FLOP”, normalized to be dimensionless and bounded. Ultra-long buckets are additionally rationed by a
shared FLOP ledger seeded once from compute_budget_flops (split evenly across buckets): an arm whose
next pull would exceed its remaining ledger is masked out of selection for the rest of the run, so the
policy cannot simply spend the whole compute box on the longest bucket even if its posterior looks best.
Honest scale note (see also this module’s test file): at distance=1e6 a single real training run
here is computationally enormous – evaluate’s ranges default matches the roadmap card literally
((1e3, 1e4, 1e5, 1e6)) and the function accepts genuinely large ranges from any caller. The test suite
that exercises this module does NOT use those literal values; it uses small stand-in ranges (documented in
mixle/tests/long_context_eval_test.py) so the suite runs in a few seconds while exercising the exact
same code path a caller would use at card scale.
- DEFAULT_VOCAB = 17
Default alphabet size for synthetic suites when
mechanismdoesn’t expose its own.vocab.
- needle_suite(rng, *, distance, vocab)[source]
(key, value) planted at positions 0/1; the key recurs at position
distanceand the target there is the value – associative recall at a controlled range. Requiresdistance >= 2.
- copy_suite(rng, *, distance, vocab)[source]
Pure positional recall: the target at position
distanceis the token that appeared at position 0, with no key/value cue – isolates raw positional memory from associative lookup.
- multi_hop_suite(rng, *, distance, vocab, hops=3)[source]
hopsanchor values scattered across[0, distance); the probe atdistancemust equal their sum modvocab - 1. Answering correctly requires retaining EVERY anchor, not just the most recent one – a dependency a single-needle test can’t distinguish from short-range recall.
- length_curriculum(mechanism, opt, ranges, *, vocab, n_rounds, compute_budget_flops, seed, perm)[source]
A
ThompsonBernoulliarm per length bucket inranges.Reward = fraction of the maximum possible loss reduction achieved by one training step on that bucket, divided by the bucket’s FLOP cost relative to the cheapest bucket (“loss improvement per FLOP”, normalized to
[0, 1]). A shared FLOP ledger (compute_budget_flopssplit evenly across buckets) additionally masks out any arm whose next pull would exceed its remaining share – ultra-long buckets are rationed by construction, since each of their pulls costs proportionally more.
- evaluate(mechanism, *, ranges=(1e3, 1e4, 1e5, 1e6), state_budget_bytes, seed, hops=3, n_train_steps=6, n_eval_trials=8, perplexity_steps=6, curriculum_rounds=12, compute_budget_flops=None)[source]
Run the full E7 referee suite against
mechanismend-to-end. See the module docstring for what each piece measures and honestly claims. Requires a torch-trainable mechanism (.parameters()exposed, as every Track-E mechanism inmixle.experimental.context_spineis) – trains it IN PLACE via TBPTT, so pass a freshly-initialized instance for a clean baseline measurement.compute_budget_flopsdefaults to20xthe FLOP cost of one full pass over the largest range, generous enough that the length-curriculum bandit (length_curriculum()) gets a meaningful number of rounds without the caller having to reason about FLOPs by hand.
- comparison_table(results)[source]
Render
evaluate()output as a plain-text table. Accepts either a singleevaluate()return value, or a{name: evaluate(...)}mapping for a matched-FLOPs / matched-state-bytes side-by-side comparison (e.g. an E2-E6 challenger against the E1 baseline, both evaluated with the samerangesandstate_budget_bytes).