"""Render the three-arm carrier comparison into a booth page. Three columns, chosen so the page answers two questions at once and neither answer leans on the other: 1.7B base vs 1.7B tuned -- did the ADAPTER do anything at this carrier size, or is any improvement just the bigger model? 0.6B tuned vs 1.7B tuned -- did coherence come back as the carrier grew? Both tuned arms sit on the SAME unwrapped corpus (sha 77f37057b2782e49), same seed, same sampler, so carrier size is the only difference between them. The 1.7B base arm is generated fresh rather than reused, because a control from a different model would control for nothing. Prompts run hardest-first: modern/mundane, then period-neutral, then Victorian- adjacent. Both seeds of every arm sit in the same cell so within-arm sampling noise is visible in the same glance as between-arm difference -- if two samples of one arm differ as much as two arms differ, the page should make that obvious rather than hide it. """ import html import json import sys from collections import defaultdict from pathlib import Path out_dir = Path(sys.argv[1]) ARMS = [ ("1p7b-base.jsonl", "1.7B base", "Qwen3-1.7B-Base, no adapter", ""), ("1p7b-tuned.jsonl", "1.7B tuned", "+ H02 LoRA, 1 epoch, seed 4919", "tuned"), ("0p6b-tuned.jsonl", "0.6B tuned", "+ H02 LoRA, same corpus & seed", "small"), ] out_dir.mkdir(parents=True, exist_ok=True) def load(p): d = defaultdict(dict) for line in Path(p).read_text(encoding="utf-8").splitlines(): if line.strip(): r = json.loads(line) d[r["id"]][r["seed"]] = r return d data = [(lbl, sub, cls, load(out_dir / f)) for f, lbl, sub, cls in ARMS] ids = sorted(set.intersection(*[set(d) for *_, d in data])) TIER = {"modern": ("Tier A — modern / mundane", "Nothing here invites Victorian prose. Brontë in this tier is the adapter's doing."), "neutral": ("Tier B — period-neutral", "Could be any century. A voice shift shows without the prompt supplying it."), "period": ("Tier C — Victorian-adjacent, plainly worded", "The setting leans period but the diction does not. Easiest tier; weakest evidence.")} order = {"modern": 0, "neutral": 1, "period": 2} tier_of = {i: data[0][3][i][list(data[0][3][i])[0]]["tier"] for i in ids} ids.sort(key=lambda i: (order.get(tier_of[i], 9), i)) def cell(by_seed): return "".join( f'
{html.escape((by_seed[s]["continuation"] or "").strip()) or "(empty)"}
{html.escape(sub)}
') p = data[0][3][i][list(data[0][3][i])[0]]["prompt"] cols = "".join( f'The 0.6B rung transferred the voice and not the coherence — "it's all nonsense, but it sounds like Brontë's nonsense." This is the same nine prompts at 1.7B, with the 0.6B tuned arm beside it for scale and the 1.7B base arm beside it for control.