From a71c95c8caf7e570c3f484ce1a53b7acb5ef2006 Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 25 Mar 2026 06:25:53 +0100 Subject: feat(cnn_v3/tools): embed default weights in HTML tool; add --html export flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cnn_v3/tools/weights.js: new file — base64-encoded cnn_v3_weights.bin + cnn_v3_film_mlp.bin; loaded at startup so the tool works without dropping files - tester.js: preload() falls back to embedded weights.js constants when fetch fails; logs "Loaded embedded" vs "Preloaded" to distinguish the two paths - index.html: load weights.js before tester.js - export_cnn_v3_weights.py: add --html / --html-output flags that call update_weights_js() to regenerate weights.js after a training run - HOW_TO_CNN.md: update pipeline diagram, §3 export commands, §7 HTML tool section (file table, workflow, weights.js description), Appendix A handoff(Gemini): weights.js now the canonical source for HTML tool defaults; regenerate with `uv run export_cnn_v3_weights.py --output ... --html` --- cnn_v3/tools/tester.js | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'cnn_v3/tools/tester.js') diff --git a/cnn_v3/tools/tester.js b/cnn_v3/tools/tester.js index 0412cae..81c869d 100644 --- a/cnn_v3/tools/tester.js +++ b/cnn_v3/tools/tester.js @@ -52,29 +52,34 @@ class CNNv3Tester { async preload() { const base = '../../workspaces/main/weights/'; const files = [ - {url: base+'cnn_v3_weights.bin', isFilm: false}, - {url: base+'cnn_v3_film_mlp.bin', isFilm: true}, + {url: base+'cnn_v3_weights.bin', isFilm: false, b64: CNN_V3_WEIGHTS_B64}, + {url: base+'cnn_v3_film_mlp.bin', isFilm: true, b64: CNN_V3_FILM_MLP_B64}, ]; - for (const {url, isFilm} of files) { + for (const {url, isFilm, b64} of files) { + let buf = null; + const name = url.split('/').pop(); try { const r = await fetch(url); - if (!r.ok) { this.log(`preload skip: ${url.split('/').pop()} (${r.status})`); continue; } - const buf = await r.arrayBuffer(); - const name = url.split('/').pop(); - if (isFilm) { - this.filmMlp = this.parseFilm(buf); - const el = document.getElementById('fDrop'); - el.textContent = `✓ ${name}`; el.classList.add('ok'); - document.getElementById('fSt').textContent = 'FiLM MLP loaded'; - document.getElementById('fSt').style.color = '#28a745'; - } else { - this.weightsU32 = this.parseWeights(buf); this.weightsBuffer = buf; - if (this.weightsGPU) { this.weightsGPU.destroy(); this.weightsGPU = null; } - const el = document.getElementById('wDrop'); - el.textContent = `✓ ${name}`; el.classList.add('ok'); - } - this.log(`Preloaded: ${name}`); - } catch(e) { this.log(`preload error (${url.split('/').pop()}): ${e.message}`, 'err'); } + if (r.ok) { buf = await r.arrayBuffer(); this.log(`Preloaded: ${name}`); } + } catch(_) {} + if (!buf) { + const s = atob(b64); const u = new Uint8Array(s.length); + for (let i = 0; i < s.length; i++) u[i] = s.charCodeAt(i); + buf = u.buffer; + this.log(`Loaded embedded: ${name}`); + } + if (isFilm) { + this.filmMlp = this.parseFilm(buf); + const el = document.getElementById('fDrop'); + el.textContent = `✓ ${name}`; el.classList.add('ok'); + document.getElementById('fSt').textContent = 'FiLM MLP loaded'; + document.getElementById('fSt').style.color = '#28a745'; + } else { + this.weightsU32 = this.parseWeights(buf); this.weightsBuffer = buf; + if (this.weightsGPU) { this.weightsGPU.destroy(); this.weightsGPU = null; } + const el = document.getElementById('wDrop'); + el.textContent = `✓ ${name}`; el.classList.add('ok'); + } } if (this.weightsU32) { if (this.image || this.isVideo) this.run(); -- cgit v1.2.3