DaisyChain-Train / web /public /index.html
Quazim0t0's picture
web: sync-guard gradient repair, FineWeb-Edu hardcoded (parquet /data streaming), dispatch-optimized backward (bit-identical), IEEE-754 oracle + corpus mutation tests, TEST_RESULTS.md
9ae1216 verified
Raw
History Blame Contribute Delete
11.8 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DaisyChain-Web — train by opening a page</title>
<style>
:root {
--page-bg: #efe4c9;
--card-bg: #fbf6e8;
--card-border: rgba(139, 111, 71, 0.30);
--text: #2a1d0a;
--text-soft: #6b4423;
--accent: #4a7c2e;
--accent-deep: #2d5016;
--counter-bg: linear-gradient(135deg, #2d5016 0%, #1f3a0f 100%);
--counter-num: #f5ecd9;
--counter-label: #c9b072;
--btn: linear-gradient(135deg, #4a7c2e 0%, #2d5016 100%);
--btn-hover: linear-gradient(135deg, #5a8c3e 0%, #3d6020 100%);
--warn: #8b2e25;
--link: #4a7c2e;
--track: rgba(139, 111, 71, 0.22);
}
@media (prefers-color-scheme: dark) {
:root {
--page-bg: #14100a; --card-bg: #1f1a12; --card-border: rgba(201, 176, 114, 0.35);
--text: #ede1c3; --text-soft: #c9b072; --accent: #9bc466; --accent-deep: #6b9039;
--counter-bg: linear-gradient(135deg, #1a2e0d 0%, #0c1606 100%);
--counter-label: #c9b072; --warn: #ff9b8e; --link: #9bc466; --track: rgba(201,176,114,0.20);
}
}
* { box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 720px; margin: 0 auto; padding: 24px 18px 40px; line-height: 1.5;
background: var(--page-bg); color: var(--text); }
h1 { margin: 0 0 2px; font-size: 1.7rem; letter-spacing: .3px; }
.sub { color: var(--text-soft); margin: 0 0 18px; font-size: .92rem; }
.sub code { background: rgba(74,124,46,.12); padding: 1px 5px; border-radius: 4px; }
.card { background: var(--card-bg); border: 1px solid var(--card-border);
border-radius: 10px; padding: 14px 16px; margin: 12px 0;
box-shadow: 0 2px 10px rgba(0,0,0,0.06); }
.lbl { color: var(--text-soft); font-size: 11px; font-weight: 800; letter-spacing: 1.5px;
text-transform: uppercase; margin-bottom: 8px; }
.row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: .95rem; }
.k { color: var(--text-soft); } .v { font-weight: 700; text-align: right; }
.device { font-family: 'Courier New', monospace; font-size: 1.5rem; font-weight: 700;
color: var(--accent-deep); }
@media (prefers-color-scheme: dark) { .device { color: var(--accent); } }
.counter { background: var(--counter-bg); border-radius: 10px; padding: 14px 16px; text-align: center; }
.counter .num { font-family: 'Courier New', monospace; font-size: 2.2rem; font-weight: 700; color: var(--counter-num); }
.counter .cl { color: var(--counter-label); font-size: 11px; text-transform: uppercase; letter-spacing: 1.5px; }
.track { width: 100%; height: 10px; border-radius: 6px; background: var(--track); overflow: hidden; margin-top: 12px; }
#bar { height: 10px; width: 0; background: linear-gradient(90deg, #6b9039, #9bc466); transition: width .25s; }
button { background: var(--btn); color: #f5ecd9; border: 0; border-radius: 8px;
padding: 12px 26px; font-weight: 800; font-size: 1rem; letter-spacing: .5px; cursor: pointer;
box-shadow: 0 3px 10px rgba(74,49,16,0.18); transition: .15s; }
button:hover:not(:disabled) { background: var(--btn-hover); box-shadow: 0 5px 14px rgba(74,49,16,0.28); }
button:disabled { background: #8b7d5e; opacity: .55; cursor: not-allowed; box-shadow: none; }
pre { background: rgba(0,0,0,0.05); border-radius: 8px; padding: 10px; max-height: 150px;
overflow: auto; font-size: .78rem; color: var(--text-soft); white-space: pre-wrap; margin: 0;
font-family: 'Courier New', monospace; }
@media (prefers-color-scheme: dark) { pre { background: rgba(0,0,0,0.25); } }
.note { color: var(--text-soft); font-size: .82rem; }
.slbl { display: flex; justify-content: space-between; font-size: .92rem; margin: 10px 0 4px; font-weight: 600; }
.sval { font-family: 'Courier New', monospace; color: var(--accent); font-weight: 700; }
input[type=range] { width: 100%; accent-color: var(--accent); }
.note b { color: var(--warn); }
.diff { color: var(--accent-deep); font-weight: 600; font-size: .88rem; }
@media (prefers-color-scheme: dark) { .diff { color: var(--accent); } }
</style>
</head>
<body>
<h1>🌼 DaisyChain-Web</h1>
<p class="sub">Open this on your other devices <b>on the same network</b> and they <b>pretrain a language model from scratch</b> together — peer-to-peer, right in the browser, through the emulated GPU logic. This is pretraining, not fine-tuning: every run starts from random weights. Only devices on your network are grouped (like Snapdrop). To invite people across networks, everyone opens <code>?room=YOUR-CODE</code> — the person who created the room approves each device before it can join.</p>
<div class="card" id="lobby" style="display:none;text-align:center">
<div class="lbl">🏡 Get started</div>
<p class="note" style="margin:0 0 12px">Create a room and invite your devices, or join a room someone shared with you.</p>
<button id="createRoom">Create a room</button>
<div style="display:flex;gap:8px;justify-content:center;margin-top:12px;flex-wrap:wrap">
<input type="text" id="joinCode" placeholder="room code" spellcheck="false"
style="padding:10px 12px;border-radius:8px;border:1px solid var(--card-border);background:transparent;color:inherit;font-family:'Courier New',monospace">
<button id="joinRoom" style="padding:10px 18px">Join</button>
</div>
</div>
<div class="card">
<div class="lbl">🌲 This device</div>
<div class="device" id="me"></div>
<div class="row" style="margin-top:8px"><span class="k">Status</span><span class="v" id="status">starting…</span></div>
<div class="row"><span class="k">Compute</span><span class="v" id="backend">detecting…</span></div>
<div class="row"><span class="k">Dataset</span><span class="v" id="dataset"></span></div>
<div class="row"><span class="k">Tokenizer</span><span class="v" id="tokenizer">loading…</span></div>
</div>
<div class="card">
<div class="lbl">🍄 Devices in your group</div>
<div class="row"><span class="v" id="peers" style="text-align:left">(none yet)</span></div>
<div id="roomInfo" style="display:none;margin-top:8px">
<div class="row"><span class="k">Room</span><span class="v" id="roomCode"></span></div>
<div style="text-align:center;margin-top:6px"><button id="copyLink" style="padding:6px 14px;font-size:.85rem">Copy invite link</button></div>
<p class="note" style="margin:.5rem 0 0;text-align:center">Open the link on your other devices — you approve each one before it joins.</p>
</div>
<div id="requests"></div>
</div>
<div class="card">
<div class="lbl">🎛 Training settings</div>
<label class="slbl">Model width <span class="sval" id="vcfgC">32</span></label>
<input type="range" id="cfgC" min="16" max="128" step="16" value="32">
<label class="slbl">Sequence length <span class="sval" id="vcfgT">32</span></label>
<input type="range" id="cfgT" min="16" max="128" step="16" value="32">
<p class="note" style="margin:.4rem 0 0"><b>Width or sequence above 64?</b> Bring more devices — big settings on 1–3 devices mean slow steps and a small effective batch. 4+ devices recommended.</p>
<label class="slbl">Batch per device <span class="sval" id="vcfgB">8</span></label>
<input type="range" id="cfgB" min="2" max="32" step="2" value="8">
<label class="slbl">Steps <span class="sval" id="vcfgSteps">300</span></label>
<input type="range" id="cfgSteps" min="100" max="10000" step="100" value="300">
<label class="slbl">Learning rate ×1000 <span class="sval" id="vcfgLr">10</span></label>
<input type="range" id="cfgLr" min="5" max="50" step="5" value="10">
<label class="slbl">Dataset</label>
<p class="note" style="margin:.2rem 0 0"><b>FineWeb-Edu</b> (HuggingFaceFW/fineweb-edu, 10BT sample) — fixed. Each device pulls its own random slice of the parquet shards, served by this Space; if streaming fails, the built-in corpus is used.</p>
<p class="note" style="margin:.6rem 0 0"><b>This is pretraining, not fine-tuning</b> — every run trains a brand-new model from random weights. You are watching a language model learn from scratch.</p>
<p class="note" style="margin:.5rem 0 0">A mini transformer language model — attention, MLP blocks, next-character prediction — every multiply through the verified INT8 units. Training text is streamed from <b>FineWeb-Edu</b> (HuggingFace); offline devices fall back to a built-in corpus. Whoever presses Start sets the settings for the whole group; total batch scales with every device that joins.</p>
</div>
<div class="card" style="text-align:center">
<button id="start" disabled>Start training</button>
<p class="note" style="margin:.6rem 0 0">Works solo — every device that joins adds its batch to the group.</p>
</div>
<div class="card">
<div class="lbl">✦ Training</div>
<div class="row"><span class="k">Step</span><span class="v" id="step">— / —</span></div>
<div class="counter" style="margin:10px 0"><div class="num" id="loss"></div><div class="cl">cluster-avg loss · lower is better</div></div>
<div class="track"><div id="bar"></div></div>
<div class="row" style="margin-top:10px"><span class="diff" id="diff"></span></div>
</div>
<div class="card">
<div class="lbl">🗣 Test the model</div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<input type="text" id="genPrompt" value="the " spellcheck="false"
style="flex:1;min-width:160px;padding:10px 12px;border-radius:8px;border:1px solid var(--card-border);background:transparent;color:inherit;font-family:'Courier New',monospace">
<button id="genBtn" disabled style="padding:10px 18px">Generate</button>
</div>
<pre id="genOut" style="margin-top:10px;min-height:44px"></pre>
<p class="note" style="margin:.5rem 0 0">Enabled after training finishes or a checkpoint is loaded. The “inference kit” below downloads a single HTML file with these weights baked in — open it anywhere to run generations offline.</p>
</div>
<div class="card">
<div class="lbl">💾 Model checkpoint</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;justify-content:center">
<button id="save" disabled>Download model (.pt)</button>
<button id="kit" disabled>Download inference kit</button>
<button id="loadBtn">Load checkpoint…</button>
<input type="file" id="load" accept=".pt" style="display:none">
</div>
<p class="note" style="margin:.6rem 0 0;text-align:center">Loading a checkpoint applies it here <b>and</b> pushes it to every connected device — use it to recover the group after a failure.</p>
</div>
<div class="card">
<div class="lbl">❋ Log</div>
<pre id="log"></pre>
</div>
<p class="note">Needs a secure context (localhost or HTTPS) for WebGPU + cross-device WebRTC. No WebGPU? The same verified INT8 units run on CPU — old machines (e.g. via Supermium) still join, just slower. Every training step goes through the Neural Units; there is no plain-float path, and if the units fail to load, training is disabled.</p>
<p class="note"><b>Heads up:</b> peers connect directly (WebRTC), so devices in your group can see each other's IP address, and there's no gradient authentication — only train with devices/people you trust. Proof of concept.</p>
<script src="traincore.js"></script>
<script src="verified_core.js"></script>
<script src="transformer.js"></script>
<script src="webgpu.js"></script>
<script src="app.js"></script>
</body>
</html>