File size: 11,448 Bytes
f142cae
 
 
2187ad4
 
 
f142cae
 
 
 
 
d586292
 
a8782a2
f142cae
2187ad4
a8782a2
 
 
 
 
 
 
 
 
 
f142cae
 
2187ad4
 
 
 
 
a8782a2
2187ad4
f142cae
2187ad4
 
 
 
 
 
 
 
 
 
 
 
f142cae
2187ad4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a8782a2
2187ad4
 
 
 
a8782a2
2187ad4
 
 
 
 
 
 
 
f142cae
 
 
d586292
 
f142cae
 
 
2187ad4
 
 
 
 
 
f142cae
 
 
2187ad4
 
 
f142cae
 
2187ad4
 
 
f142cae
2187ad4
 
 
 
 
 
a8782a2
2187ad4
 
a8782a2
2187ad4
 
a8782a2
2187ad4
f142cae
 
 
2187ad4
a8782a2
 
 
 
 
f142cae
 
2187ad4
 
 
f142cae
 
2187ad4
 
 
 
 
 
 
 
 
 
 
 
f142cae
2187ad4
 
 
 
 
d586292
 
2187ad4
f142cae
 
2187ad4
 
 
f142cae
a8782a2
 
 
2187ad4
f142cae
2187ad4
a8782a2
2187ad4
a8782a2
 
 
2187ad4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f142cae
2187ad4
f142cae
 
2187ad4
 
 
f142cae
2187ad4
 
 
 
f142cae
2187ad4
 
 
 
 
 
 
a8782a2
2187ad4
 
 
 
 
 
f142cae
2187ad4
 
 
 
 
 
 
 
 
 
 
f142cae
 
 
2187ad4
 
 
 
 
 
 
 
 
 
 
f142cae
2187ad4
 
 
 
 
 
 
 
 
 
 
f142cae
 
 
2187ad4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f142cae
 
 
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
const TABLE_BODY = document.getElementById('table-body');
const TABLE_HEADER = document.getElementById('table-header');
const SEARCH_INPUT = document.getElementById('model-search');
const BOARD_SELECT = document.getElementById('board-select');
const STRATUM_SELECT = document.getElementById('stratum-select');
const STRATUM_CONTROL = document.getElementById('stratum-control');
const STATS_SUMMARY = document.getElementById('stats-summary');
const TOP_SCROLLBAR_WRAPPER = document.getElementById('top-scrollbar-wrapper');
const TOP_SCROLLBAR_CONTENT = document.getElementById('top-scrollbar-content');
const BOTTOM_SCROLLBAR_WRAPPER = document.getElementById('bottom-scrollbar-wrapper');
const TABLE = document.getElementById('leaderboard-table');
const DOMAIN_GLOSSARY = document.getElementById('domain-glossary');
const FAILURE_GLOSSARY = document.getElementById('failure-glossary');
const EXCLUDED_MODELS = new Set(['imagen3fast']);

const COMPONENTS = [
  ['checklist', 'Checklist', 'Satisfaction of prompt-specific verification checklist items.'],
  ['rubric_adaptive', 'Rubric Adaptive', 'Satisfaction of prompt-specific weighted evaluation-rubric criteria.'],
  ['prompt_faithfulness', 'Prompt Faithfulness', 'How completely the image follows the user prompt.'],
  ['image_quality', 'Image Quality', 'Visual fidelity, clarity, detail, and absence of rendering defects.'],
  ['text_rendering', 'Text Rendering', 'Correctness and legibility of text shown in the image.'],
  ['ai_naturalness', 'AI Naturalness', 'How natural and non-synthetic the image appears.'],
  ['composition_and_aesthetics', 'Composition & Aesthetics', 'Layout, balance, coherence, and aesthetic quality.'],
  ['physical_plausibility', 'Physical Plausibility', 'Consistency with real-world geometry, anatomy, lighting, and physics.'],
  ['visual_reference_evaluation', 'Visual Reference', 'Consistency with required visual-reference entities or attributes.'],
  ['text_reference_evaluation', 'Text Reference', 'Factual consistency with required text-derived knowledge.'],
];

let manifest = null;
let strataData = {};
let domainData = {};
let failureModeData = {};
let displayRows = [];
let sortKey = 'overall_10';
let sortAsc = false;

const escapeHtml = (value) => String(value ?? '')
  .replaceAll('&', '&')
  .replaceAll('<', '&lt;')
  .replaceAll('>', '&gt;')
  .replaceAll('"', '&quot;')
  .replaceAll("'", '&#039;');

async function fetchJson(path) {
  const response = await fetch(`${path}?v=${Date.now()}`);
  if (!response.ok) throw new Error(`Unable to load ${path}: ${response.status}`);
  return response.json();
}

async function init() {
  try {
    [manifest, strataData, domainData, failureModeData] = await Promise.all([
      fetchJson('data/manifest.json'),
      fetchJson('data/leaderboard_by_stratum.json'),
      fetchJson('data/leaderboard_by_domain.json'),
      fetchJson('data/leaderboard_by_failure_mode.json'),
    ]);

    initScrollSync();
    await Promise.all([initMarkdown(), renderCitation()]);
    updateBoard();

    SEARCH_INPUT.addEventListener('input', updateBoard);
    BOARD_SELECT.addEventListener('change', () => {
      STRATUM_CONTROL.hidden = BOARD_SELECT.value !== 'components';
      sortKey = BOARD_SELECT.value === 'components' ? 'overall_10' : 'All';
      sortAsc = false;
      updateBoard();
    });
    STRATUM_SELECT.addEventListener('change', () => {
      sortKey = 'overall_10';
      sortAsc = false;
      updateBoard();
    });
    window.addEventListener('resize', updateScrollWidth);
  } catch (error) {
    console.error(error);
    TABLE_BODY.innerHTML = '<tr><td colspan="100%" class="error-cell">Error loading benchmark data.</td></tr>';
  }
}

async function initMarkdown() {
  const response = await fetch('blobs/intro.md');
  if (response.ok) document.getElementById('intro-markdown').innerHTML = marked.parse(await response.text());
}

function initScrollSync() {
  TOP_SCROLLBAR_WRAPPER.addEventListener('scroll', () => {
    BOTTOM_SCROLLBAR_WRAPPER.scrollLeft = TOP_SCROLLBAR_WRAPPER.scrollLeft;
  });
  BOTTOM_SCROLLBAR_WRAPPER.addEventListener('scroll', () => {
    TOP_SCROLLBAR_WRAPPER.scrollLeft = BOTTOM_SCROLLBAR_WRAPPER.scrollLeft;
  });
}

function updateScrollWidth() {
  requestAnimationFrame(() => {
    TOP_SCROLLBAR_CONTENT.style.width = `${TABLE.scrollWidth}px`;
  });
}

function modelMap(rows) {
  return Object.fromEntries(rows.map((row) => [row.model_id, row]));
}

function buildBreakdownRows(groups) {
  const overall = modelMap(strataData.All);
  return Object.values(manifest.models).map((metadata) => metadata.display_name)
    .map((displayName) => strataData.All.find((row) => row.display_name === displayName))
    .filter(Boolean)
    .map((base) => {
      const row = { ...base, All: base.overall_10, groupCoverage: {} };
      Object.entries(groups).forEach(([tag, scores]) => {
        const match = modelMap(scores)[base.model_id];
        row[tag] = match?.overall_10 ?? null;
        row.groupCoverage[tag] = match ? `${match.n_scored}/${match.n_total}` : '0/0';
      });
      row.All = overall[base.model_id]?.overall_10 ?? null;
      return row;
    });
}

function currentRows() {
  let rows;
  if (BOARD_SELECT.value === 'domains') rows = buildBreakdownRows(domainData);
  else if (BOARD_SELECT.value === 'failure_modes') rows = buildBreakdownRows(failureModeData);
  else rows = [...(strataData[STRATUM_SELECT.value] || [])];
  return rows.filter((row) => !EXCLUDED_MODELS.has(row.model_id));
}

function numericValue(row, key) {
  if (key.startsWith('component:')) return row.components?.[key.slice('component:'.length)] ?? null;
  return row[key] ?? null;
}

function updateBoard() {
  const query = SEARCH_INPUT.value.trim().toLowerCase();
  displayRows = currentRows().filter((row) => row.display_name.toLowerCase().includes(query));
  displayRows.sort((a, b) => {
    const left = numericValue(a, sortKey);
    const right = numericValue(b, sortKey);
    if (left == null && right == null) return a.display_name.localeCompare(b.display_name);
    if (left == null) return 1;
    if (right == null) return -1;
    if (typeof left === 'string') {
      const result = left.localeCompare(right);
      return sortAsc ? result : -result;
    }
    return sortAsc ? left - right : right - left;
  });
  renderHeaders();
  renderTable();
  renderSummary();
  DOMAIN_GLOSSARY.hidden = BOARD_SELECT.value !== 'domains';
  FAILURE_GLOSSARY.hidden = BOARD_SELECT.value !== 'failure_modes';
  updateScrollWidth();
}

function arrowFor(key) {
  return sortKey === key ? (sortAsc ? ' ↑' : ' ↓') : '';
}

function sortableHeader(key, label, className = '', description = '') {
  const title = description ? ` title="${escapeHtml(description)}"` : '';
  return `<th class="${className}" data-sort="${escapeHtml(key)}"${title}>${escapeHtml(label)}${arrowFor(key)}</th>`;
}

function renderHeaders() {
  let html = '<th class="rank-column">#</th>' + sortableHeader('display_name', 'Model', 'model-column', 'Evaluated image-generation model.');
  if (BOARD_SELECT.value === 'components') {
    html += sortableHeader('overall_10', 'Overall-10', 'primary-metric', 'Prompt-macro average across the ten applicable components, scaled to 0–100.');
    COMPONENTS.forEach(([key, label, description]) => { html += sortableHeader(`component:${key}`, label, '', description); });
    html += sortableHeader('coverage', 'Coverage', '', 'Share and count of prompts with valid scored results.');
  } else {
    html += sortableHeader('All', 'All 751', 'primary-metric');
    const groups = BOARD_SELECT.value === 'domains' ? domainData : failureModeData;
    Object.keys(groups).sort().forEach((tag) => { html += sortableHeader(tag, tag); });
  }
  TABLE_HEADER.innerHTML = html;
  TABLE_HEADER.querySelectorAll('[data-sort]').forEach((header) => {
    header.addEventListener('click', () => {
      const key = header.dataset.sort;
      if (sortKey === key) sortAsc = !sortAsc;
      else {
        sortKey = key;
        sortAsc = key === 'display_name';
      }
      updateBoard();
    });
  });
}

function formatScore(value) {
  return value == null || Number.isNaN(Number(value)) ? '<span class="na-value">N/A</span>' : Number(value).toFixed(1);
}

function modelCell(row) {
  const typeClass = row.type === 'Open' ? 'tag-open-weight' : 'tag-proprietary';
  return `<td class="model-column"><div class="model-cell"><span class="model-name">${escapeHtml(row.display_name)}</span><span class="${typeClass}">${escapeHtml(row.type)}</span></div></td>`;
}

function renderComponentRow(row, index) {
  const coveragePercent = (row.coverage * 100).toFixed(1);
  const coverageClass = row.coverage < 0.95 ? 'coverage-warning' : '';
  const components = COMPONENTS.map(([key]) => `<td>${formatScore(row.components[key])}</td>`).join('');
  return `<tr>
    <td class="rank-column">${index + 1}</td>
    ${modelCell(row)}
    <td class="metric-cell">${formatScore(row.overall_10)}</td>
    ${components}
    <td class="${coverageClass}" title="${row.n_scored} scored of ${row.n_total}; missing policy: ${escapeHtml(row.missing_policy)}">
      ${coveragePercent}% <span class="coverage-count">${row.n_scored}/${row.n_total}</span>
    </td>
  </tr>`;
}

function renderBreakdownRow(row, index, groups) {
  const cells = Object.keys(groups).sort().map((tag) => {
    const coverage = row.groupCoverage[tag];
    return `<td title="Coverage ${escapeHtml(coverage)}">${formatScore(row[tag])}</td>`;
  }).join('');
  return `<tr>
    <td class="rank-column">${index + 1}</td>
    ${modelCell(row)}
    <td class="metric-cell">${formatScore(row.All)}</td>
    ${cells}
  </tr>`;
}

function renderTable() {
  if (!displayRows.length) {
    TABLE_BODY.innerHTML = '<tr><td colspan="100%" class="empty-cell">No matching models found.</td></tr>';
    return;
  }
  if (BOARD_SELECT.value === 'components') {
    TABLE_BODY.innerHTML = displayRows.map(renderComponentRow).join('');
  } else {
    const groups = BOARD_SELECT.value === 'domains' ? domainData : failureModeData;
    TABLE_BODY.innerHTML = displayRows.map((row, index) => renderBreakdownRow(row, index, groups)).join('');
  }
}

function renderSummary() {
  let context;
  if (BOARD_SELECT.value === 'components') {
    const name = STRATUM_SELECT.value;
    const count = name === 'All' ? manifest.dataset.n_prompts : manifest.partition[name];
    context = `${escapeHtml(name)} · ${count} prompts`;
  } else {
    const groupCount = Object.keys(BOARD_SELECT.value === 'domains' ? domainData : failureModeData).length;
    context = `${groupCount} overlapping multi-label groups`;
  }
  STATS_SUMMARY.innerHTML = `Showing <strong>${displayRows.length}</strong> models · ${context}`;
}

async function renderCitation() {
  const citationEl = document.getElementById('citation-content');
  const copyButton = document.getElementById('copy-citation-btn');
  const response = await fetch('blobs/citation.md');
  if (!response.ok) return;
  const citation = await response.text();
  citationEl.textContent = citation;
  copyButton.addEventListener('click', async () => {
    await navigator.clipboard.writeText(citation);
    const original = copyButton.innerHTML;
    copyButton.innerHTML = '<i class="fa-solid fa-check"></i> Copied!';
    copyButton.classList.add('copied');
    setTimeout(() => {
      copyButton.innerHTML = original;
      copyButton.classList.remove('copied');
    }, 2000);
  });
}

init();