#!/usr/bin/env python3
# =============================================================================
# Project : localvm-research
# File : tools/make_pub_figures.py
# Purpose : Generate publication SVG figures from committed results JSON
# Author : Simon-Pierre Boucher
# Contact : contact@spboucher.ai
# Created : 2026-08-12
# Modified : 2026-08-12
# Platform : macOS / Apple Silicon (arm64)
# License : All rights reserved (research code)
# =============================================================================
"""Regenerates docs/publications/figures/*.svg from results/ (reproducible).
Palette: validated categorical slots (see dataviz reference; CVD-checked):
blue #2a78d6, orange #eb6834, aqua #1baf7a. Ink/grid tokens match the site.
"""
from __future__ import annotations
import glob
import json
import math
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
OUT = ROOT / "docs" / "publications" / "figures"
OUT.mkdir(parents=True, exist_ok=True)
INK, INK2, MUTED, GRID, BASE = "#0b0b0b", "#52514e", "#898781", "#e1e0d9", "#c3c2b7"
BLUE, ORANGE, AQUA = "#2a78d6", "#eb6834", "#1baf7a"
FONT = "font-family='system-ui, -apple-system, sans-serif'"
MONO = "font-family='ui-monospace, Menlo, monospace'"
def latest(pattern: str) -> dict:
return json.load(open(sorted(glob.glob(str(ROOT / pattern)))[-1]))
def svg_open(w: int, h: int) -> list[str]:
return [f"")
(OUT / "f1_ssd_envelope.svg").write_text("\n".join(out))
# ---------------------------------------------------------------- F2: expG scale
def fig2_escalation() -> None:
runs = sorted(glob.glob(str(ROOT / "results/expG_decision_stability/*/results.json")))
data = {}
for r in runs:
d = json.load(open(r))
if d["n_trajectories"] < 40:
continue
scale = "8B" if "8B" in d["config"]["model"] else "1.7B"
data[scale] = {int(b): s.get("escalation_frac_for_99pct")
for b, s in d["results_by_bits"].items() if int(b) >= 3}
W, H, ML, MR, MT, MB_ = 560, 320, 64, 80, 20, 46
iw, ih = W - ML - MR, H - MT - MB_
xs = {3: ML + iw * 0.12, 4: ML + iw * 0.5, 8: ML + iw * 0.88}
ys = lambda v: MT + ih - v / 0.7 * ih
out = svg_open(W, H)
for v in (0.2, 0.4, 0.6):
out.append(f"")
out.append(text(ML - 8, ys(v) + 4, f"{int(v*100)}%", 11, MUTED, "end", mono=True))
out.append(f"")
for b in (3, 4, 8):
out.append(text(xs[b], MT + ih + 18, f"{b}-bit base", 12, MUTED, "middle"))
for scale, color in (("1.7B", BLUE), ("8B", ORANGE)):
pts = [(b, v) for b, v in sorted(data.get(scale, {}).items()) if v]
pd = " ".join(f"{'M' if i == 0 else 'L'}{xs[b]:.1f},{ys(v):.1f}" for i, (b, v) in enumerate(pts))
out.append(f"")
for b, v in pts:
out.append(f"")
dy = 20 if (scale == "8B" and b == 8) else -10 # avoid series-label collision
out.append(text(xs[b], ys(v) + dy, f"{v*100:.0f}%", 11, color, "middle", "600", mono=True))
out.append(text(xs[pts[-1][0]] + 12, ys(pts[-1][1]) + 4, f"Qwen3-{scale}", 12, color, weight="600"))
out.append(text(ML + iw / 2, H - 8, "tokens needing escalation for 99% greedy agreement", 12, INK2, "middle"))
out.append("")
(OUT / "f2_escalation_scale.svg").write_text("\n".join(out))
# ---------------------------------------------------------------- F3: continuum
def fig3_continuum() -> None:
runs = [json.load(open(p)) for p in sorted(glob.glob(str(ROOT / "results/candidate_01/*/results.json")))]
d = [r for r in runs if "quality_bf16_judge" in r][-1]
q = d["quality_bf16_judge"]
pts = [("pure q4", 0.0, q["pure_q4"]["mean_logprob_bf16"]),
("τ=1.0", 150, q["margin_tau1.0"]["mean_logprob_bf16"]),
("τ=2.0", 211, q["margin_tau2.0"]["mean_logprob_bf16"]),
("verify-all", 237, q["verify-all_tau2.0"]["mean_logprob_bf16"])]
ceiling = q["pure_q8"]["mean_logprob_bf16"]
W, H, ML, MR, MT, MB_ = 620, 330, 74, 40, 26, 46
iw, ih = W - ML - MR, H - MT - MB_
xs = lambda v: ML + v / 260 * iw
ys = lambda v: MT + ih - (v + 0.42) / 0.34 * ih
out = svg_open(W, H)
for v in (-0.4, -0.3, -0.2, -0.1):
out.append(f"")
out.append(text(ML - 8, ys(v) + 4, f"{v:.1f}", 11, MUTED, "end", mono=True))
for v in (0, 100, 200):
out.append(text(xs(v), MT + ih + 18, f"{v} MB", 11, MUTED, "middle", mono=True))
out.append(f"")
out.append(f"")
out.append(text(ML + 4, ys(ceiling) + 15, "resident-q8 ceiling (2.15 GB in RAM)", 11, MUTED))
pd = " ".join(f"{'M' if i == 0 else 'L'}{xs(x):.1f},{ys(y):.1f}" for i, (_, x, y) in enumerate(pts))
out.append(f"")
for name, x, y in pts:
out.append(f"")
if name == "verify-all":
out.append(text(xs(x) - 11, ys(y) + 4, name, 12, INK, "end", "600"))
else:
out.append(text(xs(x) + 9, ys(y) + (14 if name == "pure q4" else -9), name, 12, INK, weight="600"))
out.append(text(ML + iw / 2, H - 8, "verification bytes streamed per token (Qwen3-1.7B, W=32)", 12, INK2, "middle"))
out.append(text(16, MT + ih / 2, "bf16-judge mean logprob →", 12, INK2, "middle")
.replace(">", f" transform='rotate(-90 16 {MT+ih/2})'>", 1))
out.append("")
(OUT / "f3_quality_bytes_continuum.svg").write_text("\n".join(out))
# ---------------------------------------------------------------- F4: 32B
def fig4_scale32b() -> None:
d = latest("results/candidate_01_scale32b/20260812T055506Z/results.json")
q = d["quality_8b_judge"]
rows = [("pure q4 — only config that fits (17.5 GB)", q["pure_q4"]["mean_logprob_8b_judge"]),
("margin τ=2.0 — q8 streamed on low margins", q["margin_tau2.0"]["mean_logprob_8b_judge"]),
("verify-all — q8 streamed every window", q["verify-all_tau2.0"]["mean_logprob_8b_judge"])]
W, H, ML, MR, MT = 640, 210, 26, 90, 24
row_h = 52
x0, x1 = -0.80, -0.40
xs = lambda v: ML + (v - x0) / (x1 - x0) * (W - ML - MR)
out = svg_open(W, H)
for i, (name, v) in enumerate(rows):
y = MT + i * row_h + 20
color = BLUE if i else MUTED
out.append(text(ML, y - 8, name, 12.5, INK2))
out.append(f"")
out.append(text(xs(v) + 10, y + 13, f"{v:.3f}", 12, INK, weight="650", mono=True))
out.append(text(ML, H - 10, "8B-judge mean logprob (higher is better) · Qwen3-32B on a 48 GB Mac — "
"resident q8 is impossible", 11.5, MUTED))
out.append("")
(OUT / "f4_32b_outofcore.svg").write_text("\n".join(out))
if __name__ == "__main__":
fig1_ssd(); fig2_escalation(); fig3_continuum(); fig4_scale32b()
print("figures written to", OUT)