demo mode: never overwrite real data on perf / models / live
Same hasReal* gating I already used for phase_mix, applied to: - models bars (model_metric) - perf scatter (model_perf) - live detections (live_detection) Each widget tracks whether a real producer event has arrived; demo only seeds when nothing real has been seen yet, and demo_stop preserves real state instead of wiping it. demoTick is now a no-op — periodic model_metric jitter was overwriting real values mid-stream. Per-widget one-shot seeding on demo_start (gated by hasReal*) is enough. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f429bd4223
commit
a04ea60aef
2 changed files with 32 additions and 25 deletions
|
|
@ -224,20 +224,12 @@
|
|||
const demoBtn = document.getElementById('demo-btn');
|
||||
let demoTimer = null;
|
||||
let demoActive = false;
|
||||
// Demo mode is intentionally narrow: it does NOT synthesize
|
||||
// `episode` events (those would clobber the real ingest counter,
|
||||
// host bars, and database explorer — all of which work fine in or
|
||||
// out of demo mode), and it does NOT synthesize `phase` events
|
||||
// (the baseline scene reads dataset-derived `phase_mix` instead).
|
||||
// The only periodic side-effect is occasional model_metric jitter
|
||||
// so the bars don't sit frozen during a long talk.
|
||||
function demoTick() {
|
||||
if (Math.random() < 0.05) {
|
||||
const m = ['knn', 'rnn', 'gru', 'lstm', 'bert'][Math.floor(Math.random() * 5)];
|
||||
const base = { knn: 0.736, rnn: 0.872, gru: 0.911, lstm: 0.928, bert: 0.954 }[m];
|
||||
dispatch({ type: 'model_metric', model: m, accuracy: base + (Math.random() - 0.5) * 0.012 });
|
||||
}
|
||||
}
|
||||
// Demo mode is intentionally narrow. Real data wins everywhere —
|
||||
// demo only seeds widgets that haven't received any real producer
|
||||
// output yet. demoTick is now a no-op; the per-widget demo_start
|
||||
// handlers do the (one-shot) seeding, so we don't drown out real
|
||||
// data with periodic synthetic noise.
|
||||
function demoTick() {}
|
||||
function setDemo(active) {
|
||||
if (demoActive === active) return;
|
||||
demoActive = active;
|
||||
|
|
@ -1785,19 +1777,22 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
r.fill.style.width = (visible * 100).toFixed(1) + '%';
|
||||
r.acc.textContent = accuracy.toFixed(3);
|
||||
}
|
||||
// Real data wins. Demo only fills in when no real model_metric
|
||||
// has arrived yet — once the producer publishes for any model,
|
||||
// demo never overwrites it.
|
||||
let hasRealMetric = false;
|
||||
on('demo_start', () => {
|
||||
// KNN sits below the recurrent/transformer family; it memorizes
|
||||
// the train host's feature space and generalizes worse than a
|
||||
// model that learned temporal structure. Bar visible-scale starts
|
||||
// at 0.5 so the real cross-host F1 (~0.43) reads as 0% — that's
|
||||
// honest, just visually flat. Demo value here is the in-distribution
|
||||
// ballpark for a healthier display.
|
||||
if (hasRealMetric) return;
|
||||
[ ['knn', 0.736], ['rnn', 0.872], ['gru', 0.911], ['lstm', 0.928], ['bert', 0.954] ]
|
||||
.forEach(([m, a]) => render(m, a));
|
||||
});
|
||||
on('demo_stop', () => { rows.clear(); emptyState(); });
|
||||
on('demo_stop', () => {
|
||||
// Don't wipe real data on demo toggle off.
|
||||
if (!hasRealMetric) { rows.clear(); emptyState(); }
|
||||
});
|
||||
on('model_metric', m => {
|
||||
if (!m.model || typeof m.accuracy !== 'number') return;
|
||||
hasRealMetric = true;
|
||||
render(m.model, m.accuracy);
|
||||
});
|
||||
emptyState();
|
||||
|
|
@ -2208,8 +2203,12 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
}
|
||||
setInterval(updateStats, 500);
|
||||
|
||||
function handleDetection(d) {
|
||||
// Track whether real live_detection events have arrived. Demo
|
||||
// only fills in when nothing real is flowing — never overwrites.
|
||||
let hasRealDetection = false;
|
||||
function handleDetection(d, fromReal) {
|
||||
if (!d.host_id || !d.predicted) return;
|
||||
if (fromReal) hasRealDetection = true;
|
||||
eventTimes.push(Date.now());
|
||||
if (d.model) lastModel = d.model;
|
||||
if (d.actual) {
|
||||
|
|
@ -2220,11 +2219,12 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
paintLatest(d);
|
||||
}
|
||||
|
||||
on('live_detection', handleDetection);
|
||||
on('live_detection', m => handleDetection(m, true));
|
||||
|
||||
// Synthetic demo: 5 hosts, walk through phases, ~92% accuracy.
|
||||
let demoTimer = null;
|
||||
function demoStart() {
|
||||
if (hasRealDetection) return;
|
||||
if (demoTimer) clearInterval(demoTimer);
|
||||
const HOSTS = [
|
||||
{ id: 'elliott-lab', profile: 'cpu-saturate', phaseIdx: 0 },
|
||||
|
|
@ -2258,6 +2258,8 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
}
|
||||
function demoStop() {
|
||||
if (demoTimer) { clearInterval(demoTimer); demoTimer = null; }
|
||||
// Don't wipe real data on demo toggle off.
|
||||
if (hasRealDetection) return;
|
||||
lanes.forEach(l => l.row.remove());
|
||||
lanes.clear();
|
||||
eventTimes.length = 0;
|
||||
|
|
@ -2515,7 +2517,11 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
rec.g.querySelector('text').textContent = model;
|
||||
repaintLabels();
|
||||
}
|
||||
// Real data wins. Demo only fills in when no real model_perf has
|
||||
// arrived yet.
|
||||
let hasRealPerf = false;
|
||||
on('demo_start', () => {
|
||||
if (hasRealPerf) return;
|
||||
[
|
||||
{ model: 'knn', latency_us: 90, accuracy: 0.84 },
|
||||
{ model: 'rnn', latency_us: 380, accuracy: 0.87 },
|
||||
|
|
@ -2524,9 +2530,10 @@ def train_nn(*, model, X_train, y_train, X_val, y_val,
|
|||
{ model: 'bert', latency_us: 3200, accuracy: 0.95 },
|
||||
].forEach(p => render(p.model, p.latency_us, p.accuracy));
|
||||
});
|
||||
on('demo_stop', emptyState);
|
||||
on('demo_stop', () => { if (!hasRealPerf) emptyState(); });
|
||||
on('model_perf', m => {
|
||||
if (!m.model || typeof m.latency_us !== 'number' || typeof m.accuracy !== 'number') return;
|
||||
hasRealPerf = true;
|
||||
render(m.model, m.latency_us, m.accuracy);
|
||||
});
|
||||
emptyState();
|
||||
|
|
|
|||
|
|
@ -1314,6 +1314,6 @@
|
|||
</article>
|
||||
</div>
|
||||
|
||||
<script src="/static/dashboard.js?v=7f398906"></script>
|
||||
<script src="/static/dashboard.js?v=d4323f22"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue