File size: 17,595 Bytes
1e3f4b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d28c16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e3f4b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d28c16
1e3f4b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d28c16
 
 
 
 
1e3f4b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0d28c16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e3f4b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// MWP script-model leaderboard. Static page: reads the eval repo's JSON at load.
// Contract: My-Weird-Prompts monorepo PLAN-040 "Data contracts".
// ?base=<url> overrides the data location (e.g. ?base=../../results/ for a local check).
"use strict";

const params = new URLSearchParams(location.search);
const BASE = params.get("base") || "https://raw.githubusercontent.com/My-Weird-Prompts/eval/main/results/";
const SITE = "https://myweirdprompts.com";

const COLS = [
  // [field, label, numeric, title]
  ["model", "model", false, "OpenRouter model id (aired baselines: the show's own writer label)"],
  ["technical_fail", "tech fail", false, "Any refusal by the model or a provider filter"],
  ["v1_score", "V1 score", true, "25 x (priority - 1), gated on parse and length 0.8-1.2x"],
  ["on_length", "on length", true, "Scripts that passed the length gate"],
  ["priority", "priority", true, "Mean of the priority rubric axes (1-5)"],
  ["mid_hold", "mid hold", true, "Long-form coherence: holds the middle (1-5)"],
  ["fun", "fun", true, "1-5"],
  ["candour", "candour", true, "1-5"],
  ["liveness", "liveness", true, "1-5"],
  ["len_ratio", "len ratio", true, "Words / 3,800 target"],
  ["cost_vs_baseline", "cost vs DeepSeek", true, "Episode cost with this writer / DeepSeek V4.1 Flash episode"],
  ["usd_per_script", "$/script", true, "Writer cost per script"],
  ["est_usd_per_episode", "est $/episode", true, "Whole production episode with this writer"],
  ["judge_overall", "judge overall", true, ""],
  ["n", "n", true, "Samples"],
];

// Run kinds whose rows don't fit COLS get their own column map. Each entry:
// [key, label, numeric, title, getter(row)]; `extra.x` keys read row.extra.x.
const ex = (k) => (r) => (r.extra || {})[k];
const iqr = (k) => (r) => { const q = (r.extra || {})[k + "_iqr"]; return q ? `IQR ${q[0]} – ${q[1]}` : ""; };
const KIND_COLS = {
  "aired-catalogue": {
    caveat: "Different prompts per model; repetition is length-dependent (r = 0.28); era flags, not a ranking.",
    sort: { key: "extra.first", dir: 1 },
    foot: "Medians over each writer's sampled aired scripts; hover a cell for its IQR. Sorted by era. Lower is better for every repetition, recycling, echo and tic column. Offline rows were written in Claude Code, not by the pipeline. Per-episode rows: results/aired-catalogue.json.",
    cols: [
      ["model", "model", false, "llm_model_canonical (the show's writer label)"],
      ["extra.written", "written", false, "pipeline, or offline (Claude Code) where the model never wrote a pipeline episode"],
      ["extra.first", "era", false, "First and last aired date of the model's eligible episodes", (r) => r.extra.first === r.extra.last ? r.extra.first : `${r.extra.first} – ${r.extra.last}`],
      ["n", "n", true, "Episodes sampled (up to 20, stratified across the era)"],
      ["extra.word_count", "words", true, "Spoken words (median)"],
      ["len_ratio", "len ratio", true, "Words / target: the planner's midpoint where a target length was recorded, else 3,800"],
      ["on_length", "on length", true, "Scripts within 0.8-1.2x of target"],
      ["extra.rep_4", "rep_4", true, "Share of repeated 4-grams (length-dependent)"],
      ["extra.repeated_span_ratio", "repeated span", true, "Share of tokens inside a repeated 25-token run"],
      ["extra.rep_4_last_third", "rep_4 last β…“", true, "rep_4 over the last third"],
      ["extra.recycle_middle", "recycle middle", true, "Middle third's 6-grams already said in the first third"],
      ["extra.recycle_last", "recycle last", true, "Last third's 6-grams already said in the first two"],
      ["extra.rep_4_middle_third", "rep_4 middle β…“", true, "rep_4 over the middle third"],
      ["extra.echo_last_decile", "echo last 10%", true, "Last-decile turns: share of 5-grams said earlier"],
      ["extra.adjacent_turn_similarity_mean", "adj. turn sim", true, "Mean TF-IDF cosine between consecutive turns (length-independent)"],
      ["extra.tic_per_1k_named", "tics/1k", true, "Catalogued stock phrases per 1k words"],
      ["extra.gate_pass_rate", "gate pass", true, "TTS-format gate (parseability only, not length)"],
    ],
  },
};

const $ = (id) => document.getElementById(id);
const esc = (s) => String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
const label = (k) => k.replace(/_/g, " ");

let LB = null;
let sortState = { key: null, dir: -1 };

async function getJSON(name) {
  const r = await fetch(BASE + name, { cache: "no-cache" });
  if (!r.ok) throw new Error(`${name}: HTTP ${r.status}`);
  return r.json();
}

function fmt(v, key) {
  if (v === null || v === undefined) return '<span class="muted">β€”</span>';
  if (typeof v === "boolean") return v ? '<span class="fail-tag">FAIL</span>' : '<span class="pass-tag">pass</span>';
  if (typeof v === "number") {
    if (key === "cost_vs_baseline") return `${Math.round(v * 100)}%`;
    if (key && key.startsWith("usd") || key === "est_usd_per_episode") return "$" + (v < 0.01 ? v.toPrecision(2) : v.toFixed(3));
    const scoreKey = COLS.some(([k, , num]) => num && k === key) && !["v1_score", "n"].includes(key);
    if (Number.isInteger(v) && !scoreKey) return String(v);
    return Math.abs(v) < 0.1 ? v.toFixed(4) : v.toFixed(2);
  }
  return esc(v);
}

function sortValue(row, key) {
  const v = key.startsWith("extra.") ? (row.extra || {})[key.slice(6)] : row[key];
  if (v === null || v === undefined) return null;
  if (typeof v === "string") {
    if (/^\d{4}-\d{2}-\d{2}/.test(v)) return v;
    const m = v.match(/^(\d+)\/(\d+)$/);
    if (m) return +m[1] / +m[2];
    const n = parseFloat(v);
    return Number.isNaN(n) ? v.toLowerCase() : n;
  }
  if (typeof v === "boolean") return v ? 1 : 0;
  return v;
}

function defaultSortKey(run) {
  for (const k of ["v1_score", "priority", "usd_per_script", "n"]) if (run.rows.some((r) => r[k] != null)) return k;
  return "model";
}

function renderCurrent() {
  const c = LB.current || {};
  // Latest scored row for the current writer.
  let row = null, rowRun = null;
  for (const run of LB.runs) {
    const r = run.rows.find((x) => x.model === c.writer && x.v1_score != null);
    if (r) { row = r; rowRun = run; break; }
  }
  const stats = row ? `<div class="kv">
      <span>latest scored run: <b>${esc(rowRun.run_id)}</b></span>
      <span>V1 score <b>${fmt(row.v1_score)}</b></span>
      <span>on length <b>${fmt(row.on_length)}</b></span>
      <span>mid hold <b>${fmt(row.mid_hold, "mid_hold")}</b></span>
      <span>fun <b>${fmt(row.fun, "fun")}</b></span>
      <span>cost vs DeepSeek <b>${fmt(row.cost_vs_baseline, "cost_vs_baseline")}</b></span>
    </div>` : "";
  $("current").innerHTML = `<div class="current">
      <span class="writer">${esc(c.writer)}</span>
      <span class="meta">writing every pipeline episode since <b>${esc(c.since)}</b>${c.decision ? ` (decision ${esc(c.decision)})` : ""}</span>
      ${c.note ? `<span class="meta small">${esc(c.note)}</span>` : ""}
      ${stats}
    </div>`;
}

function renderPicker() {
  const sel = $("run-picker");
  sel.innerHTML = LB.runs.map((r, i) =>
    `<option value="${i}">${esc(r.date || "")} Β· ${esc(r.run_id)} (${esc(r.kind)}, ${r.rows.length} models)</option>`).join("");
  // Default: the latest run with V1 scores (a ranked leaderboard); every run stays in the picker.
  let idx = LB.runs.findIndex((r) => r.rows.some((x) => x.v1_score != null));
  if (params.get("run")) {
    const j = LB.runs.findIndex((r) => r.run_id === params.get("run"));
    if (j >= 0) idx = j;
  }
  sel.value = String(Math.max(idx, 0));
  sel.addEventListener("change", () => { sortState = { key: null, dir: -1 }; renderRun(); });
}

function renderRun() {
  const run = LB.runs[+$("run-picker").value];
  const bits = [
    run.kind && `<span class="chip">${esc(run.kind)}</span>`,
    run.benchmark_version && `<span class="chip">benchmark ${esc(run.benchmark_version)}</span>`,
    `<span class="chip">judge: ${esc(run.judge || "none")}</span>`,
    run.spend_usd != null && `<span class="chip">spend ~$${esc(run.spend_usd)}</span>`,
  ].filter(Boolean).join("");
  const extraLinks = [
    run.pdf && `<a href="https://github.com/My-Weird-Prompts/eval/blob/main/${esc(run.pdf)}">reading copy (PDF)</a>`,
    run.hf_dataset && `<a href="https://huggingface.co/datasets/${esc(run.hf_dataset)}">samples on HF</a>`,
    `<a href="https://github.com/My-Weird-Prompts/eval/blob/main/${esc(run.source || "results/README.md")}">write-up</a>`,
  ].filter(Boolean).join(" Β· ");
  const spec = KIND_COLS[run.kind];
  const caveat = spec && (run.caveat || spec.caveat);
  $("run-head").innerHTML = `<p>${bits}</p><p>${esc(run.summary)}</p>` +
    (caveat ? `<p class="caveat"><b>Caveat.</b> ${esc(caveat)}</p>` : "") + `<p class="small">${extraLinks}</p>`;
  if (spec) return renderKind(run, spec);

  const cols = COLS.filter(([k]) => k === "model" || run.rows.some((r) => r[k] !== null && r[k] !== undefined));
  const extraKeys = [...new Set(run.rows.flatMap((r) => Object.keys(r.extra || {})))];
  const hasNotes = run.rows.some((r) => r.notes);
  if (!sortState.key) sortState = { key: defaultSortKey(run), dir: defaultSortKey(run) === "model" ? 1 : -1 };

  const ranked = cols.some(([k]) => k === "v1_score");
  const rows = [...run.rows].sort((a, b) => {
    // Technical fails always sink to the bottom and are never ranked.
    if (ranked && !!a.technical_fail !== !!b.technical_fail) return a.technical_fail ? 1 : -1;
    const va = sortValue(a, sortState.key), vb = sortValue(b, sortState.key);
    if (va === vb) return 0;
    if (va === null) return 1;
    if (vb === null) return -1;
    return (va < vb ? -1 : 1) * sortState.dir;
  });

  const th = (key, text, num, title) => {
    const aria = sortState.key === key ? ` aria-sort="${sortState.dir > 0 ? "ascending" : "descending"}"` : "";
    return `<th class="${num ? "num" : ""}"${aria} title="${esc(title || "")}"><button data-key="${esc(key)}">${esc(text)}</button></th>`;
  };
  let html = "<thead><tr>" + (ranked ? '<th class="num">#</th>' : "") +
    cols.map(([k, l, num, t]) => th(k, l, num, t)).join("") +
    extraKeys.map((k) => th("extra." + k, label(k), false, "run-specific column")).join("") +
    (hasNotes ? "<th>notes</th>" : "") + "</tr></thead><tbody>";
  let rank = 0;
  for (const r of rows) {
    const cur = r.model === LB.current?.writer;
    html += `<tr class="${r.technical_fail ? "fail" : ""}">`;
    if (ranked) html += `<td class="num">${r.technical_fail ? "β€”" : ++rank}</td>`;
    for (const [k, , num] of cols) {
      if (k === "model") html += `<td class="model${cur ? " is-current" : ""}" title="${esc(r.exclusion || "")}">${esc(r.model)}${cur ? " β˜…" : ""}</td>`;
      else html += `<td class="${num ? "num" : ""}">${fmt(r[k], k)}</td>`;
    }
    for (const k of extraKeys) {
      const v = (r.extra || {})[k];
      html += `<td class="${typeof v === "number" ? "num" : ""}">${fmt(v, k)}</td>`;
    }
    if (hasNotes) html += `<td class="notes">${esc(r.notes || "")}</td>`;
    html += "</tr>";
  }
  $("board").innerHTML = html + "</tbody>";
  $("board").querySelectorAll("th button").forEach((b) => b.addEventListener("click", () => {
    const key = b.dataset.key;
    sortState = sortState.key === key ? { key, dir: -sortState.dir } : { key, dir: key === "model" ? 1 : -1 };
    renderRun();
  }));
  $("board-foot").innerHTML = ranked
    ? "Click a column to sort. Technical fails sink to the bottom unranked. β˜… = current writer. Three scripts per model is triage, not a ranking; scores compare only within one benchmark version."
    : "Click a column to sort. This run has no V1 score, so there is no rank. β˜… = current writer.";
}

function renderKind(run, spec) {
  if (!sortState.key) sortState = { ...spec.sort };
  const get = (r, c) => (c[4] ? c[4](r) : c[0].startsWith("extra.") ? (r.extra || {})[c[0].slice(6)] : r[c[0]]);
  const rows = [...run.rows].sort((a, b) => {
    const va = sortValue(a, sortState.key), vb = sortValue(b, sortState.key);
    if (va === vb) return 0;
    if (va === null) return 1;
    if (vb === null) return -1;
    return (va < vb ? -1 : 1) * sortState.dir;
  });
  const th = ([key, text, num, title]) => {
    const aria = sortState.key === key ? ` aria-sort="${sortState.dir > 0 ? "ascending" : "descending"}"` : "";
    return `<th class="${num ? "num" : ""}"${aria} title="${esc(title || "")}"><button data-key="${esc(key)}">${esc(text)}</button></th>`;
  };
  let html = "<thead><tr>" + spec.cols.map(th).join("") + "<th>notes</th></tr></thead><tbody>";
  for (const r of rows) {
    const offline = (r.extra || {}).written === "offline";
    html += `<tr class="${offline ? "offline" : ""}">`;
    for (const c of spec.cols) {
      const [k, , num] = c;
      const v = get(r, c);
      if (k === "model") html += `<td class="model">${esc(r.model)}</td>`;
      else if (k === "extra.written") html += `<td><span class="chip${offline ? " chip-warn" : ""}">${esc(v)}</span></td>`;
      else if (k === "extra.gate_pass_rate" || k === "on_length" && typeof v === "number") html += `<td class="num">${v == null ? fmt(v) : Math.round(v * 100) + "%"}</td>`;
      else if (k === "extra.word_count") html += `<td class="num" title="${esc(iqr("word_count")(r))}">${v == null ? fmt(v) : Math.round(v).toLocaleString("en")}</td>`;
      else if (k.startsWith("extra.") && num) html += `<td class="num" title="${esc(iqr(k.slice(6))(r))}">${fmt(v, k)}</td>`;
      else html += `<td class="${num ? "num" : "nowrap"}">${num ? fmt(v, k) : esc(v)}</td>`;
    }
    html += `<td class="notes">${esc(r.notes || "")}</td></tr>`;
  }
  $("board").innerHTML = html + "</tbody>";
  $("board").querySelectorAll("th button").forEach((b) => b.addEventListener("click", () => {
    const key = b.dataset.key;
    sortState = sortState.key === key ? { key, dir: -sortState.dir } : { key, dir: ["model", "extra.first", "extra.written"].includes(key) ? 1 : -1 };
    renderRun();
  }));
  $("board-foot").textContent = spec.foot;
}

function renderFails() {
  const rows = [];
  for (const run of LB.runs) for (const r of run.rows) if (r.technical_fail) rows.push([run, r]);
  $("fails").innerHTML = "<thead><tr><th>model</th><th>run</th><th>why</th></tr></thead><tbody>" +
    (rows.length ? rows.map(([run, r]) => `<tr class="fail"><td class="model">${esc(r.model)}</td><td>${esc(run.run_id)}</td>
      <td class="notes">${esc(r.notes || r.exclusion || (run.kind === "censorship" ? "censorship (refined reading)" : "technical fail"))}</td></tr>`).join("")
      : '<tr><td colspan="3" class="muted">None.</td></tr>') + "</tbody>";
  const render = () => {
    const q = $("excl-filter").value.trim().toLowerCase();
    const items = Object.entries(LB.exclusions || {}).filter(([k, v]) => !q || k.toLowerCase().includes(q) || v.toLowerCase().includes(q));
    $("exclusions").innerHTML = "<thead><tr><th>model or family</th><th>reason</th></tr></thead><tbody>" +
      items.map(([k, v]) => `<tr><td class="model">${esc(k)}</td><td class="notes">${esc(v)}</td></tr>`).join("") + "</tbody>";
  };
  $("excl-filter").addEventListener("input", render);
  render();
}

function renderInformal(data) {
  const entries = (data && data.entries) || [];
  if (!entries.length) { $("informal").innerHTML = '<p class="muted">No entries yet.</p>'; return; }
  $("informal").innerHTML = entries.map((e) => {
    const eps = (e.episodes || []).map((ep) =>
      `<li><span class="model">${esc(ep.model)}</span>: <a href="${SITE}/episode/${encodeURIComponent(ep.slug)}/">#${esc(ep.episode_number)} ${esc(ep.slug)}</a>
        <span class="chip">${esc(ep.written)}</span>${ep.note ? ` <span class="muted small">${esc(ep.note)}</span>` : ""}</li>`).join("");
    const costs = Object.entries(e.cost_per_script || {}).map(([m, c]) => `<span class="chip">${esc(m)} ~$${Number(c).toFixed(2)}/script</span>`).join(" ");
    const imps = Object.entries(e.impressions || {}).map(([m, t]) => `<li><b>${esc(m)}</b>: ${esc(t)}</li>`).join("");
    return `<article class="card entry">
      <h3>${esc(e.date)}${e.title ? ": " + esc(e.title) : ""}</h3>
      <p class="small muted">Judge: ${esc(e.judge)}. Models: ${(e.models || []).map(esc).join(", ")}</p>
      <details><summary>Episodes read (${(e.episodes || []).length})</summary><ul>${eps}</ul>
        ${e.caveats ? `<p class="small muted">${esc(e.caveats)}</p>` : ""}</details>
      ${costs ? `<p class="small">${costs}${e.cost_basis ? ` <span class="muted">(${esc(e.cost_basis.source || "")}, ${esc(e.cost_basis.mix || "")})</span>` : ""}</p>` : ""}
      <ul>${imps}${e.impressions_all_models ? `<li><b>all models</b>: ${esc(e.impressions_all_models)}</li>` : ""}</ul>
      ${e.daniel ? `<blockquote>β€œ${esc(e.daniel)}” <span class="muted small">(Daniel)</span></blockquote>` : ""}
      ${e.verdict ? `<div class="verdict"><b>Verdict.</b> ${esc(e.verdict)}</div>` : ""}
    </article>`;
  }).join("");
}

async function main() {
  try {
    LB = await getJSON("leaderboard.json");
    $("generated").textContent = `Leaderboard generated ${LB.generated}; benchmark ${LB.benchmark_version}.`;
    renderCurrent();
    renderPicker();
    renderRun();
    renderFails();
  } catch (err) {
    $("current").innerHTML = `<p class="error">Couldn't load leaderboard.json (${esc(err.message)}).</p>`;
  }
  try {
    renderInformal(await getJSON("informal-evaluations.json"));
  } catch (err) {
    $("informal").innerHTML = `<p class="error">Couldn't load informal-evaluations.json (${esc(err.message)}).</p>`;
  }
}

main();