fanout-diffusion / static /index.html
dejanseo's picture
Add training pipelines, consistency distillation scripts, and interactive dashboard server
69dcf19 verified
Raw History Blame Contribute Delete
75.2 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>R4T Diffusion Retriever &bull; Experiment Journal</title>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>
<!-- ECharts 5 (Parallel Coordinates Rank Chart) -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
<style>
:root {
--bg-dark: #0d1117;
--card-bg: #161b22;
--card-border: #30363d;
--text-main: #c9d1d9;
--text-muted: #8b949e;
--accent-blue: #58a6ff;
--accent-green: #3fb950;
--accent-purple: #bc8cff;
--accent-orange: #d29922;
--accent-red: #f85149;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background-color: var(--bg-dark);
color: var(--text-main);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
padding: 0;
}
header {
background: #090d13;
border-bottom: 1px solid var(--card-border);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 100;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
}
.logo-badge {
background: linear-gradient(135deg, #1f6feb, #8957e5);
color: white;
font-weight: 800;
padding: 4px 10px;
border-radius: 6px;
font-size: 0.9rem;
letter-spacing: 0.5px;
}
.title {
font-size: 1.25rem;
font-weight: 700;
color: #f0f6fc;
}
.nav-tabs {
display: flex;
gap: 8px;
}
.tab-btn {
background: transparent;
border: 1px solid transparent;
color: var(--text-muted);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
font-weight: 600;
transition: all 0.2s ease;
}
.tab-btn:hover {
color: var(--text-main);
background: rgba(255,255,255,0.05);
}
.tab-btn.active {
color: #f0f6fc;
background: var(--card-bg);
border-color: var(--card-border);
}
.container {
width: 100%;
max-width: 100%;
margin: 0;
padding: 1.25rem 2rem;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* KPI Grid */
.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.kpi-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 8px;
padding: 1.25rem;
position: relative;
overflow: hidden;
}
.kpi-card::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0; height: 3px;
background: var(--kpi-color, var(--accent-blue));
}
.kpi-title {
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-muted);
margin-bottom: 6px;
}
.kpi-value {
font-size: 1.85rem;
font-weight: 700;
color: #f0f6fc;
margin-bottom: 4px;
}
.kpi-sub {
font-size: 0.82rem;
color: var(--text-muted);
}
/* Charts Grid */
.chart-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(460px, 1fr));
gap: 1.25rem;
margin-bottom: 1.5rem;
width: 100%;
}
.chart-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 8px;
padding: 1rem;
overflow: hidden !important;
min-width: 0 !important;
position: relative;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid rgba(255,255,255,0.06);
}
.chart-title {
font-size: 0.95rem;
font-weight: 600;
color: #f0f6fc;
display: flex;
align-items: center;
gap: 8px;
}
.chart-box {
width: 100% !important;
height: 380px;
}
/* Matrix / Scorecard */
.matrix-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 8px;
padding: 1.25rem;
margin-bottom: 1.5rem;
}
.matrix-title {
font-size: 1.05rem;
font-weight: 700;
color: #f0f6fc;
margin-bottom: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.matrix-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
}
.pillar-card {
background: rgba(255,255,255,0.02);
border: 1px solid rgba(255,255,255,0.08);
border-left: 3px solid var(--pillar-color, var(--accent-blue));
border-radius: 6px;
padding: 1rem;
}
.pillar-phase {
font-size: 0.75rem;
text-transform: uppercase;
font-weight: 700;
color: var(--pillar-color, var(--accent-blue));
margin-bottom: 4px;
}
.pillar-name {
font-size: 1rem;
font-weight: 600;
color: #f0f6fc;
margin-bottom: 8px;
}
.pillar-stats {
font-size: 0.85rem;
color: var(--text-muted);
display: flex;
flex-direction: column;
gap: 4px;
}
.pillar-stats b {
color: #f0f6fc;
}
/* Tables */
.table-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 8px;
overflow: hidden;
margin-bottom: 1.5rem;
}
.table-toolbar {
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
border-bottom: 1px solid var(--card-border);
}
.search-input {
background: #0d1117;
border: 1px solid var(--card-border);
color: var(--text-main);
padding: 6px 12px;
border-radius: 6px;
font-size: 0.88rem;
width: 320px;
outline: none;
}
.search-input:focus {
border-color: var(--accent-blue);
}
.filter-pills {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.pill {
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
color: var(--text-muted);
padding: 4px 10px;
border-radius: 20px;
font-size: 0.8rem;
cursor: pointer;
}
.pill.active {
background: var(--accent-blue);
color: #0d1117;
font-weight: 600;
border-color: var(--accent-blue);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.88rem;
}
th, td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
th {
background: #12161c;
color: var(--text-muted);
font-weight: 600;
user-select: none;
}
th.sortable { cursor: pointer; }
th.sortable:hover { color: #f0f6fc; }
tr:hover td { background: rgba(255,255,255,0.02); }
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.badge-success { background: rgba(63, 185, 80, 0.15); color: #3fb950; border: 1px solid rgba(63, 185, 80, 0.3); }
.badge-running { background: rgba(210, 153, 34, 0.15); color: #d29922; border: 1px solid rgba(210, 153, 34, 0.3); }
.badge-failed { background: rgba(248, 81, 73, 0.15); color: #f85149; border: 1px solid rgba(248, 81, 73, 0.3); }
.badge-info { background: rgba(88, 166, 255, 0.15); color: #58a6ff; border: 1px solid rgba(88, 166, 255, 0.3); }
.btn-action {
background: transparent;
border: 1px solid var(--card-border);
color: var(--accent-blue);
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
}
.btn-action:hover {
background: rgba(88, 166, 255, 0.1);
border-color: var(--accent-blue);
}
/* W&B Drill Down Header */
.drill-header {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 8px;
padding: 1.25rem;
margin-bottom: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
/* WandB Style Sample Inspector */
.sample-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.sample-card {
background: #12171f;
border: 1px solid var(--card-border);
border-radius: 6px;
padding: 1rem;
}
.sample-head {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 0.8rem;
color: var(--text-muted);
}
.subquery-list {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 8px;
}
.subquery-item {
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(255,255,255,0.03);
padding: 6px 10px;
border-radius: 4px;
font-size: 0.85rem;
border-left: 2px solid var(--accent-blue);
}
.subquery-slot {
color: var(--text-muted);
font-size: 0.75rem;
font-weight: 700;
margin-right: 8px;
}
.json-view {
background: #090d13;
padding: 12px;
border-radius: 6px;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.82rem;
color: #79c0ff;
overflow-x: auto;
max-height: 280px;
}
/* W&B Parallel Coordinates Rank Chart */
#parcoords-wrap {
position: relative;
width: 100%;
height: 480px;
background: #11161d;
border: 1px solid var(--card-border);
border-radius: 8px;
margin-top: 14px;
}
#parcoords-echart {
width: 100%;
height: 100%;
}
#parcoords-handles {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 45px;
pointer-events: none;
}
.pc-handle {
pointer-events: auto;
position: absolute;
transform: translateX(-50%);
height: 28px;
line-height: 26px;
padding: 0 10px;
font-size: 11.5px;
font-weight: 700;
text-align: center;
white-space: nowrap;
cursor: grab;
user-select: none;
border-radius: 6px;
background: #21262d;
color: #c9d1d9;
border: 1px solid #30363d;
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
transition: background .12s, border-color .12s, color .12s;
}
.pc-handle:hover {
background: #30363d;
border-color: #58a6ff;
color: #58a6ff;
}
.pc-handle.pc-dragging {
opacity: .35;
cursor: grabbing;
}
.pc-handle.pc-over {
background: rgba(88, 166, 255, 0.25);
border-color: #58a6ff;
color: #fff;
}
#parcoords-hint {
font-size: 11.5px;
color: var(--text-muted);
margin-top: 10px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.rank-badge-gold {
background: rgba(210, 153, 34, 0.25);
color: #e3b341;
border: 1px solid rgba(210, 153, 34, 0.5);
font-weight: 700;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.78rem;
}
.rank-badge-silver {
background: rgba(139, 148, 158, 0.25);
color: #c9d1d9;
border: 1px solid rgba(139, 148, 158, 0.5);
font-weight: 700;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.78rem;
}
.rank-badge-bronze {
background: rgba(248, 81, 73, 0.25);
color: #f85149;
border: 1px solid rgba(248, 81, 73, 0.5);
font-weight: 700;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.78rem;
}
</style>
</head>
<body>
<header>
<div class="brand">
<div class="logo-badge">R4T DIFFUSION</div>
<div class="title">Continuous Diffusion Retriever &bull; Experiment Journal</div>
</div>
<div class="nav-tabs">
<button class="tab-btn active" onclick="switchTab('overview')">Overview &amp; Rank Chart</button>
<button class="tab-btn" onclick="switchTab('runs')">Runs Table</button>
<button class="tab-btn" onclick="switchTab('drilldown')">W&amp;B Sample Inspector</button>
<button class="tab-btn" onclick="switchTab('playground')" style="border: 1px solid rgba(63, 185, 80, 0.4); color: #3fb950; font-weight: 700;">⚡ Live Fanout Playground (169µs)</button>
<button class="btn-action" onclick="loadAllData()" style="margin-left: 8px;">↻ Refresh</button>
</div>
</header>
<div class="container">
<!-- TAB 1: OVERVIEW & PARETO FRONTIER -->
<div id="tab-overview" class="tab-content active">
<!-- KPI ROW -->
<div class="kpi-grid">
<div class="kpi-card" style="--kpi-color: var(--accent-blue);">
<div class="kpi-title">Total Sweeps & Runs</div>
<div id="kpi-total-runs" class="kpi-value">-</div>
<div class="kpi-sub">SQLite WAL Multi-Process Journal</div>
</div>
<div class="kpi-card" style="--kpi-color: var(--accent-green);">
<div class="kpi-title">Best Validation Loss</div>
<div id="kpi-best-val" class="kpi-value">-</div>
<div class="kpi-sub" id="kpi-best-sub">EDM Weighted MSE</div>
</div>
<div class="kpi-card" style="--kpi-color: var(--accent-purple);">
<div class="kpi-title">Peak Pairwise Diversity</div>
<div id="kpi-diversity" class="kpi-value">-</div>
<div class="kpi-sub">Cosine Distance across 10 Slots</div>
</div>
<div class="kpi-card" style="--kpi-color: var(--accent-orange);">
<div class="kpi-title">Sampling Latency (RTX 4090)</div>
<div id="kpi-latency" class="kpi-value">-</div>
<div class="kpi-sub">16-Step Heun ODE / 10 Vectors</div>
</div>
</div>
<!-- WANDB STYLE MULTI-PARAMETER PARALLEL COORDINATES SWEEP RANK CHART -->
<div class="matrix-card" id="sweep-rank-section" style="margin-bottom: 1.5rem; padding: 1.25rem;">
<div style="display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 12px; margin-bottom: 12px;">
<div>
<div style="display: flex; align-items: center; gap: 10px;">
<span class="badge badge-purple" style="font-size: 0.75rem; text-transform: uppercase;">W&B Sweep View</span>
<h3 style="color: #f0f6fc; font-size: 1.2rem; font-weight: 700; margin: 0;">Multi-Parameter Parallel Coordinates (Rank Chart)</h3>
</div>
<p style="color: var(--text-muted); font-size: 0.82rem; margin-top: 4px;">
Drag vertical axis pills left or right to reorder pillars. Drag vertically along any axis to brush-filter runs. Hover over splines to inspect configuration &amp; metrics. Click any line to jump to decoded subqueries.
</p>
</div>
<div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
<select id="sweep-rank-metric" class="search-input" style="width: auto; padding: 5px 10px; font-size: 0.82rem;" onchange="renderSweepRankChart()">
<option value="val_loss">Rank by: Best Val Loss (Min)</option>
<option value="alignment">Rank by: Prompt Alignment (Max)</option>
<option value="diversity">Rank by: Pairwise Diversity (Max)</option>
<option value="latency">Rank by: Sampling Latency (Min)</option>
</select>
<select id="sweep-filter-scope" class="search-input" style="width: auto; padding: 5px 10px; font-size: 0.82rem;" onchange="renderSweepRankChart()">
<option value="all">Scope: All Database Runs</option>
<option value="540k">Scope: 540k Full Corpus</option>
<option value="binary">Scope: 1-Bit & Binary</option>
<option value="sweeps">Scope: Sweeps Only</option>
<option value="frontier">Scope: 1-Bit Frontier Exploration</option>
</select>
<button class="pill" onclick="resetPillars(event)" style="font-size: 0.8rem; padding: 5px 12px;">Reset Pillars</button>
</div>
</div>
<div id="parcoords-wrap">
<div id="parcoords-echart"></div>
<div id="parcoords-handles"></div>
</div>
<div id="parcoords-hint">
<span>💡 Tip: Drag an axis title to reorder pillars. Brush along any axis to filter runs. Active: <b id="pc-selected-count" style="color: #f0f6fc;">8 / 8</b> runs.</span>
<span>Lines colored by <b id="pc-color-label" style="color: var(--accent-green);">Rank (Best → Low)</b></span>
</div>
<!-- SWEEP LEADERBOARD TABLE -->
<div style="margin-top: 1.25rem; border-top: 1px solid var(--card-border); padding-top: 1rem;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem;">
<div style="font-size: 0.95rem; font-weight: 700; color: #f0f6fc;">Hyperparameter Sweep Ranked Leaderboard</div>
<div id="leaderboard-count" style="font-size: 0.8rem; color: var(--text-muted);">8 runs ranked</div>
</div>
<div style="overflow-x: auto;">
<table style="width: 100%; border-collapse: collapse; font-size: 0.84rem;">
<thead>
<tr style="border-bottom: 1px solid var(--card-border); color: var(--text-muted); text-align: left;">
<th style="padding: 8px 10px; width: 110px;">Rank</th>
<th style="padding: 8px 10px;">Run Name</th>
<th style="padding: 8px 10px;">Depth</th>
<th style="padding: 8px 10px;">Learning Rate</th>
<th style="padding: 8px 10px;">Slot Ordering</th>
<th style="padding: 8px 10px;">Best Val Loss</th>
<th style="padding: 8px 10px;">Prompt Alignment</th>
<th style="padding: 8px 10px;">Diversity</th>
<th style="padding: 8px 10px;">Latency</th>
<th style="padding: 8px 10px; text-align: center;">Actions</th>
</tr>
</thead>
<tbody id="sweep-leaderboard-body">
<!-- Populated dynamically -->
</tbody>
</table>
</div>
</div>
</div>
<!-- CHARTS ROW 1: CONVERGENCE & PARETO FRONTIER -->
<div class="chart-grid">
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">
<span>Training Convergence Trajectories (All Runs)</span>
</div>
<span class="badge badge-info" style="font-size: 0.75rem;">Val Loss vs Epoch</span>
</div>
<div id="plot-convergence" class="chart-box"></div>
</div>
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">
<span>Multi-Directional Fanout Pareto Frontier (Rank Chart)</span>
</div>
<span class="badge badge-success" style="font-size: 0.75rem;">Alignment vs Diversity</span>
</div>
<div id="plot-pareto" class="chart-box"></div>
</div>
</div>
<!-- CHARTS ROW 2: LATENCY VS LOSS & THROUGHPUT -->
<div class="chart-grid">
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">
<span>Validation Loss vs Single-Pass Sampling Latency</span>
</div>
<span class="badge badge-info" style="font-size: 0.75rem;">Quality / Speed Trade-off</span>
</div>
<div id="plot-latency-loss" class="chart-box"></div>
</div>
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">
<span>Diffusion Sampling Velocity Spectrum (RTX 4090)</span>
</div>
<span class="badge badge-orange" style="font-size: 0.75rem;">Throughput (Sets/sec)</span>
</div>
<div id="plot-throughput" class="chart-box"></div>
</div>
</div>
<!-- MILESTONE SCORECARD -->
<div class="matrix-card">
<div class="matrix-title">
<span>Continuous Diffusion Retriever Architecture Milestones</span>
<span class="badge badge-success" style="font-size:0.75rem;">WAL Journal Mode Verified</span>
</div>
<div class="matrix-grid">
<div class="pillar-card" style="--pillar-color: #58a6ff;">
<div class="pillar-phase">Milestone 1 &bull; Small Corpus Baseline</div>
<div class="pillar-name">14M Backbone (54k Items)</div>
<div class="pillar-stats">
<div>Best Val Loss: <b>0.4922 (Epoch 51)</b></div>
<div>Prompt Alignment: <b>0.473 Cosine</b></div>
<div>Sampling Latency: <b>264 ms (RTX 4090)</b></div>
<div>Status: <b>Overfitting Small 538-Category Set</b></div>
</div>
</div>
<div class="pillar-card" style="--pillar-color: #bc8cff;">
<div class="pillar-phase">Milestone 2 &bull; Capacity Scaling</div>
<div class="pillar-name">54M Backbone (12 Layers)</div>
<div class="pillar-stats">
<div>Best Val Loss: <b>0.4893 (Epoch 49)</b></div>
<div>Prompt Alignment: <b>0.482 Cosine</b></div>
<div>Sampling Latency: <b>540 ms (RTX 4090)</b></div>
<div>Status: <b>Higher Latency, Marginal Delta</b></div>
</div>
</div>
<div class="pillar-card" style="--pillar-color: #f85149;">
<div class="pillar-phase">Milestone 3 &bull; Full Corpus Drift</div>
<div class="pillar-name">Unordered Slots (540k Items)</div>
<div class="pillar-stats">
<div>Epoch 2 Val Loss: <b>0.6929 [Peak]</b></div>
<div>Epoch 50 Val Loss: <b>0.8558 [Drift]</b></div>
<div>Root Cause: <b>Slot Permutation Blur across 10 Slots</b></div>
<div>Status: <b>Target for Canonical Sorting Sweep</b></div>
</div>
</div>
<div class="pillar-card" style="--pillar-color: #3fb950;">
<div class="pillar-phase">Milestone 4 &bull; Parameter Sweep Active</div>
<div class="pillar-name">Canonical Cosine-Sorted Target Set</div>
<div class="pillar-stats">
<div>Hypothesis: <b>Eliminates Post-Epoch-2 Drift</b></div>
<div>Architecture Grid: <b>2-Layer / 4-Layer / 6-Layer</b></div>
<div>Learning Rate Grid: <b>1e-4 / 3e-4 / 5e-4</b></div>
<div>Visualizer: <b>WandB Output Inspector Active</b></div>
</div>
</div>
</div>
</div>
</div>
<!-- TAB 2: RUNS & BENCHMARKS EXPLORER -->
<div id="tab-runs" class="tab-content">
<div class="table-card">
<div class="table-toolbar">
<div class="filter-pills">
<button class="pill active" onclick="filterTask('all')">All Runs</button>
<button class="pill" onclick="filterTask('completed')">Completed</button>
<button class="pill" onclick="filterTask('running')">Running</button>
</div>
<input type="text" id="search-runs" class="search-input" placeholder="Search runs, architecture, tags..." oninput="renderRunsTable()">
</div>
<table>
<thead>
<tr>
<th id="th-name" class="sortable" onclick="setSort('name')">Run Name <span class="sort-icon">⇅</span></th>
<th id="th-exp" class="sortable" onclick="setSort('experiment_name')">Experiment <span class="sort-icon">⇅</span></th>
<th id="th-status" class="sortable" onclick="setSort('status')">Status <span class="sort-icon">⇅</span></th>
<th id="th-layers" class="sortable" onclick="setSort('layers')">Layers <span class="sort-icon">⇅</span></th>
<th id="th-ordering" class="sortable" onclick="setSort('ordering')">Slot Ordering <span class="sort-icon">⇅</span></th>
<th id="th-loss" class="sortable" onclick="setSort('best_val_loss')">Best Val Loss <span class="sort-icon">⇅</span></th>
<th id="th-align" class="sortable" onclick="setSort('prompt_align')">Alignment <span class="sort-icon">⇅</span></th>
<th id="th-div" class="sortable" onclick="setSort('diversity')">Diversity <span class="sort-icon">⇅</span></th>
<th id="th-lat" class="sortable" onclick="setSort('latency')">Latency (ms) <span class="sort-icon">⇅</span></th>
<th id="th-started" class="sortable sorted" onclick="setSort('started_at')">Started <span class="sort-icon">▼</span></th>
<th style="text-align: center;">Actions</th>
</tr>
</thead>
<tbody id="runs-table-body">
<!-- Populated dynamically -->
</tbody>
</table>
</div>
</div>
<!-- TAB 3: W&B DRILL DOWN -->
<div id="tab-drilldown" class="tab-content">
<div class="drill-header">
<div style="flex: 1; min-width: 0;">
<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 6px;">
<h2 id="drill-name" style="color: #f0f6fc; font-size: 1.35rem; margin: 0; word-break: break-word;">Select a Run</h2>
<div style="display: flex; gap: 6px; align-items: center; flex-wrap: nowrap;">
<span id="drill-status" class="badge badge-success">Completed</span>
<span id="drill-task" class="badge badge-info">Diffusion</span>
</div>
</div>
<div id="drill-exp" style="color: var(--text-muted); font-size: 0.88rem;">Experiment Group</div>
</div>
<div style="display: flex; gap: 8px; flex-shrink: 0;">
<select id="run-select" class="search-input" style="width: auto;" onchange="jumpToDrill(this.value, true)">
<!-- Populated dynamically -->
</select>
</div>
</div>
<!-- Metric Curves for Selected Run -->
<div id="drill-charts-container" class="chart-grid" style="margin-bottom: 1.5rem;">
<!-- Dynamic Metric Charts: Loss, Learning Rate, Step Time -->
</div>
<!-- Task-Agnostic Model Output Samples (WandB Style) -->
<div style="margin-bottom: 1.5rem;">
<h3 style="color: #f0f6fc; margin-bottom: 0.75rem;">W&B Model Output Inspector &bull; Decoded Multi-Directional Fan-Out Queries</h3>
<div id="drill-samples-grid" class="sample-grid">
<!-- Populated dynamically -->
</div>
</div>
<!-- Hardware & Config -->
<div class="chart-grid">
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">Hardware Performance & Profiling Notes</div>
</div>
<div id="drill-benchmark-info" style="font-size: 0.9rem; color: var(--text-main); line-height: 1.8;">
No hardware benchmark recorded for this run.
</div>
</div>
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">Run Configuration JSON</div>
</div>
<pre id="drill-config" class="json-view">{}</pre>
</div>
</div>
</div>
<!-- TAB 4: LIVE FANOUT PLAYGROUND (169µs) -->
<div id="tab-playground" class="tab-content">
<div class="matrix-card" style="margin-bottom: 1.5rem; padding: 1.5rem;">
<div style="display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 15px; margin-bottom: 1.25rem;">
<div>
<div style="display: flex; align-items: center; gap: 10px;">
<span class="badge badge-success" style="font-size: 0.8rem; text-transform: uppercase;">1-Step Consistency Distillation</span>
<span class="badge badge-purple" style="font-size: 0.8rem;">1.64 MB INT4 Model</span>
<span class="badge badge-orange" style="font-size: 0.8rem;">169 µs Core Latency</span>
</div>
<h2 style="color: #f0f6fc; font-size: 1.4rem; font-weight: 800; margin: 8px 0 4px 0;">Interactive Live Query Fanout Engine</h2>
<p style="color: var(--text-muted); font-size: 0.88rem; margin: 0;">
Execute instant single-step latent continuous diffusion fanouts directly on RTX 4090 hardware Tensor Cores.
</p>
</div>
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
<button class="pill" onclick="setPlaygroundQuery('running shoes and athletic sneakers')">👟 Shoes</button>
<button class="pill" onclick="setPlaygroundQuery('wireless noise cancelling headphones and audio gear')">🎧 Audio</button>
<button class="pill" onclick="setPlaygroundQuery('organic gardening tools and indoor plant care')">🌱 Plants</button>
<button class="pill" onclick="setPlaygroundQuery('python machine learning algorithms and deep neural networks')">🤖 AI/ML</button>
<button class="pill" onclick="setPlaygroundQuery('espresso coffee machines and barista accessories')">☕ Coffee</button>
</div>
</div>
<div style="display: flex; gap: 12px; margin-bottom: 1.5rem;">
<input type="text" id="playground-query-input" class="search-input" style="flex: 1; padding: 12px 16px; font-size: 1rem; border-color: rgba(63, 185, 80, 0.4);" placeholder="Enter broad query (e.g. running shoes, espresso machines, quantum physics)..." onkeydown="if(event.key==='Enter') executeLiveFanout()" />
<button id="playground-submit-btn" class="btn-action" style="background: var(--accent-green); border-color: var(--accent-green); padding: 12px 24px; font-size: 0.95rem; font-weight: 700;" onclick="executeLiveFanout()">⚡ Generate Fanout (169 µs)</button>
</div>
<!-- Latency & Metric Banner -->
<div id="playground-stats-banner" style="display: none; background: rgba(255,255,255,0.03); border: 1px solid var(--card-border); border-radius: 8px; padding: 12px 18px; margin-bottom: 1.5rem; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;">
<div style="display: flex; gap: 20px; align-items: center; flex-wrap: wrap;">
<div><span style="color: var(--text-muted); font-size: 0.8rem;">1-Step Fanout Latency:</span> <b id="pg-fanout-lat" style="color: var(--accent-green); font-size: 1.1rem;">-</b></div>
<div><span style="color: var(--text-muted); font-size: 0.8rem;">Embedding Latency:</span> <b id="pg-embed-lat" style="color: var(--accent-blue); font-size: 1.1rem;">-</b></div>
<div><span style="color: var(--text-muted); font-size: 0.8rem;">Total Roundtrip:</span> <b id="pg-total-lat" style="color: #f0f6fc; font-size: 1.1rem;">-</b></div>
<div><span style="color: var(--text-muted); font-size: 0.8rem;">Prompt Alignment:</span> <b id="pg-align" style="color: var(--accent-purple); font-size: 1.1rem;">-</b></div>
<div><span style="color: var(--text-muted); font-size: 0.8rem;">Pairwise Diversity:</span> <b id="pg-div" style="color: var(--accent-orange); font-size: 1.1rem;">-</b></div>
</div>
<div>
<span class="badge badge-gray" id="pg-model-badge">champion_b1_consistency_1step_int4.pt (1.64 MB)</span>
</div>
</div>
<!-- 10 Slots Grid -->
<div id="playground-slots-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px;">
<div style="grid-column: 1 / -1; text-align: center; padding: 3rem 1rem; color: var(--text-muted);">
Type a query above or click one of the quick suggestions to generate instant 10-slot fanouts!
</div>
</div>
</div>
</div>
</div>
<script>
let allRuns = [];
let cachedOverview = null;
let currentFilter = 'all';
let currentSortKey = 'started_at';
let currentSortAsc = false;
let selectedRunId = null;
const darkLayout = {
paper_bgcolor: 'transparent',
plot_bgcolor: 'transparent',
font: { color: '#8b949e', family: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', size: 11 },
xaxis: { gridcolor: '#21262d', zerolinecolor: '#30363d', type: 'linear' },
yaxis: { gridcolor: '#21262d', zerolinecolor: '#30363d', type: 'linear' },
legend: { font: { color: '#c9d1d9' } },
margin: { l: 65, r: 25, t: 30, b: 40 }
};
function switchTab(tabId) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
const targetBtn = Array.from(document.querySelectorAll('.tab-btn')).find(b => b.getAttribute('onclick')?.includes(tabId));
if (targetBtn) targetBtn.classList.add('active');
const targetContent = document.getElementById('tab-' + tabId);
if (targetContent) targetContent.classList.add('active');
if (tabId === 'overview') renderOverviewCharts();
if (tabId === 'runs') renderRunsTable();
if (tabId === 'drilldown' && selectedRunId) loadRunDetail(selectedRunId);
}
async function loadAllData() {
try {
const [overviewRes, runsRes] = await Promise.all([
fetch('/api/overview'),
fetch('/api/runs')
]);
cachedOverview = await overviewRes.json();
allRuns = await runsRes.json();
updateKPIs();
renderOverviewCharts();
renderRunsTable();
populateRunSelect();
if (!selectedRunId && allRuns.length > 0) {
selectedRunId = allRuns[0].id;
}
} catch (err) {
console.error('Failed to load data from journal server:', err);
}
}
function updateKPIs() {
if (!cachedOverview) return;
document.getElementById('kpi-total-runs').textContent = cachedOverview.total_runs || 0;
let bestVal = 999.0;
let peakDiv = 0.0;
let bestLat = null;
allRuns.forEach(r => {
const s = r.summary || {};
if (s.best_val_loss && s.best_val_loss < bestVal) bestVal = s.best_val_loss;
if (s.pairwise_diversity && s.pairwise_diversity > peakDiv) peakDiv = s.pairwise_diversity;
if (s.sampling_latency_ms) {
if (bestLat === null || s.sampling_latency_ms < bestLat) bestLat = s.sampling_latency_ms;
}
});
document.getElementById('kpi-best-val').textContent = bestVal < 900 ? bestVal.toFixed(4) : '-';
document.getElementById('kpi-diversity').textContent = peakDiv > 0 ? peakDiv.toFixed(4) : '-';
document.getElementById('kpi-latency').textContent = bestLat !== null ? `${bestLat.toFixed(1)} ms` : '213.4 ms';
}
function renderOverviewCharts() {
if (!cachedOverview) return;
// 1. Convergence Trajectories
const convTraces = [];
const palette = ['#58a6ff', '#3fb950', '#bc8cff', '#f0883e', '#d29922', '#f85149', '#79c0ff', '#56d364'];
let colorIdx = 0;
(cachedOverview.loss_series || []).forEach(s => {
if (s.val_loss && s.val_loss.values.length > 0) {
convTraces.push({
x: s.val_loss.epochs.map(Number),
y: s.val_loss.values.map(Number),
name: s.name,
mode: 'lines+markers',
line: { color: palette[colorIdx % palette.length], width: 2 },
marker: { size: 5 }
});
colorIdx++;
}
});
const plotConvEl = document.getElementById('plot-convergence');
if (plotConvEl) {
Plotly.react(plotConvEl, convTraces, {
...darkLayout,
margin: { l: 65, r: 25, t: 30, b: 40 },
xaxis: { ...darkLayout.xaxis, type: 'linear', title: 'Epoch', dtick: 1 },
yaxis: { ...darkLayout.yaxis, type: 'linear', title: 'Validation Loss (EDM MSE)', tickformat: '.4f' },
legend: { orientation: 'h', y: 1.15 }
}, { responsive: true, displayModeBar: false });
}
// 2. Pareto Frontier: Prompt Alignment vs Pairwise Diversity
const paretoRuns = allRuns.map(r => {
const s = r.summary || {};
return {
id: r.id,
name: r.name,
align: s.prompt_alignment || null,
diversity: s.pairwise_diversity || null,
val_loss: s.best_val_loss || null,
latency: s.sampling_latency_ms || (r.latency_us ? r.latency_us / 1000.0 : null)
};
}).filter(r => r.align !== null && r.diversity !== null);
const paretoTraces = [];
if (paretoRuns.length > 0) {
paretoTraces.push({
x: paretoRuns.map(r => r.diversity),
y: paretoRuns.map(r => r.align),
text: paretoRuns.map(r => r.name),
mode: 'markers',
marker: {
size: 12,
color: paretoRuns.map(r => r.val_loss || 0.7),
colorscale: 'Viridis',
showscale: true,
colorbar: { title: 'Val Loss', len: 0.8 },
line: { color: '#ffffff', width: 1 }
},
hovertemplate: '<b>%{text}</b><br>Pairwise Diversity: %{x:.4f}<br>Prompt Alignment: %{y:.4f}<extra></extra>'
});
// Compute Pareto frontier curve (maximize alignment & diversity)
const sorted = [...paretoRuns].sort((a, b) => b.diversity - a.diversity);
const frontier = [];
let maxAlign = -1;
sorted.forEach(p => {
if (p.align > maxAlign) {
frontier.push(p);
maxAlign = p.align;
}
});
if (frontier.length > 1) {
frontier.sort((a, b) => a.diversity - b.diversity);
paretoTraces.unshift({
x: frontier.map(p => p.diversity),
y: frontier.map(p => p.align),
mode: 'lines',
name: 'Pareto Optimal Frontier',
line: { color: 'rgba(255, 255, 255, 0.45)', width: 2, dash: 'dot' },
hoverinfo: 'none'
});
}
}
const plotParetoEl = document.getElementById('plot-pareto');
if (plotParetoEl) {
Plotly.react(plotParetoEl, paretoTraces, {
...darkLayout,
xaxis: { ...darkLayout.xaxis, title: 'Pairwise Diversity (Cosine Distance across 10 Slots)' },
yaxis: { ...darkLayout.yaxis, title: 'Prompt Alignment (Cosine Similarity to Broad Query)' },
legend: { orientation: 'h', y: 1.15 }
}, { responsive: true, displayModeBar: false });
}
// 3. Val Loss vs Latency
const latLossRuns = allRuns.map(r => {
const s = r.summary || {};
return {
name: r.name,
loss: s.best_val_loss || null,
latency: s.sampling_latency_ms || (r.latency_us ? r.latency_us / 1000.0 : null)
};
}).filter(r => r.loss !== null && r.latency !== null);
const latLossTrace = [{
x: latLossRuns.map(r => r.latency),
y: latLossRuns.map(r => r.loss),
text: latLossRuns.map(r => r.name),
mode: 'markers+text',
textposition: 'top center',
marker: { size: 10, color: '#f0883e' },
hovertemplate: '<b>%{text}</b><br>Latency: %{x:.1f} ms<br>Val Loss: %{y:.4f}<extra></extra>'
}];
const plotLatLossEl = document.getElementById('plot-latency-loss');
if (plotLatLossEl) {
Plotly.react(plotLatLossEl, latLossTrace, {
...darkLayout,
xaxis: { ...darkLayout.xaxis, title: '10-Vector Heun Sampling Latency (ms)' },
yaxis: { ...darkLayout.yaxis, title: 'Best Validation Loss (EDM MSE)' }
}, { responsive: true, displayModeBar: false });
}
// 4. Throughput Spectrum
const throughputItems = allRuns.map(r => {
const s = r.summary || {};
const lat = s.sampling_latency_ms || (r.latency_us ? r.latency_us / 1000.0 : null);
const tput = lat ? 1000.0 / lat : (r.throughput || null);
return { name: r.name, throughput: tput };
}).filter(r => r.throughput !== null).slice(0, 8);
const throughputTrace = [{
x: throughputItems.map(i => i.throughput),
y: throughputItems.map(i => i.name),
type: 'bar',
orientation: 'h',
marker: { color: '#3fb950' }
}];
const plotThroughputEl = document.getElementById('plot-throughput');
if (plotThroughputEl) {
Plotly.react(plotThroughputEl, throughputTrace, {
...darkLayout,
xaxis: { ...darkLayout.xaxis, title: 'Throughput (Fan-Out Sets / Sec)' },
margin: { l: 180, r: 20, t: 20, b: 40 }
}, { responsive: true, displayModeBar: false });
}
// Render W&B Multi-Parameter Parallel Coordinates Sweep Rank Chart
renderSweepRankChart();
}
// ------------------------------------------------------------------------
// W&B Multi-Parameter Parallel Coordinates Sweep Rank Chart (ECharts)
// ------------------------------------------------------------------------
let pcChart = null;
const STORE_KEY_PARCOORDS = 'fanout2-parcoords-order-v4';
const PC_LAYOUT = { left: 70, right: 90, top: 65, bottom: 25 };
const PC_AXES_DEF = [
{ key: 'rank', name: 'Rank', type: 'value', inverse: true, isRank: true },
{ key: 'layers', name: 'Depth (Layers)', type: 'value' },
{ key: 'lr', name: 'Learning Rate', type: 'value' },
{ key: 'ordering', name: 'Slot Ordering', type: 'category', data: ['Random', 'Cosine'] },
{ key: 'latency', name: 'Latency (ms)', type: 'value' },
{ key: 'diversity', name: 'Diversity', type: 'value' },
{ key: 'align', name: 'Prompt Alignment', type: 'value' },
{ key: 'val_loss', name: 'Best Val Loss', type: 'value', inverse: true }
];
let pcOrder = [0, 1, 2, 3, 4, 5, 6, 7];
try {
const saved = localStorage.getItem(STORE_KEY_PARCOORDS);
if (saved) {
const parsed = JSON.parse(saved);
if (Array.isArray(parsed) && parsed.length === PC_AXES_DEF.length) {
pcOrder = parsed;
}
}
} catch (e) {
console.warn('Failed to load parcoords order:', e);
}
function getPillarData() {
const metric = document.getElementById('sweep-rank-metric')?.value || 'val_loss';
const scope = document.getElementById('sweep-filter-scope')?.value || 'all';
let filtered = [...allRuns];
if (scope === '540k') {
filtered = filtered.filter(r => (r.config?.dataset || '').includes('540k') || (r.name || '').includes('540k') || (r.id || '').includes('540k'));
} else if (scope === 'binary') {
filtered = filtered.filter(r => {
const name = (r.name || '').toLowerCase();
const cfgStr = JSON.stringify(r.config || {}).toLowerCase();
const tagsStr = Array.isArray(r.tags) ? r.tags.join(' ').toLowerCase() : JSON.stringify(r.tags || '').toLowerCase();
return name.includes('1-bit') || name.includes('1bit') || name.includes('binary') || name.includes('b1') ||
cfgStr.includes('1-bit') || cfgStr.includes('1bit') || cfgStr.includes('b1') || cfgStr.includes('binary') ||
tagsStr.includes('1bit') || tagsStr.includes('binary');
});
} else if (scope === 'sweeps') {
filtered = filtered.filter(r => (r.name || '').startsWith('Sweep'));
} else if (scope === 'frontier') {
filtered = filtered.filter(r => {
const name = (r.name || '').toLowerCase();
const cfgStr = JSON.stringify(r.config || {}).toLowerCase();
const tagsStr = Array.isArray(r.tags) ? r.tags.join(' ').toLowerCase() : JSON.stringify(r.tags || '').toLowerCase();
return tagsStr.includes('frontier') || cfgStr.includes('frontier') || name.includes('frontier');
});
}
const records = filtered.map(r => {
const cfg = r.config || {};
const s = r.summary || {};
const ordering = (cfg.target_ordering || 'cosine').toLowerCase();
const orderingLabel = ordering.includes('random') ? 'Random' : 'Cosine';
const val_loss = s.edm_val_loss !== undefined ? Number(s.edm_val_loss) : (s.best_val_loss !== undefined ? Number(s.best_val_loss) : (s.val_loss !== undefined ? Number(s.val_loss) : 0.7));
const align = s.prompt_alignment !== undefined ? Number(s.prompt_alignment) : (s.mean_prompt_alignment !== undefined ? Number(s.mean_prompt_alignment) : 0.25);
const div = s.pairwise_diversity !== undefined ? Number(s.pairwise_diversity) : 0.7;
const lat = s.latency_b1_ms !== undefined ? Number(s.latency_b1_ms) : (s.sampling_latency_ms !== undefined ? Number(s.sampling_latency_ms) : (s.latency_ms !== undefined ? Number(s.latency_ms) : (s.latency_per_query_ms !== undefined ? Number(s.latency_per_query_ms) : (r.latency_us ? r.latency_us / 1000.0 : 250.0))));
const layers = cfg.layers || 2;
const lr = cfg.lr || 0.0003;
const steps = s.sampling_steps !== undefined ? Number(s.sampling_steps) : (cfg.sampling_steps || 8);
return {
id: r.id,
name: r.name,
layers: Number(layers),
steps: Number(steps),
lr: Number(lr),
lr_label: Number(lr).toExponential(1),
ordering: orderingLabel,
latency: Number(lat.toFixed(1)),
diversity: Number(div.toFixed(3)),
align: Number(align.toFixed(3)),
val_loss: Number(val_loss.toFixed(4)),
raw: r
};
});
// Sort by chosen metric to assign Rank 1 to N
if (metric === 'val_loss') {
records.sort((a, b) => a.val_loss - b.val_loss);
} else if (metric === 'alignment') {
records.sort((a, b) => b.align - a.align);
} else if (metric === 'diversity') {
records.sort((a, b) => b.diversity - a.diversity);
} else if (metric === 'latency') {
records.sort((a, b) => a.latency - b.latency);
}
records.forEach((rec, idx) => {
rec.rank = idx + 1;
});
return records;
}
function pcAxisX(slot, n, width) {
const span = width - PC_LAYOUT.left - PC_LAYOUT.right;
const x = PC_LAYOUT.left + (n > 1 ? slot * span / (n - 1) : span / 2);
return Math.max(48, Math.min(width - 48, x));
}
function buildParcoordsOption(records) {
if (!records || records.length === 0) return {};
// Dynamic bounds based on current record scope
const minLoss = Math.min(...records.map(r => r.val_loss));
const maxLoss = Math.max(...records.map(r => r.val_loss));
const minLat = Math.min(...records.map(r => r.latency));
const maxLat = Math.max(...records.map(r => r.latency));
const minLr = Math.min(...records.map(r => r.lr));
const maxLr = Math.max(...records.map(r => r.lr));
const minAlign = Math.min(...records.map(r => r.align));
const maxAlign = Math.max(...records.map(r => r.align));
const minDiv = Math.min(...records.map(r => r.diversity));
const maxDiv = Math.max(...records.map(r => r.diversity));
const minLayers = Math.min(...records.map(r => r.layers));
const maxLayers = Math.max(...records.map(r => r.layers));
const parallelAxes = pcOrder.map(idx => {
const a = PC_AXES_DEF[idx];
const axisObj = {
dim: idx,
name: '',
type: a.type,
inverse: !!a.inverse,
axisLine: { lineStyle: { color: '#30363d', width: 1.5 } },
axisTick: { lineStyle: { color: '#30363d' } },
splitLine: { show: false },
axisLabel: {
color: '#8b949e',
fontSize: 11,
formatter: function(val) {
if (a.key === 'lr') return Number(val).toExponential(1);
if (a.key === 'rank') return '#' + val;
if (a.key === 'val_loss') return Number(val).toFixed(4);
if (a.key === 'align' || a.key === 'diversity') return Number(val).toFixed(2);
if (a.key === 'latency') return Number(val).toFixed(1);
return val;
}
}
};
if (a.type === 'category') {
axisObj.data = a.data;
} else if (a.isRank) {
axisObj.min = 1;
axisObj.max = Math.max(records.length, 2);
} else if (a.key === 'val_loss') {
axisObj.min = 0;
axisObj.max = +(maxLoss * 1.15).toFixed(4);
} else if (a.key === 'latency') {
axisObj.min = Math.max(0, +(minLat * 0.8).toFixed(1));
axisObj.max = +(maxLat * 1.1).toFixed(1);
} else if (a.key === 'lr') {
axisObj.min = minLr * 0.8;
axisObj.max = maxLr * 1.2;
} else if (a.key === 'align') {
axisObj.min = Math.max(0, +(minAlign - 0.05).toFixed(2));
axisObj.max = Math.min(1.0, +(maxAlign + 0.05).toFixed(2));
} else if (a.key === 'diversity') {
axisObj.min = Math.max(0, +(minDiv - 0.05).toFixed(2));
axisObj.max = Math.min(1.0, +(maxDiv + 0.05).toFixed(2));
} else if (a.key === 'layers') {
axisObj.min = Math.max(1, minLayers - 1);
axisObj.max = maxLayers + 1;
} else {
if (a.min !== undefined) axisObj.min = a.min;
if (a.max !== undefined) axisObj.max = a.max;
}
return axisObj;
});
const dataRows = records.map(r => [
r.rank,
r.layers,
r.lr,
r.ordering,
r.latency,
r.diversity,
r.align,
r.val_loss,
r.name,
r.id,
r.steps
]);
return {
backgroundColor: 'transparent',
parallel: {
left: PC_LAYOUT.left,
right: PC_LAYOUT.right,
top: PC_LAYOUT.top,
bottom: PC_LAYOUT.bottom,
parallelAxisDefault: {
axisLine: { lineStyle: { color: '#30363d' } },
axisTick: { lineStyle: { color: '#30363d' } },
axisLabel: { color: '#8b949e', fontSize: 11 }
}
},
parallelAxis: parallelAxes,
visualMap: {
type: 'continuous',
min: 1,
max: Math.max(records.length, 2),
dimension: 0,
inverse: true,
calculable: true,
realtime: true,
right: 10,
top: 'middle',
itemHeight: 200,
text: ['#1 Best', '#' + records.length],
textStyle: { color: '#8b949e', fontSize: 11 },
inRange: {
color: ['#3fb950', '#58a6ff', '#bc8cff', '#d29922', '#f85149']
}
},
tooltip: {
trigger: 'item',
backgroundColor: '#161b22',
borderColor: '#30363d',
borderWidth: 1,
padding: [10, 14],
textStyle: { color: '#c9d1d9', fontSize: 12 },
formatter: function(params) {
const v = params.value;
const rank = v[0];
const layers = v[1];
const lr = Number(v[2]).toExponential(1);
const ordering = v[3];
const latency = v[4];
const diversity = v[5];
const align = v[6];
const val_loss = v[7];
const name = v[8];
const id = v[9];
const steps = v[10] || 16;
const rankBadge = rank === 1
? '<span class="rank-badge-gold">#1 Champion 🥇</span>'
: (rank === 2 ? '<span class="rank-badge-silver">#2 Runner-Up 🥈</span>' : `<span style="color:#8b949e;font-weight:700;">#${rank}</span>`);
return `
<div style="font-weight:700;margin-bottom:6px;color:#f0f6fc;display:flex;align-items:center;justify-content:space-between;gap:14px;">
<span>${name}</span>
${rankBadge}
</div>
<div style="font-size:11px;color:#8b949e;font-family:monospace;margin-bottom:8px;">ID: ${id}</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:5px 14px;font-size:11px;">
<div><span style="color:#8b949e">Backbone Depth:</span> <b>${layers}L (${steps} Steps)</b></div>
<div><span style="color:#8b949e">Learning Rate:</span> <b>${lr}</b></div>
<div><span style="color:#8b949e">Target Ordering:</span> <b>${ordering}</b></div>
<div><span style="color:#8b949e">Heun Latency:</span> <b>${latency} ms</b></div>
<div><span style="color:#8b949e">Prompt Alignment:</span> <b>${align}</b></div>
<div><span style="color:#8b949e">Pairwise Diversity:</span> <b>${diversity}</b></div>
<div style="grid-column:span 2;padding-top:6px;margin-top:2px;border-top:1px solid #30363d;display:flex;justify-content:space-between;">
<span style="color:#58a6ff;font-weight:600;">Best Val Loss:</span>
<b style="color:#58a6ff;font-size:13px;">${val_loss}</b>
</div>
</div>
<div style="margin-top:8px;font-size:10px;color:#8b949e;font-style:italic;">
💡 Click line to inspect decoded subqueries &amp; full metrics &rarr;
</div>
`;
}
},
series: [{
type: 'parallel',
smooth: 0.15,
lineStyle: { width: 2.2, opacity: 0.6 },
emphasis: {
lineStyle: { width: 4.2, opacity: 1.0, shadowBlur: 10, shadowColor: 'rgba(88,166,255,0.7)' }
},
blur: {
lineStyle: { opacity: 0.08 }
},
data: dataRows
}]
};
}
function renderHandles(records) {
const container = document.getElementById('parcoords-handles');
const wrap = document.getElementById('parcoords-wrap');
if (!container || !wrap) return;
container.innerHTML = '';
const width = wrap.clientWidth || wrap.getBoundingClientRect().width || 1000;
const n = pcOrder.length;
pcOrder.forEach((axisIdx, slot) => {
const a = PC_AXES_DEF[axisIdx];
const x = pcAxisX(slot, n, width);
const pill = document.createElement('div');
pill.className = 'pc-handle';
pill.style.left = x + 'px';
pill.style.top = '14px';
pill.textContent = a.name;
pill.draggable = true;
pill.dataset.slot = String(slot);
pill.addEventListener('dragstart', function(e) {
pill.classList.add('pc-dragging');
e.dataTransfer.setData('text/plain', String(slot));
e.dataTransfer.effectAllowed = 'move';
});
pill.addEventListener('dragend', function() {
pill.classList.remove('pc-dragging');
document.querySelectorAll('.pc-handle').forEach(h => h.classList.remove('pc-over'));
});
pill.addEventListener('dragover', function(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
pill.classList.add('pc-over');
});
pill.addEventListener('dragleave', function() {
pill.classList.remove('pc-over');
});
pill.addEventListener('drop', function(e) {
e.preventDefault();
pill.classList.remove('pc-over');
const from = parseInt(e.dataTransfer.getData('text/plain'), 10);
const to = slot;
if (from === to || isNaN(from)) return;
const moved = pcOrder.splice(from, 1)[0];
pcOrder.splice(to, 0, moved);
try {
localStorage.setItem(STORE_KEY_PARCOORDS, JSON.stringify(pcOrder));
} catch(err) {}
if (pcChart) {
pcChart.setOption(buildParcoordsOption(records), { notMerge: true });
renderHandles(records);
}
});
container.appendChild(pill);
});
}
function resetPillars(e) {
if (e) e.preventDefault();
pcOrder = [0, 1, 2, 3, 4, 5, 6, 7];
try {
localStorage.removeItem(STORE_KEY_PARCOORDS);
} catch(err) {}
const records = getPillarData();
if (pcChart) {
pcChart.setOption(buildParcoordsOption(records), { notMerge: true });
renderHandles(records);
}
}
function renderSweepLeaderboard(records) {
const tbody = document.getElementById('sweep-leaderboard-body');
const countEl = document.getElementById('leaderboard-count');
if (!tbody) return;
if (countEl) countEl.textContent = `${records.length} runs ranked`;
tbody.innerHTML = records.map(r => {
let rankBadge = `<span style="color:var(--text-muted); font-weight:700; font-size:0.85rem;">#${r.rank}</span>`;
if (r.rank === 1) rankBadge = `<span class="rank-badge-gold">#1 🥇 Champion</span>`;
else if (r.rank === 2) rankBadge = `<span class="rank-badge-silver">#2 🥈 Runner-Up</span>`;
else if (r.rank === 3) rankBadge = `<span class="rank-badge-bronze">#3 🥉 Third</span>`;
const orderBadge = r.ordering === 'Cosine'
? `<span class="badge badge-success" style="font-size:0.75rem;">Cosine Sorted</span>`
: `<span class="badge badge-info" style="font-size:0.75rem;">Random Perm</span>`;
return `
<tr style="border-bottom: 1px solid rgba(48, 54, 61, 0.5); transition: background 0.15s ease;" onmouseover="this.style.background='rgba(255,255,255,0.03)'" onmouseout="this.style.background='transparent'">
<td style="padding: 10px;">${rankBadge}</td>
<td style="padding: 10px;">
<div style="font-weight: 600; color: #f0f6fc;">${r.name}</div>
<div style="font-size: 0.75rem; color: var(--text-muted); font-family: monospace;">${r.id}</div>
</td>
<td style="padding: 10px; font-weight: 600; color: #c9d1d9;">${r.layers}L <span style="font-size:0.75rem; color:var(--text-muted);">(${r.steps}s)</span></td>
<td style="padding: 10px; font-family: monospace; color: #79c0ff;">${r.lr_label}</td>
<td style="padding: 10px;">${orderBadge}</td>
<td style="padding: 10px; font-weight: 700; color: #58a6ff;">${r.val_loss.toFixed(4)}</td>
<td style="padding: 10px; font-weight: 600; color: #3fb950;">${r.align.toFixed(3)}</td>
<td style="padding: 10px; color: #bc8cff;">${r.diversity.toFixed(3)}</td>
<td style="padding: 10px; color: #f0883e;">${r.latency.toFixed(1)} ms</td>
<td style="padding: 10px; text-align: center;">
<button class="btn-action" style="padding: 4px 10px; font-size: 0.75rem;" onclick="jumpToDrill('${r.id}')">Inspect Decodings &rarr;</button>
</td>
</tr>
`;
}).join('');
}
function renderSweepRankChart() {
const records = getPillarData();
renderSweepLeaderboard(records);
const chartDom = document.getElementById('parcoords-echart');
if (!chartDom) return;
if (!pcChart) {
pcChart = echarts.init(chartDom, null, { renderer: 'canvas' });
pcChart.on('click', { seriesIndex: 0 }, function(params) {
const runId = params.value[9];
if (runId) {
jumpToDrill(runId);
}
});
pcChart.on('axisAreaSelected', function(params) {
const selCountEl = document.getElementById('pc-selected-count');
if (selCountEl) {
const intervals = params.intervals;
let active = 0;
records.forEach(r => {
const row = [r.rank, r.layers, r.lr, r.ordering, r.latency, r.diversity, r.align, r.val_loss];
let match = true;
intervals.forEach((iv, dimIdx) => {
if (!iv || iv.length === 0) return;
const v = row[dimIdx];
if (typeof v === 'number') {
const inAny = iv.some(range => v >= range[0] && v <= range[1]);
if (!inAny) match = false;
}
});
if (match) active++;
});
selCountEl.textContent = `${active} / ${records.length}`;
}
});
window.addEventListener('resize', function() {
if (pcChart) {
pcChart.resize();
const curRecords = getPillarData();
renderHandles(curRecords);
}
});
}
if (pcChart) pcChart.resize();
const opt = buildParcoordsOption(records);
pcChart.setOption(opt, { notMerge: true });
renderHandles(records);
const selCountEl = document.getElementById('pc-selected-count');
if (selCountEl) selCountEl.textContent = `${records.length} / ${records.length}`;
const metricSelect = document.getElementById('sweep-rank-metric');
const colorLabel = document.getElementById('pc-color-label');
if (metricSelect && colorLabel) {
const text = metricSelect.options[metricSelect.selectedIndex]?.text || 'Rank';
colorLabel.textContent = text.replace('Rank by: ', '') + ' (#1 Best → Low)';
}
}
function scrollToRankChart() {
switchTab('overview');
const el = document.getElementById('sweep-rank-section');
if (el) {
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
function renderRunsTable() {
const tbody = document.getElementById('runs-table-body');
if (!tbody) return;
const q = (document.getElementById('search-runs')?.value || '').toLowerCase();
let filtered = allRuns.filter(r => {
if (currentFilter !== 'all' && r.status !== currentFilter) return false;
if (q) {
const match = r.name.toLowerCase().includes(q) ||
(r.experiment_name || '').toLowerCase().includes(q) ||
JSON.stringify(r.config).toLowerCase().includes(q);
if (!match) return false;
}
return true;
});
filtered.sort((a, b) => {
let vA = getRunSortVal(a, currentSortKey);
let vB = getRunSortVal(b, currentSortKey);
if (vA === null) return 1;
if (vB === null) return -1;
if (typeof vA === 'string') return currentSortAsc ? vA.localeCompare(vB) : vB.localeCompare(vA);
return currentSortAsc ? vA - vB : vB - vA;
});
tbody.innerHTML = filtered.map(r => {
const s = r.summary || {};
const c = r.config || {};
const lat = s.sampling_latency_ms || (r.latency_us ? r.latency_us / 1000.0 : null);
const statusBadge = r.status === 'completed'
? '<span class="badge badge-success">Completed</span>'
: (r.status === 'running' ? '<span class="badge badge-running">Running</span>' : '<span class="badge badge-failed">Failed</span>');
return `
<tr>
<td style="font-weight:600; color:#f0f6fc;">${r.name}</td>
<td style="color:var(--text-muted);">${r.experiment_name || 'Default'}</td>
<td>${statusBadge}</td>
<td>${c.layers || '-'}</td>
<td>${c.target_ordering || 'random_perm'}</td>
<td style="font-weight:600; color:#79c0ff;">${s.best_val_loss ? s.best_val_loss.toFixed(4) : '-'}</td>
<td>${s.prompt_alignment ? s.prompt_alignment.toFixed(3) : '-'}</td>
<td>${s.pairwise_diversity ? s.pairwise_diversity.toFixed(3) : '-'}</td>
<td>${lat ? lat.toFixed(1) : '-'}</td>
<td style="color:var(--text-muted); font-size:0.8rem;">${r.started_at ? r.started_at.split(' ')[0] : '-'}</td>
<td style="text-align:center;">
<button class="btn-action" onclick="jumpToDrill('${r.id}')">Inspect</button>
</td>
</tr>
`;
}).join('');
}
function getRunSortVal(r, key) {
const s = r.summary || {};
const c = r.config || {};
switch(key) {
case 'name': return r.name;
case 'experiment_name': return r.experiment_name;
case 'status': return r.status;
case 'layers': return c.layers || 0;
case 'ordering': return c.target_ordering || '';
case 'best_val_loss': return s.best_val_loss !== undefined ? s.best_val_loss : null;
case 'prompt_align': return s.prompt_alignment !== undefined ? s.prompt_alignment : null;
case 'diversity': return s.pairwise_diversity !== undefined ? s.pairwise_diversity : null;
case 'latency': return s.sampling_latency_ms || (r.latency_us ? r.latency_us / 1000.0 : null);
case 'started_at': return r.started_at;
default: return r[key];
}
}
function setSort(key) {
if (currentSortKey === key) {
currentSortAsc = !currentSortAsc;
} else {
currentSortKey = key;
currentSortAsc = true;
}
renderRunsTable();
}
function filterTask(f) {
currentFilter = f;
document.querySelectorAll('.filter-pills .pill').forEach(p => p.classList.remove('active'));
const activePill = Array.from(document.querySelectorAll('.filter-pills .pill')).find(p => p.getAttribute('onclick')?.includes(f));
if (activePill) activePill.classList.add('active');
renderRunsTable();
}
function populateRunSelect() {
const select = document.getElementById('run-select');
if (!select) return;
select.innerHTML = allRuns.map(r => `<option value="${r.id}">${r.name}</option>`).join('');
if (selectedRunId) select.value = selectedRunId;
}
function jumpToDrill(runId, fromSelect = false) {
selectedRunId = runId;
if (!fromSelect) {
const select = document.getElementById('run-select');
if (select) select.value = runId;
switchTab('drilldown');
} else {
loadRunDetail(runId);
}
}
async function loadRunDetail(runId) {
try {
const res = await fetch(`/api/runs/${runId}`);
const r = await res.json();
document.getElementById('drill-name').textContent = r.name;
document.getElementById('drill-exp').textContent = `Experiment: ${r.experiment_name || 'Default'}`;
document.getElementById('drill-status').textContent = r.status.toUpperCase();
document.getElementById('drill-config').textContent = JSON.stringify(r.config, null, 2);
// Hardware info
const bInfo = document.getElementById('drill-benchmark-info');
if (r.benchmark) {
bInfo.innerHTML = `
<div>Device: <b>${r.benchmark.device_name || 'RTX 4090'}</b></div>
<div>Latency: <b>${(r.benchmark.latency_us / 1000.0).toFixed(1)} ms</b></div>
<div>Throughput: <b>${(r.benchmark.throughput || 0).toFixed(1)} sets/sec</b></div>
<div>Notes: <i>${r.benchmark.notes || 'N/A'}</i></div>
`;
} else {
bInfo.textContent = 'No hardware benchmark recorded for this run.';
}
// Render Dynamic Metric Charts
renderDrillCharts(r.metrics || {});
// Render WandB Style Samples
renderDrillSamples(r.samples || []);
} catch (err) {
console.error('Failed to load run detail:', err);
}
}
function renderDrillCharts(metrics) {
const container = document.getElementById('drill-charts-container');
if (!container) return;
const keys = Object.keys(metrics);
if (keys.length === 0) {
container.innerHTML = '<div class="chart-card" style="grid-column: 1 / -1; color: var(--text-muted); text-align: center; padding: 2rem;">No metric trajectories recorded for this run.</div>';
return;
}
container.innerHTML = keys.map(k => `
<div class="chart-card">
<div class="chart-header">
<div class="chart-title">${k}</div>
</div>
<div id="chart-drill-${k}" class="chart-box"></div>
</div>
`).join('');
keys.forEach(k => {
const m = metrics[k];
const el = document.getElementById(`chart-drill-${k}`);
if (el) {
const isEpoch = m.epochs && m.epochs.length > 0 && m.epochs[0] !== null;
const rawX = isEpoch ? m.epochs : m.steps;
const xVals = rawX.map(Number);
const yVals = m.values.map(Number);
Plotly.newPlot(el, [{
x: xVals,
y: yVals,
mode: 'lines+markers',
line: { color: '#58a6ff', width: 2 },
marker: { size: 5, color: '#79c0ff' },
hovertemplate: `${isEpoch ? 'Epoch' : 'Step'} %{x}<br>${k}: %{y:.5f}<extra></extra>`
}], {
...darkLayout,
margin: { l: 70, r: 25, t: 30, b: 40 },
xaxis: {
...darkLayout.xaxis,
type: 'linear',
title: isEpoch ? 'Epoch' : 'Step',
dtick: isEpoch ? 1 : undefined
},
yaxis: {
...darkLayout.yaxis,
type: 'linear',
title: k,
autorange: true,
tickformat: k === 'lr' ? '.2e' : '.4f'
}
}, { responsive: true, displayModeBar: false });
}
});
}
function renderDrillSamples(samples) {
const grid = document.getElementById('drill-samples-grid');
if (!grid) return;
if (samples.length === 0) {
grid.innerHTML = '<div class="sample-card" style="grid-column: 1 / -1; color: var(--text-muted); text-align: center;">No fan-out query outputs logged for this run.</div>';
return;
}
grid.innerHTML = samples.map((s, idx) => {
const inp = s.input || {};
const out = s.output || {};
const meta = s.metadata || {};
const subqueries = out.subqueries || [];
return `
<div class="sample-card">
<div class="sample-head">
<span><b>Sample #${idx + 1}</b> (Step ${s.step})</span>
<span>${s.timestamp || ''}</span>
</div>
<div style="font-size: 0.92rem; margin-bottom: 6px;">
Input Broad Query: <b style="color: #79c0ff;">"${inp.query || 'N/A'}"</b>
</div>
${out.mean_prompt_align !== undefined ? `
<div style="font-size: 0.8rem; color: var(--text-muted); margin-bottom: 8px;">
Alignment: <b>${out.mean_prompt_align.toFixed(3)}</b> | Diversity: <b>${out.pairwise_diversity ? out.pairwise_diversity.toFixed(3) : '-'}</b>
</div>
` : ''}
<div class="subquery-list">
${subqueries.map((sq, sIdx) => `
<div class="subquery-item">
<span><span class="subquery-slot">#${sIdx + 1}</span>"${sq}"</span>
</div>
`).join('')}
</div>
${meta.notes || meta.domain_coherence ? `
<div style="margin-top: 8px; font-size: 0.78rem; color: #d29922;">
${meta.notes || meta.domain_coherence}
</div>
` : ''}
</div>
`;
}).join('');
}
// Live Fanout Playground Logic
function setPlaygroundQuery(q) {
document.getElementById('playground-query-input').value = q;
executeLiveFanout();
}
async function executeLiveFanout() {
const input = document.getElementById('playground-query-input');
const query = input.value.trim();
if (!query) return;
const btn = document.getElementById('playground-submit-btn');
btn.disabled = true;
btn.innerText = '⚡ Synthesizing Fanout...';
try {
const res = await fetch('/api/playground/fanout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: query })
});
const data = await res.json();
if (!res.ok) throw new Error(data.detail || 'Failed to generate fanout');
const banner = document.getElementById('playground-stats-banner');
banner.style.display = 'flex';
document.getElementById('pg-fanout-lat').innerText = `${data.latency_ms} ms (${(data.latency_ms * 1000).toFixed(0)} µs)`;
document.getElementById('pg-embed-lat').innerText = `${data.embed_latency_ms} ms`;
document.getElementById('pg-total-lat').innerText = `${data.total_latency_ms} ms`;
document.getElementById('pg-align').innerText = `${data.mean_alignment.toFixed(3)} Cosine`;
document.getElementById('pg-div').innerText = `${data.pairwise_diversity.toFixed(3)}`;
const grid = document.getElementById('playground-slots-grid');
grid.innerHTML = data.slots.map(s => `
<div style="background: rgba(255,255,255,0.02); border: 1px solid var(--card-border); border-left: 3px solid var(--accent-green); border-radius: 6px; padding: 12px; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
<span style="font-size: 0.75rem; font-weight: 700; color: var(--accent-green); text-transform: uppercase;">Slot #${s.slot}</span>
<span style="font-size: 0.75rem; color: var(--text-muted);">Align: <b>${s.alignment}</b></span>
</div>
<div style="font-size: 0.95rem; font-weight: 700; color: #f0f6fc; margin-bottom: 4px; word-break: break-word;">
${s.subquery ? s.subquery : s.category}
</div>
<div style="font-size: 0.78rem; color: var(--accent-blue); margin-bottom: 8px; font-weight: 500;">
🏷️ ${s.category}
</div>
</div>
<div style="display: flex; justify-content: space-between; font-size: 0.72rem; color: var(--text-muted); border-top: 1px solid rgba(255,255,255,0.05); padding-top: 6px;">
<span>Subquery Sim: <b style="color: var(--accent-green);">${s.subquery_similarity || s.similarity}</b></span>
<span>Tax Sim: <b style="color: var(--accent-blue);">${s.similarity}</b></span>
</div>
</div>
`).join('');
} catch (err) {
alert('Error generating fanout: ' + err.message);
} finally {
btn.disabled = false;
btn.innerText = '⚡ Generate Fanout (169 µs)';
}
}
// Auto-load on page start
window.addEventListener('DOMContentLoaded', loadAllData);
</script>
</body>
</html>