File size: 6,124 Bytes
526610a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14fcfd7
 
 
526610a
e69a2f9
526610a
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const $ = id => document.getElementById(id);
const node = (tag, text, cls) => {const e=document.createElement(tag); if(text!==undefined)e.textContent=text; if(cls)e.className=cls; return e;};
const name = d => d === 'nova_anima' ? 'Nova' : 'Qwen';
const num = n => Number.isFinite(n) ? n.toFixed(4) : '—';
let data;
function pictures(target, row, columns) {
  $(target).replaceChildren(...columns.map(([key,label])=>{
    const figure=node('figure'),link=node('a'),img=node('img');
    link.href=row.images[key];link.target='_blank';link.rel='noopener';
    img.src=row.images[key];img.alt=`${label}: ${row.label || row.prompt}`;img.className='sample-image';
    link.append(img);figure.append(link,node('figcaption',label));return figure;
  }));
}
function drawCharacter() {
  const row=data.characters.cases.find(r=>r.id===$('character').value&&r.domain===$('start').value);
  const p=row.policies.find(p=>p.policy===$('policy').value),kind=p.policy.replaceAll('_','-');
  const route=[row.domain,...p.audit.switches.map(s=>s.target)].map(name).join(' → ');
  $('prompt').textContent=row.prompt;
  $('trajectory').replaceChildren(...p.domains.map((d,i)=>node('span',`${i+1} ${name(d)}`,d==='nova_anima'?'sd15':'sana')));
  $('schedule').textContent=`${row.resolution}px · seed ${row.seed} · 24 denoising steps. ${p.audit.switches.map(s=>`After step ${s.after_call}: ${name(s.source)} → ${name(s.target)}`).join('. ')}.`;
  pictures('pictures',row,[['shared-single',`${name(row.domain)} only · same noise grid`],[kind,`${route} · learned bridges`],[kind+'-codec',`${route} · full decode/encode reference`]]);
  $('metrics').textContent=`Learned versus matching reference: LPIPS ${num(p.lpips_vs_matched_full_codec)}. Difference from ${name(row.domain)} only: learned ${num(p.lpips_vs_single_model)}; reference ${num(p.full_codec_lpips_vs_single_model)}. Exact repeat: ${p.repeat_bitwise_equal?'passed':'unverified'}.`;
}
function drawBridge() {
  const row=data.reconstructions.find(r=>r.domain===$('direction').value);
  $('bridge-prompt').textContent=row.prompt;
  $('bridge-step').textContent=`${row.training_step.toLocaleString()} resumed updates · ${row.kind} · seed ${row.seed}`;
  pictures('bridge-pictures',row,[['source',`${name(row.domain)} · source`],['prediction',`Learned bridge → ${name(row.other_domain)}`],['target',`Full-codec target → ${name(row.other_domain)}`]]);
  $('bridge-metrics').textContent=`Learned LPIPS ${num(row.metrics.lpips)}; full-codec target ${num(row.metrics.teacher_lpips)}; learned versus target ${num(row.metrics.lpips_vs_teacher)}.`;
}
function chart(metric) {
  const ns='http://www.w3.org/2000/svg',svg=document.createElementNS(ns,'svg');
  svg.setAttribute('viewBox','0 0 620 280');svg.setAttribute('role','img');svg.setAttribute('aria-label',`Validation ${metric} versus resumed updates`);
  const values=data.runs.flatMap(r=>r.validation.filter(v=>Number.isFinite(v.metrics[metric])));
  if(!values.length)return;
  const xmax=Math.max(...values.map(v=>v.step),1), ymax=Math.max(...values.map(v=>v.metrics[metric]),.001)*1.08;
  const x=v=>52+550*v/xmax,y=v=>236-210*v/ymax;
  function add(tag,attrs,text){const e=document.createElementNS(ns,tag);for(const [k,v]of Object.entries(attrs))e.setAttribute(k,v);if(text!==undefined)e.textContent=text;svg.append(e);return e;}
  for(let i=0;i<=4;i++){const v=ymax*i/4;add('line',{x1:52,x2:602,y1:y(v),y2:y(v),class:'gridline'});add('text',{x:45,y:y(v)+4,'text-anchor':'end'},v.toFixed(3));const step=xmax*i/4;add('text',{x:x(step),y:259,'text-anchor':'middle'},`${Math.round(step/1000)}k`);}
  data.runs.forEach((r,i)=>{const rows=r.validation.filter(v=>Number.isFinite(v.metrics[metric])),color=i?'#edb784':'#88e0c0';
    add('polyline',{points:rows.map(v=>`${x(v.step)},${y(v.metrics[metric])}`).join(' '),fill:'none',stroke:color,'stroke-width':2});
    rows.forEach(v=>{const c=add('circle',{cx:x(v.step),cy:y(v.metrics[metric]),r:3,fill:color}),t=document.createElementNS(ns,'title');t.textContent=`${r.label}: ${v.step} updates, ${metric} ${v.metrics[metric]}`;c.append(t);});
  });$(metric).replaceChildren(svg);
}
fetch('archive.json').then(r=>{if(!r.ok)throw Error(`HTTP ${r.status}`);return r.json();}).then(value=>{
  data=value;
  data.runs.forEach(r=>{r.validation=r.validation.map(v=>({...v,metrics:v.metrics||v}));});
  $('status').textContent=data.stopped?'Training stopped · experiment preserved':'Experiment snapshot · publication in progress';
  $('snapshot').textContent=`Archived ${data.created_at}. Full-codec supervision is preserved for reference; the next experiment will investigate latent-only preparation and training.`;
  if(data.stopped){const s=data.stop_record;$('snapshot').textContent+=` Stopped at ${s.checkpoints.forward.step.toLocaleString()} forward / ${s.checkpoints.reverse.step.toLocaleString()} reverse resumed updates, with ${s.total_training_prompts_prepared.toLocaleString()} / ${s.planned_training_prompts.toLocaleString()} training prompts prepared.`;}
  const cps=data.characters.checkpoints;$('checkpoints').textContent=`Character snapshot: Nova → Qwen ${cps.forward.step.toLocaleString()} updates; Qwen → Nova ${cps.reverse.step.toLocaleString()} updates. Latest/best archived weights and curves are labeled separately.`;
  const cases=[...new Map(data.characters.cases.map(r=>[r.id,r])).values()];$('character').replaceChildren(...cases.map(r=>{const o=node('option',r.label);o.value=r.id;return o;}));
  $('summary').replaceChildren(...data.runs.map(r=>{const card=node('div',undefined,'stat'),last=r.validation.at(-1);card.append(node('label',r.label),node('strong',num(last?.metrics.lpips)),node('span',`Validation LPIPS at ${last?.step.toLocaleString()} updates. Selected best: ${num(r.best?.lpips)} at ${r.best?.step.toLocaleString()}.`));return card;}));
  drawCharacter();drawBridge();chart('lpips');chart('latent_nmse');
}).catch(e=>{$('status').textContent=`Unable to load archive: ${e.message}`;});
for(const id of ['character','start','policy'])$(id).addEventListener('change',drawCharacter);
$('direction').addEventListener('change',drawBridge);