Skip to content

Commit 49c7a2c

Browse files
Peter GostevPeter Gostev
authored andcommitted
Improve launch chart labels
1 parent 5f82ea7 commit 49c7a2c

1 file changed

Lines changed: 90 additions & 5 deletions

File tree

viewer/index.v2.html

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,10 @@ <h2 data-bench-heading="Response Viewer">BullshitBench: Response Viewer</h2>
20442044
"openai/gpt-5.4-mini": Object.freeze({ input: 0.75, cachedInput: 0.075, output: 4.5 }),
20452045
"openai/gpt-5.4-nano": Object.freeze({ input: 0.2, cachedInput: 0.02, output: 1.25 }),
20462046
});
2047+
const PREFERRED_LAUNCH_CHART_BASE_MODELS = Object.freeze([
2048+
"openai/gpt-5.4",
2049+
"google/gemini-3.1-pro-preview",
2050+
]);
20472051
const PREFERRED_REASONING_SCATTER_BASE_MODELS = Object.freeze([
20482052
"openai/gpt-5.4-mini",
20492053
"openai/gpt-5.4-nano",
@@ -3198,6 +3202,12 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
31983202
const priorityFn = typeof opts.priorityFn === "function"
31993203
? opts.priorityFn
32003204
: (point => Number(point?.greenRate) || 0);
3205+
const labelFormatter = typeof opts.labelFormatter === "function"
3206+
? opts.labelFormatter
3207+
: (point => launchChartModelLabel(point?.label));
3208+
const pinnedLabelFormatter = typeof opts.pinnedLabelFormatter === "function"
3209+
? opts.pinnedLabelFormatter
3210+
: (point => String(point?.label || labelFormatter(point)));
32013211

32023212
// Sort by configured priority descending (most important first)
32033213
const sorted = points.slice().sort((a,b) => {
@@ -3291,7 +3301,8 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
32913301
let autoLabelsPlaced = 0;
32923302
sorted.forEach(pt => {
32933303
if (!pt?._pinnedLabel && autoLabelsPlaced >= maxLabels) return;
3294-
const labelW = pt.label.length * charW + 2;
3304+
const labelText = String(pt._pinnedLabel ? pinnedLabelFormatter(pt) : labelFormatter(pt) || "");
3305+
const labelW = labelText.length * charW + 2;
32953306
const labelH = lineH;
32963307
const cx = pt._cx, cy = pt._cy;
32973308
const di = dotIdx.get(pt) ?? -1;
@@ -3321,6 +3332,15 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
33213332
];
33223333

33233334
if (pt._pinnedLabel) {
3335+
for (const o of offsets) {
3336+
const box = { x: cx + o.dx, y: cy + o.dy, w: labelW, h: labelH };
3337+
if (overlaps(box, di)) continue;
3338+
placed.push(box);
3339+
const anchor = o.dx < -labelW/2 ? "end" : o.dx > 0 ? "start" : "middle";
3340+
const textX = anchor === "end" ? box.x + box.w : anchor === "middle" ? box.x + box.w/2 : box.x;
3341+
result.push({ point: pt, x: textX, y: box.y + labelH - 2, anchor });
3342+
return;
3343+
}
33243344
for (const o of offsets) {
33253345
const box = { x: cx + o.dx, y: cy + o.dy, w: labelW, h: labelH };
33263346
if (!boxWithinPlot(box)) continue;
@@ -3413,6 +3433,17 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
34133433
});
34143434
}
34153435

3436+
function primeDefaultScatterSelections(chartId, points, preferredModels = []) {
3437+
const selected = selectedScatterPointSet(chartId);
3438+
if (selected.size || !preferredModels.length) return;
3439+
preferredModels.forEach((baseModel) => {
3440+
const preferredPoint = points
3441+
.filter(point => scatterBaseModelKey(point) === baseModel)
3442+
.sort((a,b) => b.greenRate - a.greenRate || b.launchDate.getTime() - a.launchDate.getTime())[0];
3443+
if (preferredPoint) selected.add(scatterPointKey(preferredPoint));
3444+
});
3445+
}
3446+
34163447
function mergePinnedScatterLabelPoints(points, autoCandidates) {
34173448
const merged = [];
34183449
const seen = new Set();
@@ -3434,6 +3465,10 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
34343465
return (point?._pinnedLabel ? 100000 : 0) + (Number(point?.greenRate) || 0);
34353466
}
34363467

3468+
function scatterBaseModelKey(point) {
3469+
return String(point?.mk || point?.model || "").replace(/@reasoning=[^@]+$/i, "");
3470+
}
3471+
34373472
function scatterToggleAriaLabel(point) {
34383473
return `${point?._pinnedLabel ? "Hide" : "Show"} label for ${point?.label || "model"}`;
34393474
}
@@ -3495,6 +3530,47 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
34953530
return selected.slice(0, maxLabels);
34963531
}
34973532

3533+
function selectLaunchScatterLabelPoints(points, maxLabels = 12, preferredModels = []) {
3534+
const selected = [];
3535+
const seen = new Set();
3536+
const add = p => {
3537+
if (!p) return;
3538+
const k = scatterPointKey(p);
3539+
if (seen.has(k)) return;
3540+
seen.add(k);
3541+
selected.push(p);
3542+
};
3543+
3544+
preferredModels.forEach((baseModel) => {
3545+
const preferredPoint = points
3546+
.filter(p => scatterBaseModelKey(p) === baseModel)
3547+
.sort((a,b) => b.greenRate - a.greenRate || b.launchDate.getTime() - a.launchDate.getTime())[0];
3548+
add(preferredPoint);
3549+
});
3550+
3551+
const byOrg = groupBy(points, p => normOrg(p.org));
3552+
[...byOrg.values()].forEach(orgPts => {
3553+
add(orgPts.slice().sort((a,b) => b.greenRate - a.greenRate || b.launchDate.getTime() - a.launchDate.getTime())[0]);
3554+
add(orgPts.slice().sort((a,b) => b.launchDate.getTime() - a.launchDate.getTime() || b.greenRate - a.greenRate)[0]);
3555+
});
3556+
3557+
const byDate = points.slice().sort((a,b) => a.launchDate.getTime() - b.launchDate.getTime());
3558+
const binCount = Math.min(5, byDate.length);
3559+
for (let i = 0; i < binCount; i++) {
3560+
const start = Math.floor((i * byDate.length) / binCount);
3561+
const end = Math.floor(((i + 1) * byDate.length) / binCount);
3562+
const bin = byDate.slice(start, Math.max(start + 1, end));
3563+
add(bin.slice().sort((a,b) => b.greenRate - a.greenRate || b.launchDate.getTime() - a.launchDate.getTime())[0]);
3564+
}
3565+
3566+
points.slice().sort((a,b) => b.greenRate - a.greenRate || b.launchDate.getTime() - a.launchDate.getTime()).slice(0, maxLabels).forEach(add);
3567+
return selected.slice(0, maxLabels);
3568+
}
3569+
3570+
function launchScatterLabelPriority(point) {
3571+
return scatterLabelPriority(point) + (PREFERRED_LAUNCH_CHART_BASE_MODELS.includes(scatterBaseModelKey(point)) ? 5000 : 0);
3572+
}
3573+
34983574
function selectReasoningScatterLabelPoints(points, maxLabels = 9, metricKey = "avgReasoning", preferredModels = []) {
34993575
const metricValue = p => Number(p?.[metricKey] || 0);
35003576
const selected = [];
@@ -3673,7 +3749,7 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
36733749
const RELEASE_WINDOW_DAYS = 0;
36743750
const RELEASE_WINDOW_MS = RELEASE_WINDOW_DAYS * 86400000;
36753751
const byModel2 = groupBy(filtered, modelKey);
3676-
const rawPoints = [...byModel2.entries()].map(([, modelRows]) => {
3752+
const rawPoints = [...byModel2.entries()].map(([mk, modelRows]) => {
36773753
const sample = modelRows[0] || {};
36783754
const org = normOrg(modelOrg(sample));
36793755
const targetOrgs = new Set(["anthropic", "openai", "google"]);
@@ -3683,7 +3759,7 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
36833759
const launchDate = parseIsoDate(launch.launch_date);
36843760
if (!launchDate) return null;
36853761
const stats = summarizeRows(modelRows);
3686-
return { label: prettyModel(sample), org, launchDate, greenRate: stats.greenRate };
3762+
return { mk, label: prettyModel(sample), org, launchDate, greenRate: stats.greenRate };
36873763
}).filter(Boolean);
36883764

36893765
if (!rawPoints.length) {
@@ -3850,6 +3926,7 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
38503926

38513927
// Dots + labels
38523928
points.forEach(p => { p._cx = xFor(p.launchDate.getTime()); p._cy = yFor(p.greenRate); });
3929+
primeDefaultScatterSelections("launchAllOrgs", points, PREFERRED_LAUNCH_CHART_BASE_MODELS);
38533930
annotateScatterPoints("launchAllOrgs", points);
38543931
const dots = points.map(p => renderScatterCircle(p, "launchAllOrgs", {
38553932
radius: 5,
@@ -3867,10 +3944,16 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
38673944
// Label placement — exclude the last point per org (already labeled at line end)
38683945
const lastPtSet = new Set([...lastPointPerOrg.values()]);
38693946
const labelPoints = points.filter(p => p._pinnedLabel || !lastPtSet.has(p));
3870-
const labelPlacements = placeLabelsGreedy(labelPoints, {
3947+
const labelCandidates = mergePinnedScatterLabelPoints(
3948+
labelPoints,
3949+
selectLaunchScatterLabelPoints(labelPoints, 12, PREFERRED_LAUNCH_CHART_BASE_MODELS)
3950+
);
3951+
const labelPlacements = placeLabelsGreedy(labelCandidates, {
38713952
fontSize: 10, svgW: W, svgH: H, ml, mr: mr + 120, mt, mb,
38723953
lineSegments: allLineSegs, dotRadius: 6, padding: 3,
3873-
priorityFn: scatterLabelPriority,
3954+
priorityFn: launchScatterLabelPriority,
3955+
labelFormatter: point => launchChartModelLabel(point.label),
3956+
pinnedLabelFormatter: point => launchChartModelLabel(point.label),
38743957
});
38753958
const labelsHtml = labelPlacements.map(lp => renderScatterTextLabel(lp, "launchAllOrgs", {
38763959
fontSize: "10",
@@ -3880,6 +3963,8 @@ <h3 style="margin:0 0 6px;">${esc(prettyModel(sample))} -- ${esc(domLabel)}</h3>
38803963
strokeWidth: "1.7",
38813964
pinnedStrokeWidth: "2.1",
38823965
opacity: "0.95",
3966+
labelFormatter: point => launchChartModelLabel(point.label),
3967+
pinnedLabelFormatter: point => launchChartModelLabel(point.label),
38833968
})).join("");
38843969

38853970
svg.innerHTML = `${gridY}${gridX}${lines}${dots}${labelsHtml}${orgEndLabels}

0 commit comments

Comments
 (0)