SearchGen-Bench / main.js
wufangtai
Update resource links and scoreboard glossaries
d586292
Raw
History Blame Contribute Delete
11.4 kB
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();