Spaces:
Running
Running
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('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
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();
|