ouroboros / source /src /DualScene.tsx
REXWind's picture
Publish the Ouroboros scientific showcase to CladeTeam
03677d0 verified
Raw History Blame Contribute Delete
14.1 kB
import {useId} from 'react';
import config from '../t5config_large.json';
import {mix, phase, segment, windowAt, residuePreviewCount, sharingState} from './dualStory';
import type {Example} from './types';
const blue = '#397cbb', orange = '#cf643e', ink = '#24364a';
const words = (s:string) => s.replace(/([.!?])(?=[A-Z])/g,'$1 ').split(/\s+/);
function wrap(s:string, limit:number) {
const lines:string[] = []; let line = '';
words(s).forEach(word => { if ((line+' '+word).length > limit && line) { lines.push(line); line = word; } else line += (line?' ':'')+word; });
if (line) lines.push(line);
return lines;
}
function Node({x,y,protein,decoder,focus,context=0,sharing=0}:{x:number;y:number;protein:boolean;decoder:boolean;focus:number;context?:number;sharing?:number}) {
const color = protein?orange:blue;
const rows = decoder?['Masked self-attention','Cross-attention','Feed-forward']:['Self-attention','Feed-forward'];
return <g transform={`translate(${x} ${y})`} opacity={.24+.76*focus} data-module={`${protein?'protein':'text'}-${decoder?'decoder':'encoder'}`}>
{[12,6].map(n=><rect key={n} x={n} y={-n} width={228-n} height="200" rx="12" fill="#f8fafc" stroke={color} strokeOpacity=".2"/>)}
<rect width="228" height="200" rx="12" fill={protein?'#fff5ef':'#eff6fc'} stroke={color} strokeWidth={1+focus*.6}/>
<text x="17" y="25" className="ds-micro" fill={color}>{decoder?'AUTOREGRESSIVE DECODER':'CONTEXTUAL ENCODER'}</text>
<text x="17" y="54" className="ds-node-title" fill={ink}>{protein?'Protein':'Text'} {decoder?'Decoder':'Encoder'}</text>
<text x="207" y="25" textAnchor="end" className="ds-count" fill={color}>×{decoder?config.num_decoder_layers:config.num_layers}</text>
{rows.map((label,i)=>{
const rowY = 73+i*(decoder?34:51);
return <g key={label} data-shared-attention={i===0?sharing.toFixed(4):undefined}>
{i===0&&<rect x="9" y={rowY-5} width="210" height="37" rx="8" fill={color} fillOpacity={sharing*.1} stroke={color} strokeOpacity={sharing} strokeWidth={sharing*2.5}/>}
<rect x="14" y={rowY} width="200" height="27" rx="5" fill={i===0&&sharing>.1?color:label==='Cross-attention'&&context>0?color:'#ffffff'} fillOpacity={i===0?.8-sharing*.66:label==='Cross-attention'? .14+.5*context:.8} stroke={color} strokeOpacity={label==='Cross-attention'?.5:.14}/>
<text x="25" y={rowY+19} className="ds-row" fill={label==='Cross-attention'&&context>.65?'#fff':color}>{label}</text>
{i===0&&<text x="204" y={rowY+18} textAnchor="end" className="ds-shared-tag" fill={color} opacity={sharing}>TIED</text>}
</g>;
})}
<text x="17" y="190" className="ds-small" fill={color}>Block detail · d = {config.d_model.toLocaleString('en-US')}</text>
</g>;
}
function Projection({x,y,reverse,focus}:{x:number;y:number;reverse:boolean;focus:number}) {
return <g opacity={.24+.76*focus} transform={`translate(${x} ${y})`} data-projection={reverse?'p2t':'t2p'}>
<rect width="140" height="116" rx="9" fill="#fff" stroke="#8093a7"/>
<text x="70" y="25" textAnchor="middle" className="ds-micro" fill="#5f7286">LINEAR PROJECTION</text>
<text x="70" y="54" textAnchor="middle" className="ds-projection-name" fill={ink}>{reverse?'Wₚ→ₜ':'Wₜ→ₚ'}</text>
<rect x="10" y="67" width="120" height="29" rx="4" fill="#eef3f7"/>
<path d="M0 76 H140" stroke="#a8bacb" strokeOpacity=".5"/>
<text x="70" y="139" textAnchor="middle" className="ds-small" fill="#66788b">{config.d_model} → {config.d_model}</text>
</g>;
}
function StatePacket({x,y,color,opacity=1}:{x:number;y:number;color:string;opacity?:number}) {
return <g transform={`translate(${x} ${y})`} opacity={opacity} data-kind="hidden-state">{Array.from({length:6},(_,i)=><rect key={i} x={(i%2)*7} y={Math.floor(i/2)*7} width="5" height="5" rx="1" fill={color} fillOpacity={.45+(i%3)*.25}/>)}</g>;
}
function Lane({p,reverse,overview,id}:{p:number;reverse:boolean;overview:number;id:string}) {
const encoderX=reverse?600:52, decoderX=reverse?52:600;
const y=reverse?mix(230,413,overview):mix(230,119,overview);
const alpha=reverse?Math.max(phase(p,.515,.54),overview):Math.max(1-phase(p,.493,.515),overview);
const encoded=phase(p,reverse?.568:.072,reverse?.612:.16);
const projected=phase(p,reverse?.612:.18,reverse?.666:.30);
const writing=windowAt(p,reverse?.68:.32,reverse?.825:.493);
const encoding=reverse?windowAt(p,.515,.61):1-phase(p,.16,.185);
const projecting=reverse?windowAt(p,.61,.677):windowAt(p,.18,.315);
const share=sharingState(p);
const emphasis=(protein:boolean)=>Math.max(.3,protein?1-share.textFocus*.7:1-share.proteinFocus*.7);
const eFocus=Math.max(encoding,overview*emphasis(reverse)),dFocus=Math.max(writing,projecting*.55,overview*emphasis(!reverse)),wFocus=Math.max(projecting,overview*(1-Math.max(share.textFocus,share.proteinFocus)*.7));
const shared=(protein:boolean)=>protein?Math.max(share.proteinFocus,share.both*.65):Math.max(share.textFocus,share.both*.65);
const direction=reverse?-1:1;
const start=reverse?600:280, end=reverse?280:600;
return <g opacity={alpha} data-lane={reverse?'p2t':'t2p'}>
<g opacity={.25+.75*Math.max(projecting,writing,overview)}>
<path d={`M${start} ${y+123} H${end}`} fill="none" stroke="#c9d6e2" strokeWidth="2"/>
<path d={`M${start} ${y+123} H${end}`} fill="none" stroke={`url(#${id}-flow${reverse?'-reverse':''})`} strokeWidth="2.5" pathLength="1" strokeDasharray="1" strokeDashoffset={1-Math.max(projected,overview)} markerEnd={`url(#${id}-${reverse?'blue':'orange'}-arrow)`}/>
</g>
<Node x={encoderX} y={y} protein={reverse} decoder={false} focus={eFocus} sharing={shared(reverse)}/>
<Node x={decoderX} y={y} protein={!reverse} decoder focus={dFocus} sharing={shared(!reverse)} context={projected*(1-overview)}/>
<Projection x={370} y={y+47} reverse={reverse} focus={wFocus}/>
<g opacity={(1-overview)*encoded}>
<text x="440" y={y+4} textAnchor="middle" className="ds-micro" fill="#5c7085">HIDDEN STATES</text>
<text x="440" y={y+22} textAnchor="middle" className="ds-small" fill="#748598">Illustrative vectors</text>
{Array.from({length:7},(_,i)=>{
const travel=phase(p,(reverse?.612:.18)+i*.006,(reverse?.639:.255)+i*.006);
const emerge=phase(p,(reverse?.575:.095)+i*.005,(reverse?.595:.14)+i*.005);
const x=mix(start+direction*(12+i*9),end-direction*21,travel);
return <StatePacket key={i} x={x-6} y={y+113} color={travel>.55?(reverse?blue:orange):(reverse?orange:blue)} opacity={emerge*(1-phase(travel,.88,1))}/>;
})}
{Array.from({length:5},(_,i)=><StatePacket key={i} x={reverse?294:566} y={y+75+i*20} color={reverse?blue:orange} opacity={projected*.45}/>)}
</g>
<g opacity={overview}>
<text x={reverse?828:52} y={y-(reverse?15:25)} textAnchor={reverse?'end':'start'} className="ds-lane-label" fill={reverse?blue:orange}>{reverse?'02 PROTEIN → TEXT':'01 TEXT → PROTEIN'}</text>
<text x="440" y={y+202} textAnchor="middle" className="ds-small" fill="#64788a">{reverse?'Supervise with reference text':'Supervise with reference protein'}</text>
</g>
</g>;
}
function Input({p,reverse,example}:{p:number;reverse:boolean;example:Example}) {
const color=reverse?orange:blue;
const alpha=reverse?windowAt(p,.537,.815):1-phase(p,.477,.506);
const tokens=reverse?example.protein.slice(0,16).split(''):words(example.text).slice(0,9);
let wordX=52;
return <g opacity={alpha}>
<text x="52" y="35" className="ds-micro" fill={color}>{reverse?'REFERENCE PROTEIN · INDEPENDENT INPUT':'REFERENCE FUNCTION · HSP20 FAMILY'}</text>
<rect x="52" y="52" width="776" height="92" rx="10" fill={reverse?'#fff5ee':'#edf5fc'} stroke={color} strokeOpacity=".22"/>
{reverse?<>
<text x="72" y="90" className="ds-sequence" fill={orange}>{example.protein.slice(0,48)}</text>
<text x="72" y="119" className="ds-small" fill="#986651">First 48 of {example.protein.length} reference residues · not the generated sequence</text>
</>:wrap(example.text,79).map((line,i)=><text key={i} x="72" y={78+i*23} className="ds-input-text" fill={blue}>{line}</text>)}
{tokens.map((word,i)=>{
const w=reverse?37:word.length*8+18;
const x=reverse?52+i*48:wordX; wordX+=w+6;
const t=phase(p,(reverse?.546:.025)+i*.003,(reverse?.582:.085)+i*.003);
const fade=1-phase(t,.67,1);
return <g key={i} opacity={fade} transform={`translate(${mix(x,reverse?686:145,t)} ${mix(172,307,t)-Math.sin(t*Math.PI)*16})`}>
<rect width={w} height="32" rx="4" fill={color} fillOpacity=".11" stroke={color} strokeOpacity=".4"/>
<text x={w/2} y="21" textAnchor="middle" className="ds-input-token" fill={color}>{word}</text>
</g>;
})}
<g opacity={phase(p,reverse?.60:.128,reverse?.63:.16)}>
<path d={`M${reverse?714:166} 157 V209`} stroke={color} strokeOpacity=".25" strokeDasharray="3 5"/>
<text x={reverse?696:184} y="192" textAnchor={reverse?'end':'start'} className="ds-small" fill={color}>Encoded into contextual states</text>
</g>
</g>;
}
function Output({p,reverse,example}:{p:number;reverse:boolean;example:Example}) {
const start=reverse?.694:.335, end=reverse?.792:.467;
const alpha=phase(p,start-.015,start)*(1-phase(p,reverse?.823:.487,reverse?.85:.514));
const items=reverse?words(example.generatedText):example.generatedProtein.slice(0,residuePreviewCount).split('');
const color=reverse?blue:orange, origin=reverse?166:714;
let x=68,row=0;
return <g opacity={alpha} data-output={reverse?'text':'protein'}>
<path d={`M${origin} 435 V456 Q${origin} 468 ${origin-14} 468 H66`} fill="none" stroke={color} strokeOpacity=".2"/>
<circle cx={origin} cy="438" r="4" fill={color}/>
<text x="52" y="486" className="ds-micro" fill={color}>RECORDED {reverse?'TEXT':'PROTEIN'} OUTPUT</text>
{items.map((item,i)=>{
const width=reverse?item.length*9+22:26, height=reverse?40:28;
if (reverse && x+width>813) {x=68;row++;}
const tx=reverse?x:90+(i%24)*30,ty=reverse?508+row*53:508+Math.floor(i/24)*36;
x+=width+9;
const t=segment(p,start+i*(end-start)/items.length,start+(i+1.9)*(end-start)/items.length);
const eased=1-(1-t)**3;
const lift=Math.sin(t*Math.PI)*45;
return <g key={i} data-letter={item} data-arrived={t>=1} opacity={phase(t,0,.18)} transform={`translate(${mix(origin-width/2,tx,eased)} ${mix(438,ty,eased)-lift}) scale(${mix(.6,1,eased)})`}>
<rect y="3" width={width} height={height} rx={reverse?6:4} fill={color} fillOpacity=".1"/>
<rect width={width} height={height} rx={reverse?6:4} fill={reverse?'#e7f2fc':'#fff0e5'} stroke={color} strokeOpacity=".6"/>
<text x={width/2} y={reverse?27:20} textAnchor="middle" className={reverse?'ds-word':'ds-residue'} fill={color}>{item}</text>
</g>;
})}
{!reverse&&[0,1,2].map(row=><text key={row} x="52" y={528+row*36} className="ds-output-index" fill="#a48d7f">{String(row*24+1).padStart(3,'0')}</text>)}
<text x="52" y="648" className="ds-small" fill="#687b8b">{reverse?'Word excerpts · archived prediction · illustrative timing':`First ${items.length} of ${example.generatedProtein.length} generated residues · complete sequence below`}</text>
</g>;
}
export function DualScene({progress:p,example}:{progress:number;example:Example}) {
const id=useId().replace(/:/g,'');
const overview=phase(p,.839,.894);
const share=sharingState(p);
return <svg className="dual-scene-svg" viewBox="0 0 880 680" role="img" aria-label={`Ouroboros architecture, ${p<.515?'text to protein':p<.835?'protein to text':'joint supervised learning'}`} data-frame={p.toFixed(6)}>
<defs>
<linearGradient id={`${id}-flow`}><stop stopColor={blue}/><stop offset="1" stopColor={orange}/></linearGradient>
<linearGradient id={`${id}-flow-reverse`}><stop stopColor={blue}/><stop offset="1" stopColor={orange}/></linearGradient>
{[['blue',blue],['orange',orange]].map(([name,color])=><marker key={name} id={`${id}-${name}-arrow`} viewBox="0 0 8 8" refX="7" refY="4" markerWidth="5" markerHeight="5" orient="auto-start-reverse"><path d="M0 0 L8 4 L0 8" fill="none" stroke={color}/></marker>)}
</defs>
<g opacity={overview}>
<text x="52" y="36" className="ds-micro" fill="#596e82">ONE PAIRED EXAMPLE · TWO TEACHER-FORCED TRAINING TASKS</text>
<text x="828" y="36" textAnchor="end" className="ds-small" fill="#7b8995">large-v5</text>
</g>
<Input p={p} reverse={false} example={example}/>
<Input p={p} reverse example={example}/>
<Lane p={p} reverse={false} overview={overview} id={id}/>
<Lane p={p} reverse overview={overview} id={id}/>
<Output p={p} reverse={false} example={example}/>
<Output p={p} reverse example={example}/>
<g opacity={phase(p,.895,.908)} data-sharing="within-modality">
{[false,true].map(protein=>{
const color=protein?orange:blue,edge=protein?849:31,x=protein?828:52;
const progress=protein?share.protein:share.text,focus=protein?share.proteinFocus:share.textFocus;
return <g key={String(protein)} data-sharing-modality={protein?'protein':'text'} data-emphasis={focus.toFixed(4)} opacity={.2+.8*Math.max(progress,share.both)}>
<path d={`M${x} 207 H${edge} V501 H${x}`} fill="none" stroke={color} strokeOpacity=".18" strokeWidth="2"/>
<path d={`M${x} 207 H${edge} V501 H${x}`} fill="none" stroke={color} strokeWidth={1.5+focus*1.5} pathLength="1" strokeDasharray="1" strokeDashoffset={1-progress}/>
{[207,501].map(y=><g key={y}><circle cx={x} cy={y} r={3+focus*3} fill="#f8fafc" stroke={color} strokeWidth="2"/><circle cx={x} cy={y} r={6+focus*6} fill="none" stroke={color} strokeOpacity={focus*.3}/></g>)}
<rect x={protein?600:43} y="336" width="234" height="44" rx="8" fill={protein?'#fff0e7':'#e8f2fc'} stroke={color} strokeOpacity={focus}/>
<text x={protein?717:160} y="354" textAnchor="middle" className="ds-small" fill={color}>Same {protein?'protein':'text'} self-attention weights</text>
<text x={protein?717:160} y="371" textAnchor="middle" className="ds-shared-tag" fill={color}>ENCODER ↔ DECODER · BLOCKS 1–24</text>
</g>;
})}
<text x="440" y="651" textAnchor="middle" className="ds-objective" fill={ink}>L = ½ L(text → protein) + ½ L(protein → text)</text>
</g>
</svg>;
}