SLM-Leaderboard / script.js
Banaxi-Tech's picture
Update script.js
8e23c92 verified
Raw History Blame Contribute Delete
7.77 kB
const ORGS = {
bananamind: { name: "BananaMind", chartColor: "rgba(250, 204, 21, 0.70)", chartBorder: "#facc15", url: "https://huggingface.co/BananaMind" },
};
const MODELS = [
// Add models here.
{ name: "MicroBananaMind-v1", org: "bananamind", params: 902272, paramsDisplay: "902K", arc: 31.40, hellaswag: 26.53, piqa: 53.86, arcChall: 20.99, links: { card: "https://huggingface.co/BananaMind/MicroBananaMind-v1" } },
];
const BENCHMARKS = [
{ key: "avg", label: "Avg" },
{ key: "arc", label: "ARC Easy" },
{ key: "piqa", label: "PIQA" },
{ key: "arcChall", label: "ARC Challenge" },
{ key: "hellaswag", label: "HellaSwag" },
];
const SIZE_FILTERS = [
["all", "All"],
[150, "<150M"],
[100, "<100M"],
[80, "<80M"],
[50, "<50M"],
[25, "<25M"],
[10, "<10M"],
[5, "<5M"],
[3, "<3M"],
[1, "<1M"],
];
const leaderboardHead = document.querySelector("#leaderboard-head");
const leaderboardBody = document.querySelector("#leaderboard-body");
const summaryStrip = document.querySelector("#summary-strip");
const sizeFilters = document.querySelector("#size-filters");
const orgFilter = document.querySelector("#org-filter");
const searchInput = document.querySelector("#search-input");
let activeSize = "all";
let activeOrg = "all";
let searchTerm = "";
let sortKey = "avg";
let sortDirection = "descending";
const rows = MODELS.map((model) => ({
...model,
avg: average([model.arc, model.piqa, model.arcChall, model.hellaswag]),
}));
function average(values) {
const valid = values.filter((value) => Number.isFinite(value));
return valid.length ? valid.reduce((sum, value) => sum + value, 0) / valid.length : 0;
}
function escapeHtml(value) {
return String(value)
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;");
}
function orgFor(key) {
return ORGS[key] || { name: key, chartBorder: "#9ca3af", chartColor: "rgba(156, 163, 175, 0.35)", url: "" };
}
function renderHead() {
leaderboardHead.innerHTML = `
<tr>
<th class="rank-col sortable" data-sort="rank" scope="col">#<span class="sort-mark"></span></th>
<th class="model-col sortable" data-sort="name" scope="col">Model<span class="sort-mark"></span></th>
<th class="org-col sortable" data-sort="orgName" scope="col">Org<span class="sort-mark"></span></th>
<th class="params-col sortable" data-sort="params" scope="col">Params<span class="sort-mark"></span></th>
${BENCHMARKS.map((metric) => `<th class="metric-col sortable" data-sort="${metric.key}" scope="col">${metric.label}<span class="sort-mark"></span></th>`).join("")}
<th class="link-col" scope="col">Card</th>
</tr>
`;
document.querySelectorAll(".sortable").forEach((header) => {
header.addEventListener("click", () => {
const nextKey = header.dataset.sort;
sortDirection = sortKey === nextKey && sortDirection === "descending" ? "ascending" : "descending";
sortKey = nextKey;
renderRows();
updateSortMarks();
});
});
updateSortMarks();
}
function renderFilters() {
sizeFilters.innerHTML = SIZE_FILTERS.map(([value, label]) => `
<button class="filter-button ${String(value) === String(activeSize) ? "is-active" : ""}" type="button" data-size="${value}">${label}</button>
`).join("");
sizeFilters.querySelectorAll(".filter-button").forEach((button) => {
button.addEventListener("click", () => {
activeSize = button.dataset.size;
renderFilters();
renderRows();
});
});
const usedOrgs = Object.entries(ORGS)
.filter(([key]) => rows.some((row) => row.org === key))
.sort((first, second) => first[1].name.localeCompare(second[1].name));
orgFilter.innerHTML = `<option value="all">All orgs</option>${usedOrgs
.map(([key, org]) => `<option value="${key}">${escapeHtml(org.name)}</option>`)
.join("")}`;
orgFilter.value = activeOrg;
}
function filteredRows() {
return rows.filter((row) => {
const org = orgFor(row.org);
const matchesSize = activeSize === "all" || row.params < Number(activeSize) * 1_000_000;
const matchesOrg = activeOrg === "all" || row.org === activeOrg;
const text = `${row.name} ${org.name} ${row.org}`.toLowerCase();
return matchesSize && matchesOrg && (!searchTerm || text.includes(searchTerm));
});
}
function sortedRows() {
const ranked = [...filteredRows()]
.sort((first, second) => second.avg - first.avg)
.map((row, index) => ({ ...row, rank: index + 1, orgName: orgFor(row.org).name }));
return ranked.sort((first, second) => {
const firstValue = first[sortKey];
const secondValue = second[sortKey];
const result = typeof firstValue === "string"
? firstValue.localeCompare(secondValue)
: firstValue - secondValue;
return sortDirection === "descending" ? -result : result;
});
}
function scoreCell(row, key) {
const value = row[key];
const width = Math.max(0, Math.min(100, value));
return `
<td class="metric-cell">
<span class="score-value">${value.toFixed(2)}</span>
<span class="score-track" aria-hidden="true"><span style="width: ${width}%"></span></span>
</td>
`;
}
function renderRows() {
const visibleRows = sortedRows();
if (!visibleRows.length) {
leaderboardBody.innerHTML = `
<tr class="empty-row">
<td colspan="10">
<div class="empty-state">
<p class="empty-title">No matching models</p>
<p class="empty-copy">Clear search or change filters.</p>
</div>
</td>
</tr>
`;
renderSummary([]);
return;
}
leaderboardBody.innerHTML = visibleRows.map((row) => {
const org = orgFor(row.org);
const cardUrl = row.links?.card || org.url || "#";
return `
<tr>
<td class="rank-cell">${row.rank}</td>
<td class="model-cell">
<a class="model-link" href="${escapeHtml(cardUrl)}" target="_blank" rel="noreferrer">${escapeHtml(row.name)}</a>
<span class="mobile-meta">${escapeHtml(org.name)} / ${escapeHtml(row.paramsDisplay)}</span>
</td>
<td class="org-cell">
<a class="org-pill" href="${escapeHtml(org.url || cardUrl)}" target="_blank" rel="noreferrer" style="--org-color: ${org.chartBorder}">
<span></span>${escapeHtml(org.name)}
</a>
</td>
<td class="params-cell">${escapeHtml(row.paramsDisplay)}</td>
${BENCHMARKS.map((metric) => scoreCell(row, metric.key)).join("")}
<td class="card-cell"><a href="${escapeHtml(cardUrl)}" target="_blank" rel="noreferrer">Open</a></td>
</tr>
`;
}).join("");
renderSummary(visibleRows);
}
function renderSummary(visibleRows) {
const top = [...visibleRows].sort((first, second) => second.avg - first.avg)[0];
summaryStrip.innerHTML = `
<div><strong>${MODELS.length}</strong><span>models</span></div>
<div><strong>${new Set(MODELS.map((model) => model.org)).size}</strong><span>orgs</span></div>
<div><strong>${top ? top.avg.toFixed(2) : "--"}</strong><span>top avg</span></div>
`;
}
function updateSortMarks() {
document.querySelectorAll(".sortable").forEach((header) => {
const mark = header.querySelector(".sort-mark");
const active = header.dataset.sort === sortKey;
header.classList.toggle("is-sorted", active);
header.setAttribute("aria-sort", active ? sortDirection : "none");
mark.textContent = active ? (sortDirection === "descending" ? "↓" : "↑") : "";
});
}
orgFilter.addEventListener("change", () => {
activeOrg = orgFilter.value;
renderRows();
});
searchInput.addEventListener("input", () => {
searchTerm = searchInput.value.trim().toLowerCase();
renderRows();
});
renderHead();
renderFilters();
renderRows();