Spaces:
Running
Running
| /** | |
| * Aether Inference Server with Glossolalia Decoder | |
| * | |
| * SmolLM2-360M inference using WASM SIMD kernels. | |
| * Two endpoints: | |
| * /generate-standard -- standard top-p sampling | |
| * /generate-glossolalia -- temperature-ensemble fork/race/fold | |
| */ | |
| import { createServer } from 'http'; | |
| import { readFileSync, existsSync } from 'fs'; | |
| import { execSync } from 'child_process'; | |
| import { fileURLToPath } from 'url'; | |
| import { dirname, join } from 'path'; | |
| const __dirname = dirname(fileURLToPath(import.meta.url)); | |
| const PORT = parseInt(process.env.AETHER_PORT || '7861'); | |
| // βββ Model Configs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const CONFIGS = { | |
| 'smollm2-360m': { | |
| hiddenDim: 960, numLayers: 32, numHeads: 15, numKvHeads: 5, | |
| headDim: 64, intermediateSize: 2560, vocabSize: 49152, | |
| ropeTheta: 100000.0, rmsNormEps: 1e-5, eosToken: 2, | |
| }, | |
| 'qwen2.5-0.5b': { | |
| hiddenDim: 896, numLayers: 24, numHeads: 14, numKvHeads: 2, | |
| headDim: 64, intermediateSize: 4864, vocabSize: 151936, | |
| ropeTheta: 1000000.0, rmsNormEps: 1e-6, eosToken: 151645, // <|im_end|> | |
| }, | |
| }; | |
| // Five Bule Personality Profiles (THM-FIVE-BULE-PERSONALITY) | |
| // Each personality is a position on the fork/race/fold/vent/interfere axes | |
| const PERSONALITIES = { | |
| explorer: { temps: [0.8, 1.2, 1.6], topP: 0.98, absorbingThreshold: 5, label: 'Explorer -- forks broadly, high temperature diversity' }, | |
| builder: { temps: [0.2, 0.3, 0.5], topP: 0.70, absorbingThreshold: 4, label: 'Builder -- folds tightly, low temperature, precise' }, | |
| creative: { temps: [0.6, 1.0, 1.4], topP: 0.95, absorbingThreshold: 2, label: 'Creative -- races freely, aggressive C3 perturbation' }, | |
| anxious: { temps: [0.4, 0.6, 0.8], topP: 0.85, absorbingThreshold: 2, label: 'Anxious -- interferes early, cautious, frequent C3' }, | |
| balanced: { temps: [0.4, 0.7, 1.0], topP: 0.90, absorbingThreshold: 3, label: 'Balanced -- standard glossolalia, phi convergence' }, | |
| }; | |
| // Default config (overridden per-model) | |
| let C = CONFIGS['qwen2.5-0.5b']; | |
| let kvDim = C.numKvHeads * C.headDim; | |
| let gqaRatio = C.numHeads / C.numKvHeads; | |
| // βββ WASM SIMD ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| let simd = null; | |
| async function loadSIMD() { | |
| const p = join(__dirname, 'simd-kernels.wasm'); | |
| if (!existsSync(p)) return null; | |
| try { | |
| const { instance } = await WebAssembly.instantiate(readFileSync(p), { | |
| env: { expf: Math.exp, tanhf: Math.tanh, powf: Math.pow }, | |
| }); | |
| const w = instance.exports; w.resetHeap(65536); | |
| const mem = w.memory; | |
| const hf = () => new Float32Array(mem.buffer); | |
| const cp = (ptr, f) => hf().set(f, ptr >> 2); | |
| const rd = (ptr, n) => hf().slice(ptr >> 2, (ptr >> 2) + n); | |
| const wrap = (fn) => (...args) => { const s = w.getHeapPtr(); try { return fn(s, ...args); } finally { w.resetHeap(s); } }; | |
| console.log('[Aether] WASM SIMD loaded'); | |
| return { | |
| matVec: wrap((s, mat, vec, rows, cols) => { | |
| if (mat.byteLength > 100_000_000) return matVecJS(mat, vec, rows, cols); | |
| const mP=w.allocate(mat.byteLength),vP=w.allocate(vec.byteLength),rP=w.allocate(rows*4); | |
| cp(mP,mat);cp(vP,vec);w.matVecSimdBatch4(mP,vP,rP,rows,cols);return rd(rP,rows); | |
| }), | |
| rmsNorm: wrap((s,x,wt,eps) => { | |
| const xP=w.allocate(x.byteLength),wP=w.allocate(wt.byteLength),rP=w.allocate(x.byteLength); | |
| cp(xP,x);cp(wP,wt);w.rmsNormSimd(xP,wP,rP,x.length,eps);return rd(rP,x.length); | |
| }), | |
| softmax: wrap((s,x) => { | |
| const xP=w.allocate(x.byteLength),rP=w.allocate(x.byteLength); | |
| cp(xP,x);w.softmaxSimd(xP,rP,x.length);return rd(rP,x.length); | |
| }), | |
| fusedSiluMul: wrap((s,g,u) => { | |
| const gP=w.allocate(g.byteLength),uP=w.allocate(u.byteLength),rP=w.allocate(g.byteLength); | |
| cp(gP,g);cp(uP,u);w.fusedSiluMul(gP,uP,rP,g.length);return rd(rP,g.length); | |
| }), | |
| add: wrap((s,a,b) => { | |
| const aP=w.allocate(a.byteLength),bP=w.allocate(b.byteLength),rP=w.allocate(a.byteLength); | |
| cp(aP,a);cp(bP,b);w.addSimd(aP,bP,rP,a.length);return rd(rP,a.length); | |
| }), | |
| }; | |
| } catch(e) { console.warn('[Aether] WASM failed:',e.message); return null; } | |
| } | |
| // βββ JS Fallbacks βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function matVecJS(m,v,rows,cols){const o=new Float32Array(rows);for(let r=0;r<rows;r++){let s=0;const off=r*cols;for(let c=0;c<cols;c++)s+=m[off+c]*v[c];o[r]=s;}return o;} | |
| function rmsNormJS(x,w,eps){let ss=0;for(let i=0;i<x.length;i++)ss+=x[i]*x[i];ss=1/Math.sqrt(ss/x.length+eps);const o=new Float32Array(x.length);for(let i=0;i<x.length;i++)o[i]=x[i]*ss*w[i];return o;} | |
| function softmaxJS(x){let mx=-Infinity;for(let i=0;i<x.length;i++)if(x[i]>mx)mx=x[i];const o=new Float32Array(x.length);let s=0;for(let i=0;i<x.length;i++){o[i]=Math.exp(x[i]-mx);s+=o[i];}for(let i=0;i<x.length;i++)o[i]/=s;return o;} | |
| function fusedSiluMulJS(g,u){const o=new Float32Array(g.length);for(let i=0;i<g.length;i++){const v=g[i];o[i]=(v/(1+Math.exp(-v)))*u[i];}return o;} | |
| function addJS(a,b){const o=new Float32Array(a.length);for(let i=0;i<a.length;i++)o[i]=a[i]+b[i];return o;} | |
| const op = () => ({ matVec:simd?.matVec||matVecJS, rmsNorm:simd?.rmsNorm||rmsNormJS, softmax:simd?.softmax||softmaxJS, fusedSiluMul:simd?.fusedSiluMul||fusedSiluMulJS, add:simd?.add||addJS }); | |
| // βββ Q8_0 Dequant βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function fp16(lo,hi){const h=lo|(hi<<8),s=(h>>15)&1,e=(h>>10)&0x1f,f=h&0x3ff;if(e===0)return f===0?0:(s?-1:1)*(f/1024)*Math.pow(2,-14);if(e===31)return 0;return(s?-1:1)*Math.pow(2,e-15)*(1+f/1024);} | |
| function dequantQ8(data,n){const o=new Float32Array(n),nb=Math.ceil(n/32);for(let b=0;b<nb;b++){const off=b*34,sc=fp16(data[off],data[off+1]);const cnt=Math.min(32,n-b*32);for(let i=0;i<cnt;i++){const v=data[off+2+i];o[b*32+i]=(v>127?v-256:v)*sc;}}return o;} | |
| function dequantByType(data,n,type){if(type===0)return new Float32Array(data.buffer,data.byteOffset,n);if(type===8)return dequantQ8(data,n);if(type===1){const o=new Float32Array(n);for(let i=0;i<n;i++)o[i]=fp16(data[i*2],data[i*2+1]);return o;}return dequantQ8(data,n);} | |
| // βββ GGUF Parser ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const MAGIC=0x46554747;const BSZ={2:32,3:32,6:32,7:32,8:32,9:32,10:256,11:256,12:256,13:256,14:256,15:256};const BBY={2:18,3:20,6:22,7:24,8:34,9:36,10:84,11:110,12:144,13:176,14:210,15:292};const TSZ={0:4,1:2,16:1,17:2,18:4,19:8,20:8}; | |
| function csz(d,t){let n=1n;for(const x of d)n*=x;const b=BSZ[t];if(b&&BBY[t])return Math.ceil(Number(n)/b)*BBY[t];return Math.ceil(Number(n)*(TSZ[t]??4));} | |
| function rs(b,o){const l=Number(b.readBigUInt64LE(o));return{v:b.subarray(o+8,o+8+l).toString('utf8'),o:o+8+l};} | |
| function rv(b,o,t){switch(t){case 0:return{v:b.readUInt8(o),o:o+1};case 1:return{v:b.readInt8(o),o:o+1};case 2:return{v:b.readUInt16LE(o),o:o+2};case 3:return{v:b.readInt16LE(o),o:o+2};case 4:return{v:b.readUInt32LE(o),o:o+4};case 5:return{v:b.readInt32LE(o),o:o+4};case 6:return{v:b.readFloatLE(o),o:o+4};case 7:return{v:b.readUInt8(o)!==0,o:o+1};case 8:{const r=rs(b,o);return{v:r.v,o:r.o};}case 10:return{v:b.readBigUInt64LE(o),o:o+8};case 11:return{v:b.readBigInt64LE(o),o:o+8};case 12:return{v:b.readDoubleLE(o),o:o+8};case 9:{const at=b.readUInt32LE(o),al=Number(b.readBigUInt64LE(o+4));let co=o+12;const a=[];for(let i=0;i<al;i++){const r=rv(b,co,at);a.push(r.v);co=r.o;}return{v:a,o:co};}default:throw new Error(`Unknown GGUF type ${t}`);}} | |
| function parseGGUF(buf){let o=0;if(buf.readUInt32LE(o)!==MAGIC)throw new Error('Not GGUF');o+=4;o+=4;const tc=Number(buf.readBigUInt64LE(o));o+=8;const kc=Number(buf.readBigUInt64LE(o));o+=8;let align=32;for(let i=0;i<kc;i++){const{v:k,o:o1}=rs(buf,o);o=o1;const vt=buf.readUInt32LE(o);o+=4;const{v,o:o2}=rv(buf,o,vt);o=o2;if(k==='general.alignment')align=Number(v);}const tensors=[];for(let i=0;i<tc;i++){const{v:name,o:o1}=rs(buf,o);o=o1;const nd=buf.readUInt32LE(o);o+=4;const dims=[];for(let d=0;d<nd;d++){dims.push(buf.readBigUInt64LE(o));o+=8;}const type=buf.readUInt32LE(o);o+=4;const offset=buf.readBigUInt64LE(o);o+=8;tensors.push({name,dims,type,offset,size:csz(dims,type),numElements:Number(dims.reduce((a,b)=>a*b,1n))});}return{tensors,dataOffset:Math.ceil(o/align)*align};} | |
| // βββ BPE Tokenizer ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class Tok{constructor(j){const m=j.model||{};this.vocab=m.vocab||{};this.rev={};for(const[t,id]of Object.entries(this.vocab))this.rev[id]=t;this.mr={};for(const[i,mg]of(m.merges||[]).entries())this.mr[mg]=i;this.added={};if(j.added_tokens)for(const t of j.added_tokens)this.added[t.content]=t.id;} | |
| encode(text){const sp=/<\|[^|]+\|>/g;const parts=[];let last=0,m;while((m=sp.exec(text))!==null){if(m.index>last)parts.push({t:text.slice(last,m.index),s:false});parts.push({t:m[0],s:true});last=m.index+m[0].length;}if(last<text.length)parts.push({t:text.slice(last),s:false});const tokens=[];for(const p of parts){if(p.s){const id=this.added[p.t]??this.vocab[p.t];if(id!==undefined)tokens.push(id);continue;}const words=p.t.match(/\S+|\s+/g)||[];for(const w of words){let syms=[];for(const ch of w){if(this.vocab[ch]!==undefined)syms.push(ch);else for(const b of Buffer.from(ch,'utf8'))syms.push(`<0x${b.toString(16).toUpperCase().padStart(2,'0')}>`)}while(syms.length>1){let best=Infinity,bi=-1;for(let i=0;i<syms.length-1;i++){const r=this.mr[`${syms[i]} ${syms[i+1]}`];if(r!==undefined&&r<best){best=r;bi=i;}}if(bi===-1)break;syms.splice(bi,2,syms[bi]+syms[bi+1]);}for(const s of syms){const id=this.vocab[s]??this.added[s];if(id!==undefined)tokens.push(id);}}}return tokens;} | |
| decode(tokens){const p=[];for(const t of tokens){const s=this.rev[t];if(s&&s.startsWith('<0x')&&s.endsWith('>'))p.push(String.fromCharCode(parseInt(s.slice(3,-1),16)));else if(s&&!s.startsWith('<|'))p.push(s);}return p.join('').replace(/Δ /g,' ').replace(/Δ/g,'\n');}} | |
| // βββ RoPE (LLaMA style: ADJACENT pairs) βββββββββββββββββββββββββββββββββββββ | |
| function applyRoPE(x, headDim, position, theta) { | |
| for (let i = 0; i < headDim; i += 2) { | |
| const freq = 1.0 / Math.pow(theta, (2 * (i/2)) / headDim); | |
| const angle = position * freq; | |
| const cos = Math.cos(angle), sin = Math.sin(angle); | |
| const x0 = x[i], x1 = x[i + 1]; | |
| x[i] = x0 * cos - x1 * sin; | |
| x[i + 1] = x0 * sin + x1 * cos; | |
| } | |
| } | |
| // βββ Models βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const models = {}; | |
| let activeModel = null; | |
| function loadModel(name, ggufPath, tokPath, configName) { | |
| const cfg = CONFIGS[configName] || CONFIGS['smollm2-360m']; | |
| console.log(`[Aether] Loading ${name} (${configName}: ${cfg.numLayers}L, ${cfg.hiddenDim}d)...`); | |
| const t0=Date.now();const buf=readFileSync(ggufPath);const parsed=parseGGUF(buf); | |
| console.log(`[Aether] Parsed ${parsed.tensors.length} tensors in ${Date.now()-t0}ms`); | |
| const tokenizer=new Tok(JSON.parse(readFileSync(tokPath,'utf8'))); | |
| const byName={};for(const t of parsed.tensors)byName[t.name]=t; | |
| function get(nm){const t=byName[nm];if(!t)return null;const raw=new Uint8Array(buf.buffer,buf.byteOffset+parsed.dataOffset+Number(t.offset),t.size);return dequantByType(raw,t.numElements,t.type);} | |
| console.log('[Aether] Dequantizing...');const tokenEmbd=get('token_embd.weight');const layers=[]; | |
| for(let i=0;i<cfg.numLayers;i++){if(i%8===0)console.log(`[Aether] Layer ${i}/${cfg.numLayers}`);layers.push({an:get(`blk.${i}.attn_norm.weight`),fn:get(`blk.${i}.ffn_norm.weight`),qw:get(`blk.${i}.attn_q.weight`),kw:get(`blk.${i}.attn_k.weight`),vw:get(`blk.${i}.attn_v.weight`),ow:get(`blk.${i}.attn_output.weight`),gw:get(`blk.${i}.ffn_gate.weight`),uw:get(`blk.${i}.ffn_up.weight`),dw:get(`blk.${i}.ffn_down.weight`)});} | |
| const outNorm=get('output_norm.weight');let outWeight=get('output.weight');if(!outWeight){console.log('[Aether] Tied embeddings');outWeight=tokenEmbd;} | |
| const loadTime=Date.now()-t0; | |
| console.log(`[Aether] ${name} loaded in ${(loadTime/1000).toFixed(1)}s`); | |
| models[name]={tokenEmbd,layers,outNorm,outWeight,tokenizer,loadTime,name,config:cfg}; | |
| return models[name]; | |
| } | |
| function getModel(name) { | |
| return models[name] || models['base'] || Object.values(models)[0]; | |
| } | |
| // βββ Forward Pass (returns raw logits) ββββββββββββββββββββββββββββββββββββββ | |
| function forwardPass(prompt, modelName) { | |
| const o = op(); | |
| const model = getModel(modelName); | |
| const mc = model.config; // model-specific config | |
| const mcKvDim = mc.numKvHeads * mc.headDim; | |
| const mcGqaRatio = mc.numHeads / mc.numKvHeads; | |
| const chatPrompt = `<|im_start|>user\n${prompt}<|im_end|>\n<|im_start|>assistant\n`; | |
| const inputTokens = model.tokenizer.encode(chatPrompt); | |
| const allTokens = [...inputTokens]; | |
| const kvCache = Array.from({length:mc.numLayers},()=>({k:[],v:[]})); | |
| return { | |
| inputTokens, config: mc, | |
| step(allToks, kvC, diag) { | |
| const pos = allToks.length - 1; | |
| const tid = allToks[allToks.length - 1]; | |
| const x0 = model.tokenEmbd.slice(tid*mc.hiddenDim,(tid+1)*mc.hiddenDim); | |
| let x = x0; | |
| const layerNorms = diag ? [] : null; | |
| const attnEntropies = diag ? [] : null; | |
| for (let l=0;l<mc.numLayers;l++) { | |
| const ly=model.layers[l]; | |
| const xPrev = x; | |
| const normed=o.rmsNorm(x,ly.an,mc.rmsNormEps); | |
| const q=o.matVec(ly.qw,normed,mc.hiddenDim,mc.hiddenDim); | |
| const k=o.matVec(ly.kw,normed,mcKvDim,mc.hiddenDim); | |
| const v=o.matVec(ly.vw,normed,mcKvDim,mc.hiddenDim); | |
| for(let h=0;h<mc.numHeads;h++)applyRoPE(q.subarray(h*mc.headDim,(h+1)*mc.headDim),mc.headDim,pos,mc.ropeTheta); | |
| for(let h=0;h<mc.numKvHeads;h++)applyRoPE(k.subarray(h*mc.headDim,(h+1)*mc.headDim),mc.headDim,pos,mc.ropeTheta); | |
| kvC[l].k.push(new Float32Array(k));kvC[l].v.push(new Float32Array(v)); | |
| const seqLen=kvC[l].k.length;const attnOut=new Float32Array(mc.hiddenDim); | |
| const headEntropies = diag ? [] : null; | |
| for(let h=0;h<mc.numHeads;h++){const kvH=Math.floor(h/mcGqaRatio);const qH=q.subarray(h*mc.headDim,(h+1)*mc.headDim);const scores=new Float32Array(seqLen); | |
| for(let s=0;s<seqLen;s++){const kH=kvC[l].k[s].subarray(kvH*mc.headDim,(kvH+1)*mc.headDim);let dot=0;for(let d=0;d<mc.headDim;d++)dot+=qH[d]*kH[d];scores[s]=dot/Math.sqrt(mc.headDim);} | |
| const w=softmaxJS(scores); | |
| if (diag) { let he=0; for(let s=0;s<seqLen;s++) if(w[s]>1e-10) he-=w[s]*Math.log(w[s]); headEntropies.push(Math.round(he*1000)/1000); } | |
| for(let s=0;s<seqLen;s++){const vH=kvC[l].v[s].subarray(kvH*mc.headDim,(kvH+1)*mc.headDim);const wt=w[s];for(let d=0;d<mc.headDim;d++)attnOut[h*mc.headDim+d]+=wt*vH[d];}} | |
| if (diag) attnEntropies.push(headEntropies); | |
| const projected=o.matVec(ly.ow,attnOut,mc.hiddenDim,mc.hiddenDim);const postAttn=o.add(x,projected); | |
| const ffnIn=o.rmsNorm(postAttn,ly.fn,mc.rmsNormEps);const gate=o.matVec(ly.gw,ffnIn,mc.intermediateSize,mc.hiddenDim); | |
| const up=o.matVec(ly.uw,ffnIn,mc.intermediateSize,mc.hiddenDim);const activated=o.fusedSiluMul(gate,up); | |
| const down=o.matVec(ly.dw,activated,mc.hiddenDim,mc.intermediateSize);x=o.add(postAttn,down); | |
| if (diag) { | |
| let norm=0, delta=0, prevNorm=0; | |
| for(let i=0;i<mc.hiddenDim;i++) { norm+=x[i]*x[i]; delta+=(x[i]-xPrev[i])**2; prevNorm+=xPrev[i]*xPrev[i]; } | |
| layerNorms.push({ norm: Math.round(Math.sqrt(norm)*100)/100, residual: prevNorm>0 ? Math.round(Math.sqrt(delta/prevNorm)*1000)/1000 : 0 }); | |
| } | |
| } | |
| const finalNormed=o.rmsNorm(x,model.outNorm,mc.rmsNormEps); | |
| const logits = o.matVec(model.outWeight,finalNormed,mc.vocabSize,mc.hiddenDim); | |
| return { logits, layerNorms, attnEntropies }; | |
| } | |
| }; | |
| } | |
| // βββ Sampling Functions βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function sampleStandard(logits, temperature = 0.7, topP = 0.9) { | |
| const o = op(); | |
| const scaled = new Float32Array(logits.length); | |
| for (let i = 0; i < logits.length; i++) scaled[i] = logits[i] / temperature; | |
| const probs = o.softmax(scaled); | |
| // Top-p | |
| const indexed = Array.from(probs).map((p,i)=>({p,i})).sort((a,b)=>b.p-a.p); | |
| let cumP = 0; | |
| const candidates = []; | |
| for (const {p,i} of indexed) { cumP += p; candidates.push({p,i}); if (cumP >= topP) break; } | |
| const total = candidates.reduce((s,c) => s+c.p, 0); | |
| const r = Math.random() * total; | |
| let acc = 0; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) return i; } | |
| return candidates[0].i; | |
| } | |
| function glossolaliaMerge(rawLogits, temperatures = [0.4, 0.7, 1.0]) { | |
| const V = rawLogits.length; | |
| const logV = Math.log(V); | |
| const agents = []; | |
| for (const tau of temperatures) { | |
| const scaled = new Float32Array(V); | |
| for (let i = 0; i < V; i++) scaled[i] = rawLogits[i] / Math.max(tau, 0.01); | |
| const probs = softmaxJS(scaled); | |
| // Shannon entropy | |
| let h = 0; | |
| for (let i = 0; i < V; i++) { const p = probs[i]; if (p > 1e-12) h -= p * Math.log(p); } | |
| // Deficit weight: low entropy = high confidence = high weight | |
| const w = Math.max(1.0 - h / logV, 1e-8); // the sliver | |
| // Top-5 for diagnostics | |
| const top5 = Array.from(probs).map((p,i)=>({p,i})).sort((a,b)=>b.p-a.p).slice(0,5); | |
| agents.push({ probs, entropy: h, weight: w, tau, top5 }); | |
| } | |
| // Merge: weighted average | |
| const totalW = agents.reduce((s,a) => s + a.weight, 0); | |
| const merged = new Float32Array(V); | |
| for (const a of agents) { | |
| const nw = a.weight / totalW; | |
| for (let i = 0; i < V; i++) merged[i] += nw * a.probs[i]; | |
| } | |
| return { merged, agents, totalW }; | |
| } | |
| function sampleGlossolalia(logits) { | |
| const { merged, agents } = glossolaliaMerge(logits); | |
| const indexed = Array.from(merged).map((p,i)=>({p,i})).sort((a,b)=>b.p-a.p); | |
| let cumP = 0; | |
| const candidates = []; | |
| for (const {p,i} of indexed) { cumP += p; candidates.push({p,i}); if (cumP >= 0.95) break; } | |
| const total = candidates.reduce((s,c) => s+c.p, 0); | |
| const r = Math.random() * total; | |
| let acc = 0; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) return { tokenId: i, agents, merged }; } | |
| return { tokenId: candidates[0].i, agents, merged }; | |
| } | |
| // βββ C2/C3 Metacognitive Monitoring βββββββββββββββββββββββββββββββββββββββββ | |
| // C2: Detect entropy regime collapse (>50% drop in 3-token window) | |
| // C3: Detect absorbing states + apply diversity perturbation | |
| function detectRegimeChange(state) { | |
| const h = state.entropyHistory; | |
| if (h.length < 3) return false; | |
| const recent = h.slice(-3); | |
| const older = h.slice(-6, -3); | |
| if (older.length === 0) return false; | |
| const recentMean = recent.reduce((a, b) => a + b, 0) / recent.length; | |
| const olderMean = older.reduce((a, b) => a + b, 0) / older.length; | |
| return olderMean > 0 && recentMean < olderMean * 0.5; | |
| } | |
| function metacognitiveC3(logits, state, selectedToken, absorbingThreshold = 3) { | |
| // Update repeat tracking | |
| if (selectedToken === state.lastToken) state.repeatCount++; | |
| else { state.repeatCount = 0; state.lastToken = selectedToken; } | |
| const isAbsorbing = state.repeatCount >= absorbingThreshold; | |
| const isRegimeCollapse = detectRegimeChange(state); | |
| if (!isAbsorbing && !isRegimeCollapse) { | |
| return { logits, perturbed: false, reason: null }; | |
| } | |
| // Perturbation: eta scales with repetition depth | |
| const eta = 0.1 * (1 + state.repeatCount); | |
| const perturbed = new Float32Array(logits.length); | |
| let totalOther = 0; | |
| for (let i = 0; i < logits.length; i++) if (i !== selectedToken && logits[i] > 0) totalOther += logits[i]; | |
| const redistributionMass = Math.abs(logits[selectedToken]) * eta; | |
| for (let i = 0; i < logits.length; i++) { | |
| if (i === selectedToken) perturbed[i] = logits[i] * (1 - eta); | |
| else if (totalOther > 0 && logits[i] > 0) perturbed[i] = logits[i] + redistributionMass * (logits[i] / totalOther); | |
| else perturbed[i] = logits[i]; | |
| } | |
| state.perturbationCount++; | |
| return { | |
| logits: perturbed, | |
| perturbed: true, | |
| reason: isAbsorbing ? `absorbing(${state.repeatCount} repeats)` : 'regime_collapse', | |
| eta, | |
| }; | |
| } | |
| function sampleWithMetacog(rawLogits, metacogState) { | |
| const { merged, agents } = glossolaliaMerge(rawLogits); | |
| // Compute merged entropy for C2 tracking | |
| let mergedEntropy = 0; | |
| for (let i = 0; i < merged.length; i++) { const p = merged[i]; if (p > 1e-12) mergedEntropy -= p * Math.log(p); } | |
| metacogState.entropyHistory.push(mergedEntropy); | |
| // First sample from merged (pre-C3) to detect what token would be chosen | |
| const indexed = Array.from(merged).map((p,i)=>({p,i})).sort((a,b)=>b.p-a.p); | |
| let cumP = 0, candidates = []; | |
| for (const {p,i} of indexed) { cumP += p; candidates.push({p,i}); if (cumP >= 0.95) break; } | |
| let total = candidates.reduce((s,c) => s+c.p, 0); | |
| let r = Math.random() * total, acc = 0, preC3Token = candidates[0].i; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) { preC3Token = i; break; } } | |
| // C3: check and potentially perturb | |
| const c3 = metacognitiveC3(rawLogits, metacogState, preC3Token); | |
| let finalToken = preC3Token; | |
| if (c3.perturbed) { | |
| // Re-merge with perturbed logits | |
| const { merged: remerged } = glossolaliaMerge(c3.logits); | |
| const ridx = Array.from(remerged).map((p,i)=>({p,i})).sort((a,b)=>b.p-a.p); | |
| cumP = 0; candidates = []; | |
| for (const {p,i} of ridx) { cumP += p; candidates.push({p,i}); if (cumP >= 0.95) break; } | |
| total = candidates.reduce((s,c) => s+c.p, 0); | |
| r = Math.random() * total; acc = 0; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) { finalToken = i; break; } } | |
| } | |
| return { | |
| tokenId: finalToken, agents, merged, mergedEntropy, | |
| c3: { perturbed: c3.perturbed, reason: c3.reason, eta: c3.eta, | |
| preC3Token, repeatCount: metacogState.repeatCount, | |
| perturbationCount: metacogState.perturbationCount }, | |
| }; | |
| } | |
| // βββ Generation Loops βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function generateStandard(prompt, maxTokens = 8192, modelName = 'buleyean') { | |
| const t0 = performance.now(); | |
| const model = getModel(modelName); | |
| const fwd = forwardPass(prompt, modelName); | |
| const allTokens = [...fwd.inputTokens]; | |
| const kvC = Array.from({length:model.config.numLayers},()=>({k:[],v:[]})); | |
| const tokenTimes = []; | |
| // Prefill | |
| for (let i = 0; i < fwd.inputTokens.length; i++) { | |
| fwd.step(allTokens.slice(0, i+1), kvC, false); | |
| } | |
| const perTokenInfo = []; | |
| // Decode | |
| for (let i = 0; i < maxTokens; i++) { | |
| const ts = performance.now(); | |
| const { logits, layerNorms, attnEntropies } = fwd.step(allTokens, kvC, true); | |
| const o2 = op(); | |
| const scaled = new Float32Array(logits.length); | |
| for (let j = 0; j < logits.length; j++) scaled[j] = logits[j] / 0.7; | |
| const probs = o2.softmax(scaled); | |
| const chosen = sampleStandard(logits); | |
| const chosenProb = probs[chosen]; | |
| const perplexity = chosenProb > 0 ? -Math.log2(chosenProb) : 99; | |
| // Vocab coverage: tokens with >0.1% probability | |
| let vocabCoverage = 0; | |
| for (let j = 0; j < probs.length; j++) if (probs[j] > 0.001) vocabCoverage++; | |
| // Top-5 | |
| const top5 = Array.from(probs).map((p,j)=>({p,i:j})).sort((a,b)=>b.p-a.p).slice(0,5) | |
| .map(t => ({ token: model.tokenizer.decode([t.i]), prob: Math.round(t.p*1000)/1000 })); | |
| tokenTimes.push(performance.now() - ts); | |
| perTokenInfo.push({ perplexity: Math.round(perplexity*100)/100, chosenProb: Math.round(chosenProb*1000)/1000, vocabCoverage, top5, layerNorms, attnEntropies }); | |
| if (chosen === model.config.eosToken) break; | |
| allTokens.push(chosen); | |
| } | |
| const genTokens = allTokens.slice(fwd.inputTokens.length); | |
| const totalTime = performance.now() - t0; | |
| const avgMs = tokenTimes.length > 0 ? tokenTimes.reduce((a,b)=>a+b,0)/tokenTimes.length : 0; | |
| return { | |
| text: model.tokenizer.decode(genTokens), tokens: genTokens.length, | |
| totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs), | |
| mode: 'standard', temperature: 0.7, topP: 0.9, | |
| tokenDiagnostics: perTokenInfo, | |
| }; | |
| } | |
| function generateGlossolalia(prompt, maxTokens = 8192, modelName = 'buleyean') { | |
| const t0 = performance.now(); | |
| const model = getModel(modelName); | |
| const fwd = forwardPass(prompt, modelName); | |
| const allTokens = [...fwd.inputTokens]; | |
| const kvC = Array.from({length:model.config.numLayers},()=>({k:[],v:[]})); | |
| const tokenTimes = []; | |
| const perTokenDiag = []; | |
| // Prefill | |
| for (let i = 0; i < fwd.inputTokens.length; i++) { | |
| fwd.step(allTokens.slice(0, i+1), kvC, false); | |
| } | |
| // Decode with Glossolalia | |
| for (let i = 0; i < maxTokens; i++) { | |
| const ts = performance.now(); | |
| const { logits, layerNorms, attnEntropies } = fwd.step(allTokens, kvC, true); | |
| const { tokenId, agents } = sampleGlossolalia(logits); | |
| // Token-level perplexity from merged distribution | |
| const { merged } = glossolaliaMerge(logits); | |
| const chosenProb = merged[tokenId] || 0; | |
| const perplexity = chosenProb > 0 ? -Math.log2(chosenProb) : 99; | |
| let vocabCoverage = 0; | |
| for (let j = 0; j < merged.length; j++) if (merged[j] > 0.001) vocabCoverage++; | |
| tokenTimes.push(performance.now() - ts); | |
| perTokenDiag.push({ | |
| agents: agents.map(a => ({ | |
| tau: a.tau, entropy: Math.round(a.entropy*1000)/1000, weight: Math.round(a.weight*1000)/1000, | |
| top3: a.top5.slice(0,3).map(t => ({ token: model.tokenizer.decode([t.i]), prob: Math.round(t.p*1000)/1000 })), | |
| })), | |
| perplexity: Math.round(perplexity*100)/100, | |
| chosenProb: Math.round(chosenProb*1000)/1000, | |
| vocabCoverage, | |
| layerNorms, | |
| attnEntropies, | |
| }); | |
| if (tokenId === model.config.eosToken) break; | |
| allTokens.push(tokenId); | |
| } | |
| const genTokens = allTokens.slice(fwd.inputTokens.length); | |
| const totalTime = performance.now() - t0; | |
| const avgMs = tokenTimes.length > 0 ? tokenTimes.reduce((a,b)=>a+b,0)/tokenTimes.length : 0; | |
| return { | |
| text: model.tokenizer.decode(genTokens), tokens: genTokens.length, | |
| totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs), | |
| mode: 'glossolalia', temperatures: [0.4, 0.7, 1.0], | |
| diagnostics: perTokenDiag, | |
| }; | |
| } | |
| // βββ Metacog Generation (Glossolalia + C2/C3) βββββββββββββββββββββββββββββββ | |
| function generateMetacog(prompt, maxTokens = 8192, modelName = 'buleyean') { | |
| const t0 = performance.now(); | |
| const model = getModel(modelName); | |
| const fwd = forwardPass(prompt, modelName); | |
| const allTokens = [...fwd.inputTokens]; | |
| const kvC = Array.from({length:model.config.numLayers},()=>({k:[],v:[]})); | |
| const tokenTimes = []; | |
| const perTokenDiag = []; | |
| // Metacognitive state (persists across tokens) | |
| const metacogState = { repeatCount: 0, lastToken: -1, entropyHistory: [], perturbationCount: 0 }; | |
| // Prefill | |
| for (let i = 0; i < fwd.inputTokens.length; i++) { | |
| fwd.step(allTokens.slice(0, i+1), kvC, false); | |
| } | |
| // Decode with Glossolalia + C2/C3 | |
| for (let i = 0; i < maxTokens; i++) { | |
| const ts = performance.now(); | |
| const { logits, layerNorms } = fwd.step(allTokens, kvC, true); | |
| const result = sampleWithMetacog(logits, metacogState); | |
| const chosenProb = result.merged[result.tokenId] || 0; | |
| const perplexity = chosenProb > 0 ? -Math.log2(chosenProb) : 99; | |
| let vocabCoverage = 0; | |
| for (let j = 0; j < result.merged.length; j++) if (result.merged[j] > 0.001) vocabCoverage++; | |
| tokenTimes.push(performance.now() - ts); | |
| perTokenDiag.push({ | |
| agents: result.agents.map(a => ({ | |
| tau: a.tau, entropy: Math.round(a.entropy*1000)/1000, weight: Math.round(a.weight*1000)/1000, | |
| top3: a.top5.slice(0,3).map(t => ({ token: model.tokenizer.decode([t.i]), prob: Math.round(t.p*1000)/1000 })), | |
| })), | |
| perplexity: Math.round(perplexity*100)/100, | |
| chosenProb: Math.round(chosenProb*1000)/1000, | |
| vocabCoverage, | |
| layerNorms, | |
| c3: result.c3, | |
| mergedEntropy: Math.round(result.mergedEntropy*1000)/1000, | |
| }); | |
| if (result.tokenId === model.config.eosToken) break; | |
| allTokens.push(result.tokenId); | |
| } | |
| const genTokens = allTokens.slice(fwd.inputTokens.length); | |
| const totalTime = performance.now() - t0; | |
| const avgMs = tokenTimes.length > 0 ? tokenTimes.reduce((a,b)=>a+b,0)/tokenTimes.length : 0; | |
| return { | |
| text: model.tokenizer.decode(genTokens), tokens: genTokens.length, | |
| totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs), | |
| mode: 'metacog', temperatures: [0.4, 0.7, 1.0], | |
| diagnostics: perTokenDiag, | |
| metacogSummary: { | |
| totalPerturbations: metacogState.perturbationCount, | |
| finalRepeatCount: metacogState.repeatCount, | |
| entropyHistory: metacogState.entropyHistory.map(h => Math.round(h*1000)/1000), | |
| }, | |
| }; | |
| } | |
| // βββ Personality Generation ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function generatePersonality(prompt, maxTokens = 8192, modelName = 'buleyean-smollm2', personalityName = 'balanced') { | |
| const personality = PERSONALITIES[personalityName] || PERSONALITIES.balanced; | |
| const model = getModel(modelName); | |
| const mc = model.config; | |
| const t0 = performance.now(); | |
| const fwd = forwardPass(prompt, modelName); | |
| const allTokens = [...fwd.inputTokens]; | |
| const kvC = Array.from({length:mc.numLayers},()=>({k:[],v:[]})); | |
| const tokenTimes = []; | |
| const metacogState = { repeatCount: 0, lastToken: -1, entropyHistory: [], perturbationCount: 0 }; | |
| for (let i = 0; i < fwd.inputTokens.length; i++) fwd.step(allTokens.slice(0,i+1), kvC, false); | |
| for (let i = 0; i < maxTokens; i++) { | |
| const ts = performance.now(); | |
| const { logits } = fwd.step(allTokens, kvC, false); | |
| const { merged } = glossolaliaMerge(logits, personality.temps); | |
| let mergedEntropy = 0; | |
| for (let j = 0; j < merged.length; j++) { const p = merged[j]; if (p > 1e-12) mergedEntropy -= p * Math.log(p); } | |
| metacogState.entropyHistory.push(mergedEntropy); | |
| const indexed = Array.from(merged).map((p,j)=>({p,i:j})).sort((a,b)=>b.p-a.p); | |
| let cumP = 0, candidates = []; | |
| for (const {p,i} of indexed) { cumP += p; candidates.push({p,i}); if (cumP >= personality.topP) break; } | |
| let total = candidates.reduce((s,c) => s+c.p, 0); | |
| let r = Math.random() * total, acc = 0, preC3Token = candidates[0].i; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) { preC3Token = i; break; } } | |
| const c3 = metacognitiveC3(logits, metacogState, preC3Token, personality.absorbingThreshold); | |
| let finalToken = preC3Token; | |
| if (c3.perturbed) { | |
| const { merged: rm } = glossolaliaMerge(c3.logits, personality.temps); | |
| const ri = Array.from(rm).map((p,j)=>({p,i:j})).sort((a,b)=>b.p-a.p); | |
| cumP = 0; candidates = []; | |
| for (const {p,i} of ri) { cumP += p; candidates.push({p,i}); if (cumP >= personality.topP) break; } | |
| total = candidates.reduce((s,c) => s+c.p, 0); | |
| r = Math.random() * total; acc = 0; | |
| for (const {p,i} of candidates) { acc += p; if (r < acc) { finalToken = i; break; } } | |
| } | |
| tokenTimes.push(performance.now() - ts); | |
| if (finalToken === mc.eosToken) break; | |
| allTokens.push(finalToken); | |
| } | |
| const genTokens = allTokens.slice(fwd.inputTokens.length); | |
| const totalTime = performance.now() - t0; | |
| const avgMs = tokenTimes.length > 0 ? tokenTimes.reduce((a,b)=>a+b,0)/tokenTimes.length : 0; | |
| return { | |
| text: model.tokenizer.decode(genTokens), tokens: genTokens.length, | |
| totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs), | |
| mode: 'personality', personality: personalityName, | |
| personalityLabel: personality.label, | |
| temperatures: personality.temps, | |
| modelName, | |
| metacogSummary: { totalPerturbations: metacogState.perturbationCount }, | |
| }; | |
| } | |
| // βββ HTTP Server ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const server = createServer((req, res) => { | |
| let body = ''; | |
| req.on('data', c => body += c); | |
| req.on('end', () => { | |
| try { | |
| if (req.url === '/health') { | |
| res.writeHead(200,{'Content-Type':'application/json'}); | |
| res.end(JSON.stringify({status:'ok',models:Object.keys(models),personalities:Object.keys(PERSONALITIES),simd:!!simd})); | |
| return; | |
| } | |
| if (req.method !== 'POST') { res.writeHead(404); res.end(); return; } | |
| const { prompt, max_tokens, model, personality } = JSON.parse(body); | |
| const mn = model || 'buleyean-smollm2'; | |
| let result; | |
| if (req.url === '/generate-personality') result = generatePersonality(prompt, max_tokens||128, mn, personality||'balanced'); | |
| else if (req.url === '/generate-standard') result = generateStandard(prompt, max_tokens||128, mn); | |
| else if (req.url === '/generate-glossolalia') result = generateGlossolalia(prompt, max_tokens||128, mn); | |
| else if (req.url === '/generate-metacog') result = generateMetacog(prompt, max_tokens||128, mn); | |
| else { res.writeHead(404); res.end(); return; } | |
| res.writeHead(200, { 'Content-Type': 'application/json' }); | |
| res.end(JSON.stringify(result)); | |
| } catch (e) { | |
| console.error('[Aether]', e); | |
| res.writeHead(500, { 'Content-Type': 'application/json' }); | |
| res.end(JSON.stringify({ error: e.message })); | |
| } | |
| }); | |
| }); | |
| // βββ Model Registry βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const MODEL_REGISTRY = [ | |
| { name: 'buleyean-smollm2', repo: 'forkjoin-ai/buleyean-smollm2-360m', file: 'buleyean-smollm2-360m-q8_0.gguf', tokRepo: 'HuggingFaceTB/SmolLM2-360M-Instruct', config: 'smollm2-360m' }, | |
| { name: 'base-smollm2', repo: 'bartowski/SmolLM2-360M-Instruct-GGUF', file: 'SmolLM2-360M-Instruct-Q8_0.gguf', tokRepo: 'HuggingFaceTB/SmolLM2-360M-Instruct', config: 'smollm2-360m' }, | |
| { name: 'buleyean-qwen', repo: 'forkjoin-ai/buleyean-qwen2.5-0.5b', file: 'buleyean-qwen2.5-0.5b-q8_0.gguf', tokRepo: 'Qwen/Qwen2.5-0.5B-Instruct', config: 'qwen2.5-0.5b' }, | |
| { name: 'base-qwen', repo: 'bartowski/Qwen2.5-0.5B-Instruct-GGUF', file: 'Qwen2.5-0.5B-Instruct-Q8_0.gguf', tokRepo: 'Qwen/Qwen2.5-0.5B-Instruct', config: 'qwen2.5-0.5b' }, | |
| ]; | |
| function dl(repo, file) { | |
| const local = `/tmp/hf_cache/${file}`; | |
| if (existsSync(local)) return local; | |
| console.log(`[Aether] Downloading ${repo}/${file}...`); | |
| execSync(`python3 -c "from huggingface_hub import hf_hub_download; hf_hub_download('${repo}', '${file}', cache_dir='/tmp/hf_cache', local_dir='/tmp/hf_cache')"`, { stdio: 'inherit' }); | |
| return local; | |
| } | |
| function dlTok(repo) { | |
| const local = `/tmp/hf_cache/tokenizer-${repo.replace(/\//g,'-')}.json`; | |
| if (existsSync(local)) return local; | |
| console.log(`[Aether] Downloading tokenizer from ${repo}...`); | |
| execSync(`python3 -c "from huggingface_hub import hf_hub_download; p=hf_hub_download('${repo}', 'tokenizer.json'); import shutil; shutil.copy(p, '${local}')"`, { stdio: 'inherit' }); | |
| return local; | |
| } | |
| async function main() { | |
| simd = await loadSIMD(); | |
| // Load all models that fit in memory (load sequentially, keep all) | |
| for (const m of MODEL_REGISTRY) { | |
| try { | |
| const gguf = dl(m.repo, m.file); | |
| const tok = dlTok(m.tokRepo); | |
| loadModel(m.name, gguf, tok, m.config); | |
| } catch (e) { | |
| console.error(`[Aether] Failed to load ${m.name}: ${e.message}`); | |
| } | |
| } | |
| server.listen(PORT, '127.0.0.1', () => console.log(`[Aether] http://127.0.0.1:${PORT} (SIMD: ${!!simd}, models: ${Object.keys(models).join(', ')})`)); | |
| } | |
| main().catch(e => { console.error('[Aether] Fatal:', e); process.exit(1); }); | |