class LLMBenchmarkDashboard { constructor() { this.currentJudge = 'gpt5.4'; this.searchQuery = ''; this.judgeData = { o3: { general: null, complicated: null }, 'gpt5.4': { general: null, complicated: null } }; this.generalSort = { column: 'overall_score', direction: 'desc' }; this.complicatedSort = { column: 'overall_score', direction: 'desc' }; this.metricDisplayNames = { comprehension_score: 'Comprehension', structure_score: 'Coherence', prose_style_score: 'Style', creativity_score: 'Creativity', depth_score: 'Depth', helpfulness_score: 'Helpfulness', overall_score: 'Overall' }; this.metricDescriptions = { comprehension_score: 'How well the response understands the prompt intent and stays on topic.', structure_score: 'How clear, logical, and well-organized the writing is.', prose_style_score: 'The quality of language, grammar, and adherence to the requested tone.', creativity_score: 'The novelty of ideas and uniqueness of perspective.', depth_score: 'The level of detail, analysis, and substance provided.', helpfulness_score: 'How effectively the response fulfills the user\'s overall goal.', overall_score: 'Average score across all six criteria.' }; this.judgePaths = { o3: { general: 'data/all-scores.json', complicated: 'data/complicated-writing-scores.json' }, 'gpt5.4': { general: 'data/gpt5.4-judge-all-scores.json', complicated: 'data/gpt5.4-judge-complicated-writing-scores.json' } }; this.modelLinks = { 'Monomer-24B-Writer': 'https://huggingface.co/zake7749/Monomer-24B-Writer-Preview', 'Monomer-8B-Writer': 'https://huggingface.co/zake7749/Monomer-8B-Writer-Preview' }; this.init(); } async init() { this.showLoading(true); const promises = []; for (const judge of ['o3', 'gpt5.4']) { for (const type of ['general', 'complicated']) { promises.push(this.loadData(this.judgePaths[judge][type], judge, type)); } } await Promise.all(promises); this.renderTable('general'); this.renderTable('complicated'); this.setupSearch(); this.setupJudgeToggle(); this.setupTabs(); this.showLoading(false); } async loadData(path, judge, type) { try { const response = await fetch(path); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } this.judgeData[judge][type] = await response.json(); } catch (error) { console.error(`Error loading ${judge}/${type} data:`, error); } } get generalData() { return this.judgeData[this.currentJudge].general; } get complicatedData() { return this.judgeData[this.currentJudge].complicated; } setupJudgeToggle() { const buttons = document.querySelectorAll('.judge-btn'); buttons.forEach(btn => { btn.addEventListener('click', () => { const judge = btn.dataset.judge; if (judge === this.currentJudge) return; this.currentJudge = judge; buttons.forEach(b => b.classList.remove('active')); btn.classList.add('active'); this.renderTable('general'); this.renderTable('complicated'); }); }); } setupSearch() { const searchInput = document.getElementById('globalSearch'); if (searchInput) { searchInput.addEventListener('input', (e) => { this.searchQuery = e.target.value.toLowerCase().trim(); this.renderTable('general'); this.renderTable('complicated'); }); } } setupTabs() { const tabBtns = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); tabBtns.forEach(btn => { btn.addEventListener('click', () => { const targetId = btn.dataset.target; // Update active state of buttons tabBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); // Update active state of content tabContents.forEach(content => { if (content.id === targetId) { content.classList.add('active'); } else { content.classList.remove('active'); } }); }); }); } renderTable(type) { const data = type === 'general' ? this.generalData : this.complicatedData; const sortState = type === 'general' ? this.generalSort : this.complicatedSort; const tableContainer = document.getElementById(type === 'general' ? 'generalTable' : 'complicatedTable'); if (!data) return; const models = Object.keys(data); const metrics = Object.keys(data[models[0]]); const tableHTML = `
| Model | ${metrics.map(metric => `${this.metricDisplayNames[metric] || metric} | `).join('')}
|---|---|
| ${medalHtml} ${isMonomer ? `${row.model}` : row.model} ${isBaseline ? ' (Baseline)' : ''} | ${metrics.map(metric => `${this.formatScore(row[metric])} | `).join('')}
${message}