dashboard / assets /app.js
3v324v23's picture
score trend
cd80b88
Raw
History Blame Contribute Delete
32.4 kB
const ACCENT = "#5eead4";
const BASE = "#6b7280";
const css = (v) => getComputedStyle(document.documentElement).getPropertyValue(v).trim();
let DATA = null;
let scoreChart = null;
let lenChart = null;
let loading = false;
const $ = (id) => document.getElementById(id);
function shortKey(k) {
if (!k || k.length <= 14) return { head: k || "pending", tail: "" };
return { head: k.slice(0, 8), tail: "…" + k.slice(-6) };
}
async function load() {
await refreshData(true);
window.setInterval(() => refreshData(false), 15000);
}
async function refreshData(initial) {
if (loading) return;
loading = true;
const previousView = $("validator-select")?.value;
try {
const res = await fetch("./data.json", { cache: "no-store" });
if (!res.ok) throw new Error("HTTP " + res.status);
DATA = await res.json();
} catch (err) {
console.error("Failed to load data.json", err);
if (initial || !DATA) {
$("board-empty").hidden = false;
$("board-empty").textContent = "Data is not ready yet";
}
loading = false;
return;
}
hydrateUpdated();
buildViews(previousView);
renderActiveView();
loading = false;
}
function hydrateUpdated() {
const ts = DATA.generated_at;
const date = ts ? new Date(ts) : null;
const label = date && !Number.isNaN(date.getTime()) ? formatTimestamp(date) : "unknown";
$("updated").textContent = "latest " + label;
$("footer-meta").textContent = DATA.sample ? "sample data" : "live data";
}
function formatTimestamp(date) {
const day = date.toLocaleDateString(undefined, { year: "2-digit", month: "numeric", day: "numeric" });
const time = date.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" });
return `${day} ${time}`;
}
function buildViews(preferredView) {
const select = $("validator-select");
select.innerHTML = "";
const views = [];
for (const v of DATA.validators || []) {
const sk = shortKey(v.hotkey);
views.push({ id: v.hotkey, label: "Validator " + sk.head + sk.tail });
}
for (const view of views) {
const opt = document.createElement("option");
opt.value = view.id;
opt.textContent = view.label;
select.appendChild(opt);
}
if (preferredView && views.some((view) => view.id === preferredView)) {
select.value = preferredView;
}
select.onchange = renderActiveView;
$("stat-validators").textContent = (DATA.validators || []).length || "0";
}
const FULL_EVALUATION_ENTRANT_STATES = new Set(["evaluating", "finished", "failed"]);
function roundParticipation(progresses) {
const miners = new Map();
let hasCurrentRound = false;
for (const progress of progresses) {
for (const [stageName, stage] of Object.entries(progress?.stages || {})) {
if (stageName !== "qualification" && stageName !== "full_evaluation") continue;
const entries = Object.entries(stage?.miners || {});
if (entries.length) hasCurrentRound = true;
for (const [hotkey, status] of entries) {
const participation = miners.get(hotkey) || {
qualification: false,
fullEvaluation: false,
qualificationStatus: null,
fullEvaluationStatus: null,
};
if (stageName === "qualification") {
participation.qualification = true;
participation.qualificationStatus = status;
}
if (stageName === "full_evaluation" && FULL_EVALUATION_ENTRANT_STATES.has(status)) {
participation.fullEvaluation = true;
}
if (stageName === "full_evaluation") participation.fullEvaluationStatus = status;
miners.set(hotkey, participation);
}
}
}
return { miners, hasCurrentRound };
}
function numericScore(value) {
return typeof value === "number" && Number.isFinite(value) ? value : null;
}
function currentRoundRows(progress) {
const round = roundParticipation(progress ? [progress] : []);
const qualificationScores = progress?.stages?.qualification?.scores || {};
const fullEvaluationScores = progress?.stages?.full_evaluation?.scores || {};
const rows = [...round.miners].map(([hotkey, participation]) => ({
hotkey,
participation,
qualificationScore: numericScore(qualificationScores[hotkey]),
fullEvaluationScore: numericScore(fullEvaluationScores[hotkey]),
}));
rows.sort((a, b) => {
if (a.fullEvaluationScore != null || b.fullEvaluationScore != null) {
if (a.fullEvaluationScore == null) return 1;
if (b.fullEvaluationScore == null) return -1;
return b.fullEvaluationScore - a.fullEvaluationScore;
}
if (a.qualificationScore == null) {
return b.qualificationScore == null ? a.hotkey.localeCompare(b.hotkey) : 1;
}
if (b.qualificationScore == null) return -1;
return b.qualificationScore - a.qualificationScore;
});
return { rows, hasCurrentRound: round.hasCurrentRound, hotkeys: new Set(round.miners.keys()) };
}
function scoreFromHistory(history, hotkey, epoch) {
const epochs = history?.epochs || [];
const index = epochs.indexOf(epoch);
if (index < 0) return null;
return numericScore(history?.miners?.[hotkey]?.score?.[index]);
}
function stageScoresFromHistory(history, epoch) {
const snapshot = (history?.stage_scores || []).find((row) => row.epoch === epoch);
return {
qualification: snapshot?.qualification || {},
fullEvaluation: snapshot?.full_evaluation || {},
};
}
function previousRoundRows(rankings, history, progress, currentHotkeys) {
const epochs = history?.epochs || [];
const currentEpoch = numericScore(progress?.epoch);
const previousEpoch = currentEpoch == null
? (epochs.length ? epochs[epochs.length - 1] : null)
: [...epochs].reverse().find((epoch) => epoch < currentEpoch) ?? null;
const latestCompletedEpoch = epochs.length ? epochs[epochs.length - 1] : null;
const finalScores = new Map();
if (previousEpoch != null) {
for (const hotkey of Object.keys(history?.miners || {})) {
const score = scoreFromHistory(history, hotkey, previousEpoch);
if (score != null) finalScores.set(hotkey, score);
}
}
if (previousEpoch == null && latestCompletedEpoch == null) {
for (const row of rankings) {
const score = numericScore(row.score);
if (score != null && !finalScores.has(row.hotkey)) finalScores.set(row.hotkey, score);
}
}
const stageScores = stageScoresFromHistory(history, previousEpoch);
const hotkeys = new Set([
...finalScores.keys(),
...Object.keys(stageScores.qualification),
...Object.keys(stageScores.fullEvaluation),
]);
const rows = [...hotkeys].map((hotkey) => ({
hotkey,
finalScore: finalScores.get(hotkey) ?? null,
qualificationScore: numericScore(stageScores.qualification[hotkey]),
fullEvaluationScore: numericScore(stageScores.fullEvaluation[hotkey]),
isCurrent: currentHotkeys.has(hotkey),
}));
rows.sort((a, b) => {
if (a.finalScore == null) return b.finalScore == null ? a.hotkey.localeCompare(b.hotkey) : 1;
if (b.finalScore == null) return -1;
return b.finalScore - a.finalScore;
});
rows.forEach((row, index) => { row.previousRank = row.finalScore == null ? null : index + 1; });
return { rows, epoch: previousEpoch };
}
function olderMinerRows(history, currentHotkeys, previousRows, previousEpoch) {
if (previousEpoch == null) return [];
const epochs = history?.epochs || [];
const excluded = new Set([...currentHotkeys, ...previousRows.map((row) => row.hotkey)]);
const rows = [];
for (const [hotkey, series] of Object.entries(history?.miners || {})) {
if (excluded.has(hotkey)) continue;
let index = epochs.length - 1;
while (index >= 0 && (epochs[index] >= previousEpoch || numericScore(series?.score?.[index]) == null)) {
index -= 1;
}
if (index < 0) continue;
const epoch = epochs[index];
const stageScores = stageScoresFromHistory(history, epoch);
rows.push({
hotkey,
lastScoredEpoch: epoch,
finalScore: numericScore(series.score[index]),
qualificationScore: numericScore(stageScores.qualification[hotkey]),
fullEvaluationScore: numericScore(stageScores.fullEvaluation[hotkey]),
});
}
rows.sort((a, b) => (
b.lastScoredEpoch - a.lastScoredEpoch
|| (b.finalScore ?? -Infinity) - (a.finalScore ?? -Infinity)
));
return rows;
}
function activeView() {
const id = $("validator-select").value;
const v = (DATA.validators || []).find((x) => x.hotkey === id);
const current = currentRoundRows(v?.progress || null);
const previous = previousRoundRows(
v?.rankings || [],
v?.history || null,
v?.progress || null,
current.hotkeys,
);
const older = olderMinerRows(v?.history || null, current.hotkeys, previous.rows, previous.epoch);
return {
rankings: current.rows,
previousRankings: previous.rows,
previousEpoch: previous.epoch,
olderRankings: older,
hasCurrentRound: current.hasCurrentRound,
history: v?.history || null,
progress: v?.progress || null,
validator: v || null,
};
}
function renderActiveView() {
const view = activeView();
renderBoard(view);
renderStats(view);
renderProgress(view);
renderTrends(view);
}
function renderStats(view) {
const top = view.rankings.find((row) => row.fullEvaluationScore != null);
$("stat-miners").textContent = view.rankings.length;
$("stat-top").textContent = top ? top.fullEvaluationScore.toFixed(3) : "-";
const ep = view.history?.epochs;
$("stat-epoch").textContent = view.progress?.epoch ?? (ep && ep.length ? ep[ep.length - 1] : "0");
}
const TERMINAL_MINER_STATES = new Set(["finished", "failed", "rejected", "skipped", "not_selected"]);
function statusLabel(status) {
return String(status || "waiting").replaceAll("_", " ");
}
function statusClass(status) {
const safe = String(status || "waiting").toLowerCase().replaceAll("_", "-").replace(/[^a-z-]/g, "");
return "status-" + safe;
}
function compactStatusLabel(status) {
switch (status) {
case "completed":
case "finished":
return "done";
case "evaluating":
case "running":
return "live";
case "not_selected":
return "out";
default:
return statusLabel(status || "waiting");
}
}
function appendHotkey(parent, value) {
const sk = shortKey(value);
const hotkey = document.createElement("span");
hotkey.className = "hotkey";
const head = document.createElement("span");
head.className = "head";
head.textContent = sk.head;
const tail = document.createElement("span");
tail.className = "tail";
tail.textContent = sk.tail;
hotkey.append(head, tail);
parent.appendChild(hotkey);
}
function progressTimestamp(progress) {
const date = progress?.updated_at ? new Date(progress.updated_at) : null;
return date && !Number.isNaN(date.getTime()) ? date : null;
}
function displayProgressStatus(progress) {
return progress?.status || "waiting";
}
function stageStats(stage) {
const entries = Object.entries(stage?.miners || {});
const resolved = entries.filter(([, status]) => TERMINAL_MINER_STATES.has(status)).length;
const finished = entries.filter(([, status]) => status === "finished").length;
const evaluating = entries.filter(([, status]) => status === "evaluating").length;
return { total: entries.length, resolved, finished, evaluating };
}
function stageProgressPercent(stats) {
return stats.total ? Math.round((stats.resolved / stats.total) * 100) : 0;
}
function baselineStatus(stage) {
return stage?.baseline || "waiting";
}
function stageScore(stage, hotkey) {
const score = stage?.scores?.[hotkey];
return typeof score === "number" && Number.isFinite(score) ? score : null;
}
function stageTopScore(stage) {
const scores = Object.values(stage?.scores || {}).filter(
(value) => typeof value === "number" && Number.isFinite(value),
);
return scores.length ? Math.max(...scores) : null;
}
function formatScore(value) {
return value == null ? "-" : value.toFixed(3);
}
function formatDuration(seconds) {
if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds < 0) return null;
if (seconds < 60) return `${seconds.toFixed(1)}s`;
const minutes = Math.floor(seconds / 60);
const rest = Math.round(seconds % 60);
return `${minutes}m ${String(rest).padStart(2, "0")}s`;
}
function baselineDurationLabel(stage) {
return formatDuration(stage?.baseline_seconds);
}
function stageDurationLabel(stage) {
return formatDuration(stage?.duration_seconds);
}
function stageIsEvaluating(stage, stats = stageStats(stage)) {
return stage?.status === "evaluating" || baselineStatus(stage) === "evaluating" || stats.evaluating > 0;
}
function renderProgress(view) {
const content = $("progress-content");
content.innerHTML = "";
if (!view.validator) {
renderProgressOverview(content);
return;
}
const progress = view.progress;
const validatorKey = shortKey(view.validator.hotkey);
$("progress-subtitle").textContent = `Epoch ${progress?.epoch ?? "-"} from validator ${validatorKey.head}${validatorKey.tail}`;
const overallStatus = displayProgressStatus(progress);
$("progress-status").textContent = statusLabel(overallStatus);
$("progress-status").className = `status-pill ${statusClass(overallStatus)}`;
const updated = progressTimestamp(progress);
$("progress-updated").textContent = updated ? formatTimestamp(updated) : "syncing";
if (!progress) {
const empty = document.createElement("div");
empty.className = "empty";
empty.textContent = "Waiting for this validator";
content.appendChild(empty);
return;
}
const grid = document.createElement("div");
grid.className = "stage-grid";
grid.append(
renderStageCard("Qualification", progress.stages?.qualification),
renderStageCard("Full evaluation", progress.stages?.full_evaluation),
);
content.appendChild(grid);
}
function renderProgressOverview(content) {
$("progress-subtitle").textContent = "Live stage health across validators";
$("progress-status").textContent = "all";
$("progress-status").className = "status-pill";
const validators = DATA.validators || [];
const dates = validators.map((validator) => progressTimestamp(validator.progress)).filter(Boolean);
const latest = dates.length ? new Date(Math.max(...dates.map((date) => date.getTime()))) : null;
$("progress-updated").textContent = latest ? formatTimestamp(latest) : "syncing";
if (!validators.length) {
const empty = document.createElement("div");
empty.className = "empty";
empty.textContent = "Waiting for validator progress";
content.appendChild(empty);
return;
}
const overview = document.createElement("div");
overview.className = "progress-overview";
for (const validator of validators) overview.appendChild(renderValidatorProgressRow(validator));
content.appendChild(overview);
}
function renderValidatorProgressRow(validator) {
const row = document.createElement("div");
row.className = "validator-progress-row";
const name = document.createElement("div");
name.className = "validator-progress-name";
appendHotkey(name, validator.hotkey);
const status = displayProgressStatus(validator.progress);
const pill = document.createElement("span");
pill.className = `status-pill ${statusClass(status)}`;
pill.textContent = statusLabel(status);
name.appendChild(pill);
row.append(
name,
renderStageSummary("Qualification", validator.progress?.stages?.qualification),
renderStageSummary("Full evaluation", validator.progress?.stages?.full_evaluation),
);
return row;
}
function renderStageSummary(label, stage) {
const summary = document.createElement("div");
const stats = stageStats(stage);
summary.className = stageIsEvaluating(stage, stats) ? "stage-summary is-evaluating" : "stage-summary";
const baseDuration = baselineDurationLabel(stage);
summary.title = stage
? `${label} ${statusLabel(stage.status)} with base ${statusLabel(baselineStatus(stage))}` +
(baseDuration ? ` (${baseDuration})` : "") +
` and ${stats.resolved}/${stats.total} miners complete`
: `${label} waiting for data`;
const head = document.createElement("div");
head.className = "stage-summary-head";
const title = document.createElement("strong");
title.textContent = label;
const state = document.createElement("span");
state.className = `stage-state ${statusClass(stage?.status)}`;
state.textContent = compactStatusLabel(stage?.status);
head.append(title, state);
const meter = document.createElement("div");
meter.className = "stage-mini-bar";
const fill = document.createElement("i");
fill.style.width = `${stageProgressPercent(stats)}%`;
meter.appendChild(fill);
const foot = document.createElement("div");
foot.className = "stage-summary-foot";
const done = document.createElement("span");
done.className = "stage-mini-count";
done.textContent = stage ? `${stats.resolved}/${stats.total}` : "0/0";
done.setAttribute("aria-label", "miners complete");
const baseline = document.createElement("span");
const baseStatus = baselineStatus(stage);
baseline.className = `stage-mini-base ${statusClass(baseStatus)}`;
baseline.textContent = `base ${compactStatusLabel(baseStatus)}` + (baseDuration ? ` · ${baseDuration}` : "");
baseline.title = `Base model ${statusLabel(baseStatus)}` + (baseDuration ? ` in ${baseDuration}` : "");
foot.append(done, baseline);
if (stats.evaluating) {
const active = document.createElement("span");
active.className = "stage-mini-active";
active.textContent = `${stats.evaluating} active`;
foot.appendChild(active);
}
summary.append(head, meter, foot);
return summary;
}
function renderStageCard(label, stage) {
const card = document.createElement("section");
const stats = stageStats(stage);
const isEvaluating = stageIsEvaluating(stage, stats);
card.className = isEvaluating ? "stage-card is-evaluating" : "stage-card";
const head = document.createElement("div");
head.className = "stage-head";
const titleRow = document.createElement("div");
titleRow.className = "stage-title-row";
const title = document.createElement("span");
title.className = "stage-title";
title.textContent = label;
const pill = document.createElement("span");
pill.className = `status-pill ${statusClass(stage?.status)}`;
pill.textContent = statusLabel(stage?.status);
const stageDuration = stageDurationLabel(stage);
if (stageDuration) pill.title = `took ${stageDuration}`;
titleRow.append(title, pill);
const count = document.createElement("div");
const bar = document.createElement("div");
count.className = "stage-metrics";
const baseDuration = baselineDurationLabel(stage);
count.append(
renderStageMetric("done", `${stats.resolved}/${stats.total}`),
renderStageMetric("active", String(stats.evaluating)),
renderStageMetric(
"base",
compactStatusLabel(baselineStatus(stage)) + (baseDuration ? ` · ${baseDuration}` : ""),
),
renderStageMetric("top", formatScore(stageTopScore(stage))),
);
bar.className = isEvaluating ? "stage-bar is-evaluating" : "stage-bar";
const fill = document.createElement("i");
fill.style.width = `${stageProgressPercent(stats)}%`;
bar.appendChild(fill);
head.append(titleRow, count, bar);
card.appendChild(head);
const list = document.createElement("div");
list.className = "miner-state-list";
if (stage) {
const baselineRow = document.createElement("div");
baselineRow.className = "miner-state-row baseline-state-row";
const label = document.createElement("span");
label.className = "baseline-label";
label.textContent = "Base model";
const state = document.createElement("span");
const baseStatus = baselineStatus(stage);
const baseDuration = baselineDurationLabel(stage);
state.className = `miner-state ${statusClass(baseStatus)}`;
state.textContent = statusLabel(baseStatus) + (baseDuration ? ` · ${baseDuration}` : "");
baselineRow.append(label, state);
list.appendChild(baselineRow);
}
const miners = Object.entries(stage?.miners || {});
if (!miners.length) {
const empty = document.createElement("div");
empty.className = "empty";
empty.textContent = "No miners yet";
list.appendChild(empty);
} else {
for (const [hotkey, minerStatus] of miners) {
const row = document.createElement("div");
row.className = "miner-state-row";
appendHotkey(row, hotkey);
const score = stageScore(stage, hotkey);
const state = document.createElement("span");
state.className = `miner-state ${statusClass(minerStatus)}`;
state.textContent = statusLabel(minerStatus) + (score != null ? ` · ${formatScore(score)}` : "");
row.appendChild(state);
list.appendChild(row);
}
}
card.appendChild(list);
return card;
}
function renderStageMetric(label, value) {
const metric = document.createElement("span");
metric.className = `stage-metric stage-metric-${label}`;
const key = document.createElement("span");
key.textContent = label;
const val = document.createElement("strong");
val.textContent = value;
metric.append(key, val);
return metric;
}
function participationLabel(participation) {
if (!participation) return "Latest ranking";
if (participation.qualification && participation.fullEvaluation) return "Qualification + full";
if (participation.fullEvaluation) return "Full evaluation";
return "Qualification";
}
function renderParticipation(participation) {
const badge = document.createElement("span");
badge.className = "entry-badge";
if (participation?.fullEvaluation) badge.classList.add("entry-full");
badge.textContent = participationLabel(participation);
return badge;
}
function stageScoreText(score, status) {
if (score != null) return score.toFixed(4);
if (status === "not_selected") return "not selected";
if (status === "failed" || status === "rejected" || status === "skipped") return statusLabel(status);
if (status === "evaluating") return "evaluating";
return "pending";
}
function renderScoreCell(score, status, className) {
const cell = document.createElement("td");
cell.className = `score-val ${className}`;
cell.textContent = stageScoreText(score, status);
if (score == null) cell.classList.add("score-pending");
return cell;
}
function renderBoard(view) {
const rankings = view.rankings;
const body = $("board-body");
body.innerHTML = "";
$("board-empty").hidden = rankings.length > 0;
$("ranking-subtitle").textContent = view.hasCurrentRound
? `Stage scores from epoch ${view.progress?.epoch ?? "-"}`
: "Waiting for current-round participation";
let displayedRank = 0;
rankings.forEach((r) => {
const tr = document.createElement("tr");
const hasFullScore = r.fullEvaluationScore != null;
if (hasFullScore) displayedRank += 1;
tr.className = hasFullScore ? "rank-" + displayedRank : "rank-pending";
if (displayedRank === 1 && hasFullScore) tr.classList.add("is-king");
const sk = shortKey(r.hotkey);
const rankCell = document.createElement("td");
rankCell.className = "c-rank";
const rank = document.createElement("span");
rank.className = "rank-num";
rank.textContent = hasFullScore ? String(displayedRank).padStart(2, "0") : "--";
rankCell.appendChild(rank);
const hotkeyCell = document.createElement("td");
const hotkey = document.createElement("span");
hotkey.className = "hotkey";
const head = document.createElement("span");
head.className = "head";
head.textContent = sk.head;
const tail = document.createElement("span");
tail.className = "tail";
tail.textContent = sk.tail;
hotkey.append(head, tail);
hotkeyCell.appendChild(hotkey);
if (displayedRank === 1 && hasFullScore) {
const king = document.createElement("span");
king.className = "king-badge";
king.textContent = "\u265B King";
hotkeyCell.appendChild(king);
tr.setAttribute("aria-label", `King: ${r.hotkey}`);
}
const stageCell = document.createElement("td");
stageCell.className = "c-stage";
stageCell.appendChild(renderParticipation(r.participation));
const qualificationCell = renderScoreCell(
r.qualificationScore,
r.participation?.qualificationStatus,
"c-qualification",
);
const fullEvaluationCell = renderScoreCell(
r.fullEvaluationScore,
r.participation?.fullEvaluationStatus,
"c-full-evaluation",
);
tr.append(rankCell, hotkeyCell, stageCell, qualificationCell, fullEvaluationCell);
body.appendChild(tr);
});
renderPreviousBoard(view.previousRankings, view.previousEpoch);
renderOlderBoard(view.olderRankings);
}
function renderPreviousBoard(rankings, epoch) {
const section = $("previous-rankings");
const body = $("previous-board-body");
body.innerHTML = "";
section.hidden = !rankings.length;
$("previous-count").textContent = epoch == null
? `${rankings.length} miners`
: `${rankings.length} miners · epoch ${epoch}`;
for (const row of rankings) {
const tr = document.createElement("tr");
const rankCell = document.createElement("td");
rankCell.className = "c-rank";
rankCell.textContent = row.previousRank == null ? "--" : String(row.previousRank).padStart(2, "0");
const hotkeyCell = document.createElement("td");
appendHotkey(hotkeyCell, row.hotkey);
const statusCell = document.createElement("td");
statusCell.className = "c-round-status";
const status = document.createElement("span");
status.className = row.isCurrent ? "entry-badge" : "status-pill status-stale";
status.textContent = row.isCurrent ? "also current" : "stale";
statusCell.appendChild(status);
const qualificationCell = renderScoreCell(row.qualificationScore, null, "c-qualification");
const fullEvaluationCell = renderScoreCell(row.fullEvaluationScore, null, "c-full-evaluation");
const finalScoreCell = renderScoreCell(row.finalScore, null, "c-final-score");
if (row.qualificationScore == null) qualificationCell.textContent = "-";
if (row.fullEvaluationScore == null) fullEvaluationCell.textContent = "-";
if (row.finalScore == null) finalScoreCell.textContent = "-";
tr.append(
rankCell,
hotkeyCell,
statusCell,
qualificationCell,
fullEvaluationCell,
finalScoreCell,
);
body.appendChild(tr);
}
}
function renderOlderBoard(rankings) {
const section = $("older-rankings");
const body = $("older-board-body");
body.innerHTML = "";
section.hidden = !rankings.length;
$("older-count").textContent = `${rankings.length} stale`;
for (const row of rankings) {
const tr = document.createElement("tr");
const epochCell = document.createElement("td");
epochCell.className = "c-rank";
epochCell.textContent = String(row.lastScoredEpoch);
const hotkeyCell = document.createElement("td");
appendHotkey(hotkeyCell, row.hotkey);
const qualificationCell = renderScoreCell(row.qualificationScore, null, "c-qualification");
const fullEvaluationCell = renderScoreCell(row.fullEvaluationScore, null, "c-full-evaluation");
const finalScoreCell = renderScoreCell(row.finalScore, null, "c-final-score");
if (row.qualificationScore == null) qualificationCell.textContent = "-";
if (row.fullEvaluationScore == null) fullEvaluationCell.textContent = "-";
tr.append(epochCell, hotkeyCell, qualificationCell, fullEvaluationCell, finalScoreCell);
body.appendChild(tr);
}
}
function hasPoints(arr) {
return Array.isArray(arr) && arr.some((x) => x !== null && x !== undefined && !Number.isNaN(x));
}
function topAccuracySeries(history) {
const epochs = history?.epochs || [];
const correctnessScore = [];
const completionLen = [];
const winners = [];
for (let index = 0; index < epochs.length; index += 1) {
let winner = null;
for (const [hotkey, series] of Object.entries(history?.miners || {})) {
const accuracy = numericScore(series?.correctness_score?.[index]);
if (accuracy == null) continue;
const tokens = numericScore(series?.completion_len?.[index]);
const betterAccuracy = winner == null || accuracy > winner.accuracy;
const betterTie = winner != null && accuracy === winner.accuracy && (
(tokens ?? Infinity) < (winner.tokens ?? Infinity)
|| ((tokens ?? Infinity) === (winner.tokens ?? Infinity) && hotkey < winner.hotkey)
);
if (betterAccuracy || betterTie) winner = { hotkey, accuracy, tokens };
}
correctnessScore.push(winner?.accuracy ?? null);
completionLen.push(winner?.tokens ?? null);
winners.push(winner?.hotkey ?? null);
}
return {
epochs,
miner: { correctness_score: correctnessScore, completion_len: completionLen },
original: history?.original || null,
winners,
};
}
function renderTrends(view) {
const s = topAccuracySeries(view.history);
let latestIndex = s.miner.correctness_score.length - 1;
while (latestIndex >= 0 && s.miner.correctness_score[latestIndex] == null) latestIndex -= 1;
const completedEpoch = latestIndex >= 0 ? s.epochs[latestIndex] : null;
$("trend-miner").textContent = "Best accuracy each epoch";
$("trend-epoch").textContent = completedEpoch == null ? "waiting" : `through ${completedEpoch}`;
drawTrend("score", s, "correctness_score");
drawTrend("len", s, "completion_len");
}
function drawTrend(which, s, field) {
const canvasId = which === "score" ? "chart-score" : "chart-len";
const awaitId = which === "score" ? "await-score" : "await-len";
const minerData = s?.miner?.[field];
const origData = s?.original?.[field];
const ok = s && s.epochs.length && (hasPoints(minerData) || hasPoints(origData));
$(awaitId).hidden = !!ok;
if (!ok) {
destroyChart(which);
return;
}
const ctx = $(canvasId).getContext("2d");
const datasets = [];
if (hasPoints(minerData)) {
datasets.push(lineDS("Top miner", minerData, ACCENT, css("--accent-ghost"), false, s.winners));
}
if (hasPoints(origData)) datasets.push(lineDS("Base model", origData, BASE, "transparent", true));
const cfg = {
type: "line",
data: { labels: s.epochs, datasets },
options: chartOptions(which === "len" ? "tokens" : "accuracy", which === "score"),
};
destroyChart(which);
const chart = new Chart(ctx, cfg);
if (which === "score") scoreChart = chart; else lenChart = chart;
}
function lineDS(label, data, color, fill, dashed = false, winnerHotkeys = null) {
return {
label, data,
borderColor: color,
backgroundColor: fill,
borderWidth: 2,
borderDash: dashed ? [5, 4] : [],
pointRadius: 0,
pointHoverRadius: 4,
tension: 0.25,
fill: !dashed,
spanGaps: true,
winnerHotkeys,
};
}
function chartOptions(yLabel, signed = false) {
const grid = css("--line-soft");
const tick = css("--faint");
return {
responsive: true,
maintainAspectRatio: false,
interaction: { mode: "index", intersect: false },
plugins: {
legend: { labels: { color: css("--muted"), boxWidth: 10, boxHeight: 10, usePointStyle: true, font: { size: 11 } } },
tooltip: {
backgroundColor: "#0b0e12", borderColor: css("--line"), borderWidth: 1,
titleColor: css("--muted"), bodyColor: css("--text"), padding: 10, displayColors: true,
callbacks: {
afterLabel(context) {
const hotkey = context.dataset.winnerHotkeys?.[context.dataIndex];
if (!hotkey) return "";
const sk = shortKey(hotkey);
return `miner ${sk.head}${sk.tail}`;
},
},
},
},
scales: {
x: { title: { display: true, text: "epoch", color: tick, font: { size: 10 } }, grid: { color: grid }, ticks: { color: tick, font: { size: 10 } } },
y: {
title: { display: true, text: yLabel, color: tick, font: { size: 10 } },
min: signed ? -1 : undefined,
max: signed ? 1 : undefined,
grid: { color: grid },
ticks: { color: tick, font: { size: 10 } },
},
},
};
}
function destroyChart(which) {
if (which === "score" && scoreChart) { scoreChart.destroy(); scoreChart = null; }
if (which === "len" && lenChart) { lenChart.destroy(); lenChart = null; }
}
window.addEventListener("DOMContentLoaded", load);