CoolFace
Apppublic

NohTow/BrowseComp-Plus

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
main.js348 linesDownload Raw Back to root
1const TABLE_BODY = document.getElementById('table-body');2const TABLE_HEADER = document.getElementById('table-header');3const SEARCH_INPUT = document.getElementById('model-search');4const STATS_SUMMARY = document.getElementById('stats-summary');5const TOP_SCROLLBAR_WRAPPER = document.getElementById('top-scrollbar-wrapper');6const TOP_SCROLLBAR_CONTENT = document.getElementById('top-scrollbar-content');7const BOTTOM_SCROLLBAR_WRAPPER = document.getElementById('bottom-scrollbar-wrapper');8const TABLE = document.getElementById('leaderboard-table');9 10let rawData = [];11let displayData = [];12let sortKey = 'Accuracy (%)';13let sortAsc = false;14 15// Metrics we want to display as columns (from left to right)16const COLUMNS = [17    { id: 'LLM', label: 'LLM', class: 'col-llm' },18    { id: 'Retriever', label: 'Retriever', class: 'col-retriever' },19    { id: 'Submitted By', label: 'Submitted By', class: 'col-submitted' },20    { id: 'Scaffold', label: 'Scaffold', class: 'col-scaffold' },21    { id: 'Accuracy (%)', label: 'Accuracy (%)', class: 'col-metric' },22    { id: 'Recall (%)', label: 'Recall (%)', class: 'col-metric' },23    { id: 'Search Calls', label: 'Search Calls', class: 'col-metric' },24    { id: 'Calibration Error (%)', label: 'Calibration Error (%)', class: 'col-metric' },25];26 27async function init() {28    try {29        // Cache buster to ensure fresh data from the extraction script30        const v = Date.now();31        const response = await fetch(`data/leaderboard.json?v=${v}`);32 33        if (response.ok) {34            rawData = await response.json();35        } else {36            console.error('Leaderboard JSON not found.');37        }38 39        renderHeaders();40        updateDisplayData();41        renderTable();42        initScrollSync();43        await initMarkdown();44        await renderCitation();45 46        SEARCH_INPUT.addEventListener('input', e => {47            updateDisplayData(e.target.value);48            renderTable();49            updateScrollWidth();50        });51 52        window.addEventListener('resize', updateScrollWidth);53        updateScrollWidth();54 55    } catch (err) {56        console.error('Failed to load data:', err);57        TABLE_BODY.innerHTML = '<tr><td colspan="100%" style="color: red; text-align: center;">Error loading benchmark data.</td></tr>';58    }59}60 61async function initMarkdown() {62    const introEl = document.getElementById('intro-markdown');63    const metricsEl = document.getElementById('metrics-details');64    const submittingEl = document.getElementById('submit-here');65 66    try {67        const [introRes, metricsRes, submittingRes] = await Promise.all([68            fetch('blobs/intro.md'),69            fetch('blobs/metrics.md'),70            fetch('blobs/submitting.md')71        ]);72 73        if (introRes.ok) introEl.innerHTML = marked.parse(await introRes.text());74        if (metricsRes.ok) metricsEl.innerHTML = marked.parse(await metricsRes.text());75        if (submittingRes.ok) submittingEl.innerHTML = marked.parse(await submittingRes.text());76 77        // Expand/Collapse logic78        document.querySelectorAll('.expand-btn').forEach(btn => {79            btn.addEventListener('click', () => {80                const targetId = btn.getAttribute('data-target');81                if (!targetId) return; // Skip external links82 83                const targetEl = document.getElementById(targetId);84                const isActive = btn.classList.contains('active');85 86                if (isActive) {87                    btn.classList.remove('active');88                    targetEl.classList.remove('active');89                } else {90                    // Optional: close other expandable sections91                    document.querySelectorAll('.expand-btn').forEach(b => b.classList.remove('active'));92                    document.querySelectorAll('.expandable-content').forEach(c => c.classList.remove('active'));93 94                    btn.classList.add('active');95                    targetEl.classList.add('active');96 97                    // Smooth scroll to content98                    setTimeout(() => {99                        targetEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });100                    }, 100);101                }102            });103        });104 105    } catch (err) {106        console.error('Failed to load markdown blobs:', err);107    }108}109 110function initScrollSync() {111    TOP_SCROLLBAR_WRAPPER.addEventListener('scroll', () => {112        BOTTOM_SCROLLBAR_WRAPPER.scrollLeft = TOP_SCROLLBAR_WRAPPER.scrollLeft;113    });114    BOTTOM_SCROLLBAR_WRAPPER.addEventListener('scroll', () => {115        TOP_SCROLLBAR_WRAPPER.scrollLeft = BOTTOM_SCROLLBAR_WRAPPER.scrollLeft;116    });117}118 119function updateScrollWidth() {120    TOP_SCROLLBAR_CONTENT.style.width = TABLE.offsetWidth + 'px';121}122 123function parseCSV(csv) {124    const lines = csv.split('\n').filter(line => line.trim() !== '');125    if (lines.length === 0) return [];126 127    const headers = parseCSVLine(lines[0]);128    return lines.slice(1).map(line => {129        const values = parseCSVLine(line);130        const obj = {};131        headers.forEach((header, i) => {132            obj[header.trim()] = values[i] ? values[i].trim() : '';133        });134        return obj;135    });136}137 138function parseCSVLine(line) {139    const result = [];140    let cur = '';141    let inQuotes = false;142    for (let i = 0; i < line.length; i++) {143        const char = line[i];144        if (char === '"') {145            inQuotes = !inQuotes;146        } else if (char === ',' && !inQuotes) {147            result.push(cur);148            cur = '';149        } else {150            cur += char;151        }152    }153    result.push(cur);154    return result;155}156 157function renderHeaders() {158    let html = `<th style="width: 60px;">#</th>`;159 160    COLUMNS.forEach(col => {161        const arrow = sortKey === col.id ? (sortAsc ? ' \u2191' : ' \u2193') : '';162        html += `<th onclick="handleSort('${col.id}')" class="${col.class || ''}">${col.label}${arrow}</th>`;163    });164 165    TABLE_HEADER.innerHTML = html;166}167 168function handleSort(key) {169    if (sortKey === key) {170        sortAsc = !sortAsc;171    } else {172        sortKey = key;173        sortAsc = false;174    }175 176    renderHeaders();177    updateDisplayData(SEARCH_INPUT.value);178    renderTable();179}180 181window.handleSort = handleSort;182 183function updateDisplayData(query = '') {184    displayData = rawData.filter(item => {185        const searchStr = `${item.LLM} ${item.Retriever} ${item["Submitted By"]}`.toLowerCase();186        return searchStr.includes(query.toLowerCase());187    });188 189    displayData.sort((a, b) => {190        let valA = a[sortKey];191        let valB = b[sortKey];192 193        if (['Accuracy (%)', 'Recall (%)', 'Search Calls', 'Calibration Error (%)'].includes(sortKey)) {194            valA = parseFloat(valA) || 0;195            valB = parseFloat(valB) || 0;196        } else {197            if (typeof valA === 'string') valA = valA.toLowerCase();198            if (typeof valB === 'string') valB = valB.toLowerCase();199        }200 201        if (valA < valB) return sortAsc ? -1 : 1;202        if (valA > valB) return sortAsc ? 1 : -1;203        return 0;204    });205 206    STATS_SUMMARY.innerHTML = `Showing <strong>${displayData.length}</strong> results`;207}208 209function formatScaffold(scaffold) {210    if (!scaffold || scaffold.trim() === '') {211        const text = 'The default scaffold in BrowseComp-Plus, with a `search` function that returns top 5 docs, truncated by 512 tokens.';212        return {213            display: 'Standard',214            title: 'Standard',215            text: text.replace(/`([^`]+)`/g, '<code class="tooltip-code">$1</code>')216        };217    }218 219    const parts = scaffold.split(':');220    const title = parts[0].trim();221    let text = parts.length > 1 ? parts.slice(1).join(':').trim() : '';222 223    // Highlight terms bracketed in backticks224    text = text.replace(/`([^`]+)`/g, '<code class="tooltip-code">$1</code>');225 226    return {227        display: 'Custom',228        title: title,229        text: text230    };231}232 233function renderTable() {234    if (displayData.length === 0) {235        TABLE_BODY.innerHTML = '<tr><td colspan="100%" style="text-align: center;">No matching models found.</td></tr>';236        return;237    }238 239    TABLE_BODY.innerHTML = displayData.map((row, index) => {240        const scaffoldInfo = formatScaffold(row.Scaffold);241        const isOpenWeight = row["Open Weights?"] === 'Yes';242        const modelSize = row["Model Size (B)"];243 244        return `245        <tr>246          <!-- Rank & Weight Column -->247          <td style="text-align: center; vertical-align: top; padding-top: 1.5rem;">248            <div style="display: flex; flex-direction: column; align-items: center; gap: 6px;">249                <span style="color: var(--text-secondary); font-size: 0.8rem; font-weight: 600;">${index + 1}</span>250                ${isOpenWeight ?251                `<span class="tag-open-weight">${modelSize}B</span>` :252                `<span class="tag-proprietary">Proprietary</span>`253            }254            </div>255          </td>256          257          <!-- LLM Column -->258          <td class="col-llm">259            <div style="display: flex; flex-direction: column;">260                <a href="${row["LLM Link"] || '#'}" target="_blank" class="model-name">${row.LLM}</a>261                <div class="evaluation-date">262                    ${row["Evaluation Date"] || 'N/A'}263                </div>264            </div>265          </td>266 267          <!-- Retriever Column -->268          <td class="col-retriever">269            <a href="${row["Retriever Link"] || '#'}" target="_blank" style="color: var(--text-primary); text-decoration: none; font-weight: 500;">270                ${row.Retriever}271            </a>272          </td>273 274          <!-- Submitted By Column -->275          <td class="col-submitted">276            ${(() => {277                const isInternal = row["Submitted By"] === 'BrowseComp-Plus';278                const style = isInternal ?279                    'color: var(--text-secondary); font-size: 0.9rem;' :280                    'color: var(--accent-secondary); font-size: 0.9rem; font-weight: 600;';281                const border = isInternal ? 'border-bottom: 1px dashed #cbd5e1;' : 'border-bottom: 1px dashed rgba(124, 58, 237, 0.3);';282 283                return row["Submittor Link"] ?284                    `<a href="${row["Submittor Link"]}" target="_blank" style="${style} ${border} text-decoration: none;">${row["Submitted By"]}</a>` :285                    `<span style="${style}">${row["Submitted By"]}</span>`;286            })()}287          </td>288 289          <!-- Scaffold Column -->290          <td class="col-scaffold">291            <div class="tooltip-container">292                <span class="tag-scaffold ${scaffoldInfo.display === 'Custom' ? 'tag-scaffold-custom' : 'tag-scaffold-standard'}">293                    ${scaffoldInfo.display}294                </span>295                <div class="tooltip-content">296                    <div class="tooltip-title">${scaffoldInfo.title}</div>297                    <div class="tooltip-text">${scaffoldInfo.text}</div>298                </div>299            </div>300          </td>301 302          <!-- Accuracy (%) -->303          <td class="metric-cell col-metric">${parseFloat(row["Accuracy (%)"]).toFixed(2)}%</td>304 305          <!-- Recall (%) -->306          <td class="col-metric" style="font-weight: 500; color: var(--text-primary);">${parseFloat(row["Recall (%)"]).toFixed(2)}%</td>307 308          <!-- Search Calls -->309          <td class="col-metric" style="color: var(--text-primary);">${parseFloat(row["Search Calls"]).toFixed(2)}</td>310 311          <!-- Calibration Error (%) -->312          <td class="col-metric" style="color: var(--text-primary);">313            ${row["Calibration Error (%)"] && row["Calibration Error (%)"] !== '-' ? parseFloat(row["Calibration Error (%)"]).toFixed(2) + '%' : 'N/A'}314          </td>315        </tr>316    `}).join('');317}318 319async function renderCitation() {320    const citationEl = document.getElementById('citation-content');321    const copyBtn = document.getElementById('copy-citation-btn');322 323    try {324        const response = await fetch('blobs/citation.md');325        if (response.ok) {326            const text = await response.text();327            citationEl.textContent = text;328 329            copyBtn.addEventListener('click', () => {330                navigator.clipboard.writeText(text).then(() => {331                    const originalHtml = copyBtn.innerHTML;332                    copyBtn.innerHTML = '<i class="fa-solid fa-check"></i> Copied!';333                    copyBtn.classList.add('copied');334 335                    setTimeout(() => {336                        copyBtn.innerHTML = originalHtml;337                        copyBtn.classList.remove('copied');338                    }, 2000);339                });340            });341        }342    } catch (err) {343        console.error('Failed to load citation:', err);344    }345}346 347init();348