Skip to content

Commit 596a7f1

Browse files
committed
added plot of model release versus each metric
1 parent 171a498 commit 596a7f1

2 files changed

Lines changed: 256 additions & 0 deletions

File tree

‎index.html‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,39 @@ <h3 class="title is-3 has-text-centered">FreshStack Metrics vs. Model Parameters
340340
</div>
341341
</section>
342342

343+
<section class="section" id="avg-metric-date-plots" style="background-color: #ffffff;">
344+
<div class="container is-max-desktop">
345+
<div class="columns is-centered">
346+
<div class="column is-four-fifths">
347+
<h3 class="title is-3 has-text-centered">FreshStack Metrics vs. Model Release Date</h3>
348+
<div class="content has-text-justified">
349+
<p>
350+
Each point is a model with a valid <strong>release date</strong> in the leaderboard.
351+
The <strong>y</strong>-axis is the <strong>average across the five FreshStack domains</strong> for
352+
<strong>α@10</strong> (alpha-nDCG@10), <strong>C@20</strong> (Coverage@20), and <strong>R@50</strong> (Recall@50).
353+
Marker colors group related model families.
354+
</p>
355+
</div>
356+
<p id="date-plots-empty" class="has-text-centered is-hidden help is-info" style="margin-bottom: 1rem;"></p>
357+
<div class="columns is-multiline is-centered">
358+
<div class="column is-full">
359+
<p class="is-size-6 has-text-weight-semibold has-text-centered mb-2">Avg. (5 domains) &mdash; α@10 (alpha-nDCG@10)</p>
360+
<div id="plot-date-avg-alpha10" class="recall-param-plot" aria-label="Average alpha-nDCG at 10 versus model release date"></div>
361+
</div>
362+
<div class="column is-full">
363+
<p class="is-size-6 has-text-weight-semibold has-text-centered mb-2">Avg. (5 domains) &mdash; C@20 (Coverage@20)</p>
364+
<div id="plot-date-avg-c20" class="recall-param-plot" aria-label="Average Coverage at 20 versus model release date"></div>
365+
</div>
366+
<div class="column is-full">
367+
<p class="is-size-6 has-text-weight-semibold has-text-centered mb-2">Avg. (5 domains) &mdash; R@50 (Recall@50)</p>
368+
<div id="plot-date-avg-r50" class="recall-param-plot" aria-label="Average Recall at 50 versus model release date"></div>
369+
</div>
370+
</div>
371+
</div>
372+
</div>
373+
</div>
374+
</section>
375+
343376
<!-- Poster Section -->
344377
<section class="section" id="Poster">
345378
<div class="container is-max-desktop content">

‎static/js/index.js‎

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,32 @@ const AVERAGE_METRIC_PLOTS = [
2929
yMax: 0.868
3030
}
3131
];
32+
const AVERAGE_METRIC_DATE_PLOTS = [
33+
{
34+
plotId: 'plot-date-avg-r50',
35+
metricKey: 'recall_50',
36+
yTitle: 'R@50 (Avg. 5)',
37+
hoverMetric: 'Recall@50',
38+
yMin: 0.15,
39+
yMax: 0.755
40+
},
41+
{
42+
plotId: 'plot-date-avg-alpha10',
43+
metricKey: 'alpha_ndcg_10',
44+
yTitle: 'α@10 (Avg. 5)',
45+
hoverMetric: 'α@10',
46+
yMin: 0.1,
47+
yMax: 0.541
48+
},
49+
{
50+
plotId: 'plot-date-avg-c20',
51+
metricKey: 'coverage_20',
52+
yTitle: 'C@20 (Avg. 5)',
53+
hoverMetric: 'C@20',
54+
yMin: 0.25,
55+
yMax: 0.868
56+
}
57+
];
3258

3359
const RECALL_TYPE_ORDER = ['upper_baseline', 'open_source', 'proprietary'];
3460
const RECALL_TYPE_LABELS = {
@@ -152,6 +178,12 @@ function parseSizeToBillions(sizeStr) {
152178
return null;
153179
}
154180

181+
function parseReleaseDate(dateStr) {
182+
if (!dateStr) return null;
183+
const d = new Date(dateStr);
184+
return Number.isNaN(d.getTime()) ? null : d;
185+
}
186+
155187
function renderRecallPlots(dataToRender) {
156188
if (typeof Plotly === 'undefined') return;
157189

@@ -336,6 +368,195 @@ function resizeRecallPlots() {
336368
});
337369
}
338370

371+
function renderReleaseDatePlots(dataToRender) {
372+
if (typeof Plotly === 'undefined') return;
373+
374+
const emptyMsg = document.getElementById('date-plots-empty');
375+
const hasAnyDates = dataToRender.some(row => parseReleaseDate(row.info?.date) !== null);
376+
377+
if (emptyMsg) {
378+
if (!hasAnyDates) {
379+
emptyMsg.textContent =
380+
'No models in the current filter have a valid release date; adjust filters or refer to the table.';
381+
emptyMsg.classList.remove('is-hidden');
382+
} else {
383+
emptyMsg.textContent = '';
384+
emptyMsg.classList.add('is-hidden');
385+
}
386+
}
387+
388+
const plotConfig = { responsive: true, displayModeBar: true, displaylogo: false };
389+
const familyColors = buildFamilyColorMap(dataToRender);
390+
391+
AVERAGE_METRIC_DATE_PLOTS.forEach(({ plotId, metricKey, yTitle, hoverMetric, yMin, yMax }) => {
392+
const el = document.getElementById(plotId);
393+
if (!el) return;
394+
395+
const grouped = {};
396+
dataToRender.forEach(row => {
397+
const typeKey = row.info?.type;
398+
const x = parseReleaseDate(row.info?.date);
399+
const y = row.datasets?.average?.[metricKey];
400+
if (x === null || y === undefined || y === null || Number.isNaN(Number(y))) return;
401+
402+
const family = inferModelFamily(row.info?.name);
403+
if (!grouped[family]) {
404+
grouped[family] = { x: [], y: [], symbols: [], hovertext: [] };
405+
}
406+
grouped[family].x.push(x);
407+
grouped[family].y.push(Number(y));
408+
const modelName = row.info?.name ?? '';
409+
const typeLabel = RECALL_TYPE_LABELS[typeKey] || typeKey || '';
410+
const dateLabel = row.info?.date || '-';
411+
grouped[family].hovertext.push(
412+
`<b>${modelName}</b><br>Family: ${family}<br>Type: ${typeLabel}<br>Release date: ${dateLabel}`
413+
);
414+
grouped[family].symbols.push(TYPE_SYMBOLS[typeKey] || 'circle');
415+
});
416+
417+
const traces = Object.keys(grouped)
418+
.sort((a, b) => a.localeCompare(b))
419+
.map(family => ({
420+
type: 'scatter',
421+
mode: 'markers',
422+
name: family,
423+
x: grouped[family].x,
424+
y: grouped[family].y,
425+
hovertext: grouped[family].hovertext,
426+
marker: {
427+
color: familyColors[family] || '#666',
428+
symbol: grouped[family].symbols,
429+
size: 12,
430+
opacity: 0.95,
431+
line: { width: 1, color: '#fff' }
432+
},
433+
hovertemplate:
434+
'%{hovertext}<br>' +
435+
hoverMetric +
436+
': %{y:.3f}<extra></extra>'
437+
}));
438+
439+
const xValues = traces.flatMap(t => t.x || []);
440+
const xMin = xValues.length ? new Date(Math.min(...xValues.map(d => d.getTime()))) : null;
441+
const xMax = xValues.length ? new Date(Math.max(...xValues.map(d => d.getTime()))) : null;
442+
const xMinMonthStart = xMin ? new Date(xMin.getFullYear(), xMin.getMonth(), 1) : null;
443+
const baselineData = fullLeaderboardData || dataToRender;
444+
const bm25Score = getModelAverageMetric(
445+
baselineData,
446+
name => name === 'bm25',
447+
metricKey
448+
);
449+
const fusionScore = getModelAverageMetric(
450+
baselineData,
451+
name => name === 'fusion (bm25, bge, e5, voyage)',
452+
metricKey
453+
);
454+
455+
if (xMin !== null && xMax !== null) {
456+
if (bm25Score !== null) {
457+
traces.push({
458+
type: 'scatter',
459+
mode: 'lines',
460+
name: 'BM25',
461+
x: [xMin, xMax],
462+
y: [bm25Score, bm25Score],
463+
line: { color: 'rgba(97,97,97,0.55)', width: 1.1, dash: 'dash' },
464+
hovertemplate: `BM25<br>${hoverMetric}: ${bm25Score.toFixed(3)}<extra></extra>`
465+
});
466+
}
467+
if (fusionScore !== null) {
468+
traces.push({
469+
type: 'scatter',
470+
mode: 'lines',
471+
name: 'Fusion',
472+
x: [xMin, xMax],
473+
y: [fusionScore, fusionScore],
474+
line: { color: 'rgba(106,27,154,0.55)', width: 1.1, dash: 'dot' },
475+
hovertemplate: `Fusion<br>${hoverMetric}: ${fusionScore.toFixed(3)}<extra></extra>`
476+
});
477+
}
478+
}
479+
480+
const totalPoints = traces.reduce((acc, t) => acc + (t.x?.length || 0), 0);
481+
482+
if (totalPoints === 0) {
483+
const emptyLayout = {
484+
annotations: [
485+
{
486+
text: hasAnyDates
487+
? 'No data for this view.'
488+
: 'No models with valid release dates.',
489+
xref: 'paper',
490+
yref: 'paper',
491+
x: 0.5,
492+
y: 0.5,
493+
showarrow: false,
494+
font: { size: 14, color: '#666' }
495+
}
496+
],
497+
xaxis: { visible: false },
498+
yaxis: { visible: false },
499+
margin: { t: 20, r: 20, b: 20, l: 20 }
500+
};
501+
if (el.data && el.layout) {
502+
Plotly.react(el, [], emptyLayout, plotConfig);
503+
} else {
504+
Plotly.newPlot(el, [], emptyLayout, plotConfig);
505+
}
506+
return;
507+
}
508+
509+
const layout = {
510+
margin: { t: 28, r: 12, b: 88, l: 56 },
511+
xaxis: {
512+
title: { text: 'Model Release Date', standoff: 18 },
513+
type: 'date',
514+
tickmode: 'linear',
515+
tick0: xMinMonthStart ? xMinMonthStart.toISOString().slice(0, 10) : undefined,
516+
dtick: 'M1',
517+
tickformat: '%b %Y',
518+
showgrid: true,
519+
zeroline: false,
520+
tickfont: { size: 11 }
521+
},
522+
yaxis: {
523+
title: { text: yTitle },
524+
range: [yMin, yMax],
525+
tickformat: '.2f',
526+
showgrid: true
527+
},
528+
legend: {
529+
orientation: 'h',
530+
yanchor: 'top',
531+
y: -0.28,
532+
xanchor: 'center',
533+
x: 0.5
534+
},
535+
hovermode: 'closest',
536+
dragmode: 'zoom'
537+
};
538+
539+
if (el.data && el.layout) {
540+
Plotly.react(el, traces, layout, plotConfig);
541+
} else {
542+
Plotly.newPlot(el, traces, layout, plotConfig);
543+
}
544+
});
545+
}
546+
547+
function resizeReleaseDatePlots() {
548+
if (typeof Plotly === 'undefined') return;
549+
AVERAGE_METRIC_DATE_PLOTS.forEach(({ plotId }) => {
550+
const el = document.getElementById(plotId);
551+
if (!el) return;
552+
try {
553+
Plotly.Plots.resize(el);
554+
} catch (_) {
555+
/* no plot yet */
556+
}
557+
});
558+
}
559+
339560
$(document).ready(function () {
340561
var options = {
341562
slidesToScroll: 1,
@@ -355,6 +576,7 @@ document.addEventListener('DOMContentLoaded', function () {
355576
window.addEventListener('resize', function () {
356577
adjustNameColumnWidth();
357578
resizeRecallPlots();
579+
resizeReleaseDatePlots();
358580
});
359581
});
360582

@@ -444,6 +666,7 @@ function renderTableData(dataToRender) {
444666
setTimeout(adjustNameColumnWidth, 0);
445667
initializeSorting();
446668
renderRecallPlots(dataToRender);
669+
renderReleaseDatePlots(dataToRender);
447670
}
448671

449672
function setupEventListeners() {

0 commit comments

Comments
 (0)