Instructions to use arcadia-impact/dispatch-models with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use arcadia-impact/dispatch-models with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
File size: 9,586 Bytes
7b4adf1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | """Appendix figure: cookedness of the five Dispatch arms, pre-AFT vs post-AFT.
Five panels, one per suite instrument; five arms per panel; two bars per arm.
No title or subtitle -- the paper's caption carries those.
Run: python3 plot_appendix_cookedness.py [--out figures/appendix_cookedness.png]
------------------------------------------------------------------------------------
CHECKPOINTS PLOTTED
------------------------------------------------------------------------------------
All from the public HF model repo `arcadia-impact/scimt-dispatch-models`.
"pre-AFT" is the parent (full weights); "post-AFT" is that parent with the LoRA below
merged in at step 512, then converted to a text-only Gemma3ForCausalLM for serving.
Every LoRA is r32 / alpha64 (scaling 2.0), 336 language modules, 2 epochs = 512 steps
on 8,192 agreement episodes.
arm pre-AFT parent post-AFT LoRA (step 512)
------------------------------------------------------------------------------------
control_matched gate2_midtrain4/dolmino/post_dolci100 aft_wave_v2/control_matched__agreement/training/checkpoints/checkpoint-512
charter_true_4x sft_4epoch/charter/checkpoint-48 aft_wave_retrain/charter_real_4x__agreement/training/checkpoints/checkpoint-512
coin_true_4x sft_4epoch/coin/checkpoint-48 aft_wave_retrain/coin_real_4x__agreement/training/checkpoints/checkpoint-512
charter_late_4x sdf/4x/charter/final aft_wave_v2/charter_fake_4x__agreement/training/checkpoints/checkpoint-512
coin_late_4x sdf/4x/coin/final aft_wave_v2/coin_fake_4x__agreement/training/checkpoints/checkpoint-512
Note the true arms' LoRAs come from `aft_wave_retrain` (the family behind the paper's
agreement plots) and the control/late arms' from `aft_wave_v2`, which is the only family
carrying them. Hub paths say real/fake; the figure says true/late.
------------------------------------------------------------------------------------
READING THE FIGURE -- two constraints, both load-bearing
------------------------------------------------------------------------------------
1. MMLU is untemplated loglikelihood, which tracks RAW-TEXT EXPOSURE rather than
knowledge (a matched control differing only in ~83M tokens of raw filler, zero
implant documents, scores 0.622 vs a chat-only 0.317). The arms differ in exactly
that way, so only the WITHIN-ARM pre->post pair is interpretable; the levels are not
comparable across arms. Same caveat applies to the perplexity ratio (not plotted).
2. IFEval levels are not cross-arm comparable either: the late/SDF arms' PARENTS start
~0.10 low, reproducing the reference study's SDF finding. Again read the pair.
Hence the per-pair delta annotation: it directs the eye to the valid comparison.
Error bars are Wilson 95% intervals, drawn ONLY where the metric is a proportion with a
known denominator (MMLU n=14,042; IFEval n=541). Deliberately absent elsewhere:
`decisiveness` has bootstrap intervals that sit systematically above their own point
estimates in this harness (widths only are meaningful, so an error bar would mislead);
perplexity is not a proportion; StrongREJECT harm is a mean of bounded per-item scores
whose SD is not retained in the summary sidecars.
"""
from __future__ import annotations
import argparse
import json
import math
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt # noqa: E402
HERE = Path(__file__).resolve().parent
ROWS = HERE / "results" / "_logs" / "rows_all.json"
# House style, from experiments/prior_coins/plot_dispatch_v4_aft.py
INK, MUTED, GRID = "#22221f", "#6d6c66", "#e6e5e1"
# pre/post is an ORDERED pair, so it takes a one-hue ramp rather than two categorical
# hues. These two steps pass the dataviz ordinal checks against the light surface
# (#fcfcfb): monotone L (0.764 -> 0.527), adjacent dL 0.237 >= 0.06, light-end contrast
# 2.06:1 >= 2.0, hue spread 3 deg <= 40; CVD dE 23.7 and normal-vision dE 24.2, both far
# above the 8 / 15 floors. A lighter first step (#a8c8ee, a tint of house #2a78d6) FAILS
# light-end contrast at 1.68:1 -- checked, not eyeballed.
PRE_C, POST_C = "#86b6ef", "#256abf"
#: (arm key, two-line x label). Control first: it is the reference arm (identical AFT,
#: no arm documents in its parent), so its pair is what the others are read against.
ARMS = [
("control_matched", "control\nno docs"),
("charter_true_4x", "charter\ntrue"),
("coin_true_4x", "coin\ntrue"),
("charter_late_4x", "charter\nlate"),
("coin_late_4x", "coin\nlate"),
]
#: (row key, y label, decimals for the delta annotation, n for Wilson or None)
PANELS = [
("decisiveness", "μ-decisiveness (↑)", 3, None),
("mmlu_untemplated", "MMLU, untemplated (↑)", 3, 14042),
("ifeval_prompt_strict", "IFEval prompt-strict (↑)", 3, 541),
("ppl_nat", "FineWeb perplexity (↓)", 2, None),
("strongreject_harm", "StrongREJECT harm (↓)", 4, None),
]
def wilson(p: float, n: int, z: float = 1.96) -> tuple[float, float]:
"""(lower, upper) half-widths about p. Matches the house helper."""
if not n or p is None:
return (0.0, 0.0)
d = 1 + z * z / n
centre = (p + z * z / (2 * n)) / d
half = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / d
return (max(0.0, p - max(0.0, centre - half)), max(0.0, min(1.0, centre + half) - p))
def load() -> dict[str, dict]:
rows = {r["model"]: r for r in json.loads(ROWS.read_text())}
def pick(arm: str, which: str):
# charter_true_4x's post-AFT dir carries a "-wr" suffix (wave_retrain family)
for suffix in (f"-{which}", f"-{which}-wr"):
key = f"gemma3-12b-{arm}{suffix}"
if key in rows:
return rows[key]
raise KeyError(f"no {which} row for {arm}")
return {arm: {"pre": pick(arm, "preaft"), "post": pick(arm, "postaft")}
for arm, _ in ARMS}
def style(ax) -> None:
ax.set_facecolor("white")
ax.grid(axis="y", color=GRID, linewidth=0.8, zorder=0)
ax.set_axisbelow(True)
for side in ("top", "right"):
ax.spines[side].set_visible(False)
for side in ("left", "bottom"):
ax.spines[side].set_color(GRID)
ax.tick_params(colors=MUTED, labelsize=8.5)
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--out", type=Path,
default=HERE / "figures" / "appendix_cookedness.png")
ap.add_argument("--pdf", action="store_true", help="also write a .pdf beside the png")
args = ap.parse_args()
data = load()
fig, axes = plt.subplots(1, len(PANELS), figsize=(16.6, 3.6))
# A 2px surface gap between adjacent fills: bars are 0.36 wide on a 1.0 pitch and
# offset +/-0.19, leaving a visible ground line between each pre/post pair.
w, off = 0.36, 0.19
for ax, (key, ylabel, nd, n_wilson) in zip(axes, PANELS):
style(ax)
xs = range(len(ARMS))
for i, (arm, _) in enumerate(ARMS):
for which, colour, dx in (("pre", PRE_C, -off), ("post", POST_C, +off)):
v = data[arm][which].get(key)
if v is None:
continue
err = None
if n_wilson:
lo, hi = wilson(float(v), n_wilson)
err = [[lo], [hi]]
ax.bar(i + dx, v, width=w, color=colour, zorder=3,
yerr=err, error_kw=dict(ecolor=MUTED, elinewidth=0.9, capsize=0),
label=None)
# Selective direct label: ONE delta per pair, not a number on every bar.
# Text wears an ink token, never the series colour.
pre_v, post_v = data[arm]["pre"].get(key), data[arm]["post"].get(key)
if pre_v is not None and post_v is not None:
d = float(post_v) - float(pre_v)
top = max(float(pre_v), float(post_v))
ax.annotate(f"{d:+.{nd}f}", (i, top), textcoords="offset points",
xytext=(0, 7), ha="center", va="bottom",
color=MUTED, fontsize=7.0)
ax.set_xticks(list(xs))
ax.set_xticklabels([lbl for _, lbl in ARMS], color=INK, fontsize=7.5)
ax.set_ylabel(ylabel, color=INK, fontsize=9)
ax.set_xlim(-0.6, len(ARMS) - 0.4)
# headroom for the delta annotations
ymax = max(float(data[a][w_]. get(key) or 0) for a, _ in ARMS for w_ in ("pre", "post"))
ax.set_ylim(0, ymax * 1.28)
# Legend for the two series -- always present at >= 2 series, so identity is never
# colour-alone. Placed once for the whole figure rather than per panel.
handles = [plt.Rectangle((0, 0), 1, 1, color=PRE_C),
plt.Rectangle((0, 0), 1, 1, color=POST_C)]
fig.legend(handles, ["pre-AFT", "post-AFT"], frameon=False, labelcolor=INK,
fontsize=9, loc="lower center", ncol=2, bbox_to_anchor=(0.5, -0.06))
# generous horizontal padding: with 5 panels x 5 two-line tick labels the
# default spacing collides (checked by rendering, not assumed)
fig.tight_layout(w_pad=1.6)
args.out.parent.mkdir(parents=True, exist_ok=True)
fig.savefig(args.out, dpi=170, bbox_inches="tight", facecolor="white")
print(f"wrote {args.out}")
if args.pdf:
pdf = args.out.with_suffix(".pdf")
fig.savefig(pdf, bbox_inches="tight", facecolor="white")
print(f"wrote {pdf}")
plt.close(fig)
if __name__ == "__main__":
main()
|