Spaces:
Sleeping
Sleeping
Taylor commited on
Commit Β·
a902eca
1
Parent(s): d903d74
feat: deep diagnostics + uncapped tokens (up to 512)
Browse filesThree diagnostic panels:
- Glossolalia Agent Diagnostics: per-token perplexity, vocab coverage,
deficit weights, entropy, top-3 per agent
- Standard Sampling Diagnostics: per-token perplexity, confidence,
vocab coverage, top-3 predictions
- Layer Health: per-layer hidden state norms and residual contribution
through all 32 transformer layers
Token limit raised to 512 (slider) / 8192 (server). Zero cost --
all Aether, no API calls.
- aether-server.mjs +66 -18
- app.py +109 -49
aether-server.mjs
CHANGED
|
@@ -131,13 +131,17 @@ function forwardPass(prompt) {
|
|
| 131 |
// Returns a function that generates one token at a time
|
| 132 |
return {
|
| 133 |
inputTokens,
|
| 134 |
-
step(allToks, kvC) {
|
| 135 |
const pos = allToks.length - 1;
|
| 136 |
const tid = allToks[allToks.length - 1];
|
| 137 |
const x0 = model.tokenEmbd.slice(tid*C.hiddenDim,(tid+1)*C.hiddenDim);
|
| 138 |
let x = x0;
|
|
|
|
|
|
|
|
|
|
| 139 |
for (let l=0;l<C.numLayers;l++) {
|
| 140 |
const ly=model.layers[l];
|
|
|
|
| 141 |
const normed=o.rmsNorm(x,ly.an,C.rmsNormEps);
|
| 142 |
const q=o.matVec(ly.qw,normed,C.hiddenDim,C.hiddenDim);
|
| 143 |
const k=o.matVec(ly.kw,normed,kvDim,C.hiddenDim);
|
|
@@ -146,16 +150,29 @@ function forwardPass(prompt) {
|
|
| 146 |
for(let h=0;h<C.numKvHeads;h++)applyRoPE(k.subarray(h*C.headDim,(h+1)*C.headDim),C.headDim,pos,C.ropeTheta);
|
| 147 |
kvC[l].k.push(new Float32Array(k));kvC[l].v.push(new Float32Array(v));
|
| 148 |
const seqLen=kvC[l].k.length;const attnOut=new Float32Array(C.hiddenDim);
|
|
|
|
| 149 |
for(let h=0;h<C.numHeads;h++){const kvH=Math.floor(h/gqaRatio);const qH=q.subarray(h*C.headDim,(h+1)*C.headDim);const scores=new Float32Array(seqLen);
|
| 150 |
for(let s=0;s<seqLen;s++){const kH=kvC[l].k[s].subarray(kvH*C.headDim,(kvH+1)*C.headDim);let dot=0;for(let d=0;d<C.headDim;d++)dot+=qH[d]*kH[d];scores[s]=dot/Math.sqrt(C.headDim);}
|
| 151 |
-
const w=softmaxJS(scores);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
const projected=o.matVec(ly.ow,attnOut,C.hiddenDim,C.hiddenDim);const postAttn=o.add(x,projected);
|
| 153 |
const ffnIn=o.rmsNorm(postAttn,ly.fn,C.rmsNormEps);const gate=o.matVec(ly.gw,ffnIn,C.intermediateSize,C.hiddenDim);
|
| 154 |
const up=o.matVec(ly.uw,ffnIn,C.intermediateSize,C.hiddenDim);const activated=o.fusedSiluMul(gate,up);
|
| 155 |
const down=o.matVec(ly.dw,activated,C.hiddenDim,C.intermediateSize);x=o.add(postAttn,down);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
}
|
| 157 |
const finalNormed=o.rmsNorm(x,model.outNorm,C.rmsNormEps);
|
| 158 |
-
|
|
|
|
| 159 |
}
|
| 160 |
};
|
| 161 |
}
|
|
@@ -230,7 +247,7 @@ function sampleGlossolalia(logits) {
|
|
| 230 |
|
| 231 |
// βββ Generation Loops βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 232 |
|
| 233 |
-
function generateStandard(prompt, maxTokens =
|
| 234 |
const t0 = performance.now();
|
| 235 |
const fwd = forwardPass(prompt);
|
| 236 |
const allTokens = [...fwd.inputTokens];
|
|
@@ -239,15 +256,35 @@ function generateStandard(prompt, maxTokens = 48) {
|
|
| 239 |
|
| 240 |
// Prefill
|
| 241 |
for (let i = 0; i < fwd.inputTokens.length; i++) {
|
| 242 |
-
fwd.step(allTokens.slice(0, i+1), kvC);
|
| 243 |
}
|
| 244 |
|
|
|
|
|
|
|
| 245 |
// Decode
|
| 246 |
for (let i = 0; i < maxTokens; i++) {
|
| 247 |
const ts = performance.now();
|
| 248 |
-
const logits = fwd.step(allTokens, kvC);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
const chosen = sampleStandard(logits);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
tokenTimes.push(performance.now() - ts);
|
|
|
|
|
|
|
| 251 |
if (chosen === C.eosToken) break;
|
| 252 |
allTokens.push(chosen);
|
| 253 |
}
|
|
@@ -260,10 +297,11 @@ function generateStandard(prompt, maxTokens = 48) {
|
|
| 260 |
text: model.tokenizer.decode(genTokens), tokens: genTokens.length,
|
| 261 |
totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs),
|
| 262 |
mode: 'standard', temperature: 0.7, topP: 0.9,
|
|
|
|
| 263 |
};
|
| 264 |
}
|
| 265 |
|
| 266 |
-
function generateGlossolalia(prompt, maxTokens =
|
| 267 |
const t0 = performance.now();
|
| 268 |
const fwd = forwardPass(prompt);
|
| 269 |
const allTokens = [...fwd.inputTokens];
|
|
@@ -273,25 +311,35 @@ function generateGlossolalia(prompt, maxTokens = 48) {
|
|
| 273 |
|
| 274 |
// Prefill
|
| 275 |
for (let i = 0; i < fwd.inputTokens.length; i++) {
|
| 276 |
-
fwd.step(allTokens.slice(0, i+1), kvC);
|
| 277 |
}
|
| 278 |
|
| 279 |
// Decode with Glossolalia
|
| 280 |
for (let i = 0; i < maxTokens; i++) {
|
| 281 |
const ts = performance.now();
|
| 282 |
-
const logits = fwd.step(allTokens, kvC);
|
| 283 |
const { tokenId, agents } = sampleGlossolalia(logits);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
tokenTimes.push(performance.now() - ts);
|
| 285 |
|
| 286 |
-
perTokenDiag.push(
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
top3: a.top5.slice(0, 3).map(t => ({
|
| 291 |
-
token: model.tokenizer.decode([t.i]),
|
| 292 |
-
prob: Math.round(t.p * 1000) / 1000,
|
| 293 |
})),
|
| 294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
|
| 296 |
if (tokenId === C.eosToken) break;
|
| 297 |
allTokens.push(tokenId);
|
|
@@ -317,7 +365,7 @@ const server = createServer((req, res) => {
|
|
| 317 |
req.on('end', () => {
|
| 318 |
try {
|
| 319 |
const { prompt, max_tokens } = JSON.parse(body);
|
| 320 |
-
const result = genFn(prompt, max_tokens ||
|
| 321 |
res.writeHead(200, { 'Content-Type': 'application/json' });
|
| 322 |
res.end(JSON.stringify(result));
|
| 323 |
} catch (e) {
|
|
|
|
| 131 |
// Returns a function that generates one token at a time
|
| 132 |
return {
|
| 133 |
inputTokens,
|
| 134 |
+
step(allToks, kvC, diag) {
|
| 135 |
const pos = allToks.length - 1;
|
| 136 |
const tid = allToks[allToks.length - 1];
|
| 137 |
const x0 = model.tokenEmbd.slice(tid*C.hiddenDim,(tid+1)*C.hiddenDim);
|
| 138 |
let x = x0;
|
| 139 |
+
const layerNorms = diag ? [] : null;
|
| 140 |
+
const attnEntropies = diag ? [] : null;
|
| 141 |
+
|
| 142 |
for (let l=0;l<C.numLayers;l++) {
|
| 143 |
const ly=model.layers[l];
|
| 144 |
+
const xPrev = x;
|
| 145 |
const normed=o.rmsNorm(x,ly.an,C.rmsNormEps);
|
| 146 |
const q=o.matVec(ly.qw,normed,C.hiddenDim,C.hiddenDim);
|
| 147 |
const k=o.matVec(ly.kw,normed,kvDim,C.hiddenDim);
|
|
|
|
| 150 |
for(let h=0;h<C.numKvHeads;h++)applyRoPE(k.subarray(h*C.headDim,(h+1)*C.headDim),C.headDim,pos,C.ropeTheta);
|
| 151 |
kvC[l].k.push(new Float32Array(k));kvC[l].v.push(new Float32Array(v));
|
| 152 |
const seqLen=kvC[l].k.length;const attnOut=new Float32Array(C.hiddenDim);
|
| 153 |
+
const headEntropies = diag ? [] : null;
|
| 154 |
for(let h=0;h<C.numHeads;h++){const kvH=Math.floor(h/gqaRatio);const qH=q.subarray(h*C.headDim,(h+1)*C.headDim);const scores=new Float32Array(seqLen);
|
| 155 |
for(let s=0;s<seqLen;s++){const kH=kvC[l].k[s].subarray(kvH*C.headDim,(kvH+1)*C.headDim);let dot=0;for(let d=0;d<C.headDim;d++)dot+=qH[d]*kH[d];scores[s]=dot/Math.sqrt(C.headDim);}
|
| 156 |
+
const w=softmaxJS(scores);
|
| 157 |
+
// Attention entropy per head
|
| 158 |
+
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); }
|
| 159 |
+
for(let s=0;s<seqLen;s++){const vH=kvC[l].v[s].subarray(kvH*C.headDim,(kvH+1)*C.headDim);const wt=w[s];for(let d=0;d<C.headDim;d++)attnOut[h*C.headDim+d]+=wt*vH[d];}}
|
| 160 |
+
if (diag) attnEntropies.push(headEntropies);
|
| 161 |
const projected=o.matVec(ly.ow,attnOut,C.hiddenDim,C.hiddenDim);const postAttn=o.add(x,projected);
|
| 162 |
const ffnIn=o.rmsNorm(postAttn,ly.fn,C.rmsNormEps);const gate=o.matVec(ly.gw,ffnIn,C.intermediateSize,C.hiddenDim);
|
| 163 |
const up=o.matVec(ly.uw,ffnIn,C.intermediateSize,C.hiddenDim);const activated=o.fusedSiluMul(gate,up);
|
| 164 |
const down=o.matVec(ly.dw,activated,C.hiddenDim,C.intermediateSize);x=o.add(postAttn,down);
|
| 165 |
+
|
| 166 |
+
// Layer norms + residual contribution
|
| 167 |
+
if (diag) {
|
| 168 |
+
let norm=0, delta=0, prevNorm=0;
|
| 169 |
+
for(let i=0;i<C.hiddenDim;i++) { norm+=x[i]*x[i]; delta+=(x[i]-xPrev[i])**2; prevNorm+=xPrev[i]*xPrev[i]; }
|
| 170 |
+
layerNorms.push({ norm: Math.round(Math.sqrt(norm)*100)/100, residual: prevNorm>0 ? Math.round(Math.sqrt(delta/prevNorm)*1000)/1000 : 0 });
|
| 171 |
+
}
|
| 172 |
}
|
| 173 |
const finalNormed=o.rmsNorm(x,model.outNorm,C.rmsNormEps);
|
| 174 |
+
const logits = o.matVec(model.outWeight,finalNormed,C.vocabSize,C.hiddenDim);
|
| 175 |
+
return { logits, layerNorms, attnEntropies };
|
| 176 |
}
|
| 177 |
};
|
| 178 |
}
|
|
|
|
| 247 |
|
| 248 |
// βββ Generation Loops βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 249 |
|
| 250 |
+
function generateStandard(prompt, maxTokens = 8192) {
|
| 251 |
const t0 = performance.now();
|
| 252 |
const fwd = forwardPass(prompt);
|
| 253 |
const allTokens = [...fwd.inputTokens];
|
|
|
|
| 256 |
|
| 257 |
// Prefill
|
| 258 |
for (let i = 0; i < fwd.inputTokens.length; i++) {
|
| 259 |
+
fwd.step(allTokens.slice(0, i+1), kvC, false);
|
| 260 |
}
|
| 261 |
|
| 262 |
+
const perTokenInfo = [];
|
| 263 |
+
|
| 264 |
// Decode
|
| 265 |
for (let i = 0; i < maxTokens; i++) {
|
| 266 |
const ts = performance.now();
|
| 267 |
+
const { logits, layerNorms, attnEntropies } = fwd.step(allTokens, kvC, true);
|
| 268 |
+
const o2 = op();
|
| 269 |
+
const scaled = new Float32Array(logits.length);
|
| 270 |
+
for (let j = 0; j < logits.length; j++) scaled[j] = logits[j] / 0.7;
|
| 271 |
+
const probs = o2.softmax(scaled);
|
| 272 |
+
|
| 273 |
const chosen = sampleStandard(logits);
|
| 274 |
+
const chosenProb = probs[chosen];
|
| 275 |
+
const perplexity = chosenProb > 0 ? -Math.log2(chosenProb) : 99;
|
| 276 |
+
|
| 277 |
+
// Vocab coverage: tokens with >0.1% probability
|
| 278 |
+
let vocabCoverage = 0;
|
| 279 |
+
for (let j = 0; j < probs.length; j++) if (probs[j] > 0.001) vocabCoverage++;
|
| 280 |
+
|
| 281 |
+
// Top-5
|
| 282 |
+
const top5 = Array.from(probs).map((p,j)=>({p,i:j})).sort((a,b)=>b.p-a.p).slice(0,5)
|
| 283 |
+
.map(t => ({ token: model.tokenizer.decode([t.i]), prob: Math.round(t.p*1000)/1000 }));
|
| 284 |
+
|
| 285 |
tokenTimes.push(performance.now() - ts);
|
| 286 |
+
perTokenInfo.push({ perplexity: Math.round(perplexity*100)/100, chosenProb: Math.round(chosenProb*1000)/1000, vocabCoverage, top5, layerNorms, attnEntropies });
|
| 287 |
+
|
| 288 |
if (chosen === C.eosToken) break;
|
| 289 |
allTokens.push(chosen);
|
| 290 |
}
|
|
|
|
| 297 |
text: model.tokenizer.decode(genTokens), tokens: genTokens.length,
|
| 298 |
totalTimeMs: Math.round(totalTime), avgTokenMs: Math.round(avgMs),
|
| 299 |
mode: 'standard', temperature: 0.7, topP: 0.9,
|
| 300 |
+
tokenDiagnostics: perTokenInfo,
|
| 301 |
};
|
| 302 |
}
|
| 303 |
|
| 304 |
+
function generateGlossolalia(prompt, maxTokens = 8192) {
|
| 305 |
const t0 = performance.now();
|
| 306 |
const fwd = forwardPass(prompt);
|
| 307 |
const allTokens = [...fwd.inputTokens];
|
|
|
|
| 311 |
|
| 312 |
// Prefill
|
| 313 |
for (let i = 0; i < fwd.inputTokens.length; i++) {
|
| 314 |
+
fwd.step(allTokens.slice(0, i+1), kvC, false);
|
| 315 |
}
|
| 316 |
|
| 317 |
// Decode with Glossolalia
|
| 318 |
for (let i = 0; i < maxTokens; i++) {
|
| 319 |
const ts = performance.now();
|
| 320 |
+
const { logits, layerNorms, attnEntropies } = fwd.step(allTokens, kvC, true);
|
| 321 |
const { tokenId, agents } = sampleGlossolalia(logits);
|
| 322 |
+
|
| 323 |
+
// Token-level perplexity from merged distribution
|
| 324 |
+
const { merged } = glossolaliaMerge(logits);
|
| 325 |
+
const chosenProb = merged[tokenId] || 0;
|
| 326 |
+
const perplexity = chosenProb > 0 ? -Math.log2(chosenProb) : 99;
|
| 327 |
+
let vocabCoverage = 0;
|
| 328 |
+
for (let j = 0; j < merged.length; j++) if (merged[j] > 0.001) vocabCoverage++;
|
| 329 |
+
|
| 330 |
tokenTimes.push(performance.now() - ts);
|
| 331 |
|
| 332 |
+
perTokenDiag.push({
|
| 333 |
+
agents: agents.map(a => ({
|
| 334 |
+
tau: a.tau, entropy: Math.round(a.entropy*1000)/1000, weight: Math.round(a.weight*1000)/1000,
|
| 335 |
+
top3: a.top5.slice(0,3).map(t => ({ token: model.tokenizer.decode([t.i]), prob: Math.round(t.p*1000)/1000 })),
|
|
|
|
|
|
|
|
|
|
| 336 |
})),
|
| 337 |
+
perplexity: Math.round(perplexity*100)/100,
|
| 338 |
+
chosenProb: Math.round(chosenProb*1000)/1000,
|
| 339 |
+
vocabCoverage,
|
| 340 |
+
layerNorms,
|
| 341 |
+
attnEntropies,
|
| 342 |
+
});
|
| 343 |
|
| 344 |
if (tokenId === C.eosToken) break;
|
| 345 |
allTokens.push(tokenId);
|
|
|
|
| 365 |
req.on('end', () => {
|
| 366 |
try {
|
| 367 |
const { prompt, max_tokens } = JSON.parse(body);
|
| 368 |
+
const result = genFn(prompt, max_tokens || 256);
|
| 369 |
res.writeHead(200, { 'Content-Type': 'application/json' });
|
| 370 |
res.end(JSON.stringify(result));
|
| 371 |
} catch (e) {
|
app.py
CHANGED
|
@@ -2,9 +2,9 @@
|
|
| 2 |
Glossolalia -- Semiotic Ensemble Inference
|
| 3 |
Act 2: Fork/Race/Fold at the decoder level.
|
| 4 |
|
| 5 |
-
Standard sampling vs Glossolalia
|
| 6 |
-
|
| 7 |
-
|
| 8 |
"""
|
| 9 |
|
| 10 |
import gradio as gr
|
|
@@ -44,14 +44,14 @@ else:
|
|
| 44 |
print("[Glossolalia] WARNING: Aether not ready after 180s", flush=True)
|
| 45 |
|
| 46 |
|
| 47 |
-
def call_aether(endpoint, prompt, max_tokens=
|
| 48 |
try:
|
| 49 |
data = json.dumps({"prompt": prompt, "max_tokens": max_tokens}).encode()
|
| 50 |
req = urllib.request.Request(
|
| 51 |
f"http://127.0.0.1:7861/{endpoint}", data=data,
|
| 52 |
headers={"Content-Type": "application/json"},
|
| 53 |
)
|
| 54 |
-
resp = urllib.request.urlopen(req, timeout=
|
| 55 |
return json.loads(resp.read())
|
| 56 |
except urllib.error.HTTPError as e:
|
| 57 |
body = e.read().decode() if e.fp else str(e)
|
|
@@ -62,24 +62,73 @@ def call_aether(endpoint, prompt, max_tokens=48):
|
|
| 62 |
return {"error": str(e), "text": f"[Error: {e}]", "tokens": 0, "totalTimeMs": 0, "avgTokenMs": 0}
|
| 63 |
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
| 66 |
if not diag_list:
|
| 67 |
-
return "No diagnostics
|
| 68 |
-
lines = ["
|
| 69 |
-
"
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
top_str = ", ".join(f"'{t['token']}' ({t['prob']:.3f})" for t in a.get("top3", []))
|
| 75 |
-
lines.append(f" tau={a
|
| 76 |
lines.append("")
|
| 77 |
return "\n".join(lines)
|
| 78 |
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
def compare(prompt, max_tokens):
|
|
|
|
| 81 |
if not prompt or not prompt.strip():
|
| 82 |
-
yield
|
| 83 |
return
|
| 84 |
|
| 85 |
max_tokens = int(max_tokens)
|
|
@@ -91,33 +140,34 @@ def compare(prompt, max_tokens):
|
|
| 91 |
def run_glo():
|
| 92 |
glo_result[0] = call_aether("generate-glossolalia", prompt, max_tokens)
|
| 93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
with ThreadPoolExecutor(max_workers=2) as pool:
|
| 95 |
futures = {pool.submit(run_std): "std", pool.submit(run_glo): "glo"}
|
| 96 |
for future in as_completed(futures):
|
| 97 |
-
name = futures[future]
|
| 98 |
future.result()
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
gt = glo_result[0]["text"] if glo_result[0] else "generating..."
|
| 103 |
-
gs = f"{glo_result[0]['tokens']} tokens in {glo_result[0]['totalTimeMs']/1000:.1f}s ({glo_result[0]['avgTokenMs']}ms/tok)" if glo_result[0] else "running..."
|
| 104 |
-
diag = format_diagnostics(glo_result[0].get("diagnostics", [])) if glo_result[0] else ""
|
| 105 |
-
yield r["text"], gt, st, gs, diag
|
| 106 |
-
elif name == "glo" and glo_result[0]:
|
| 107 |
-
r = glo_result[0]
|
| 108 |
-
gs = f"{r['tokens']} tokens in {r['totalTimeMs']/1000:.1f}s ({r['avgTokenMs']}ms/tok)"
|
| 109 |
-
bt = std_result[0]["text"] if std_result[0] else "generating..."
|
| 110 |
-
bs = f"{std_result[0]['tokens']} tokens in {std_result[0]['totalTimeMs']/1000:.1f}s ({std_result[0]['avgTokenMs']}ms/tok)" if std_result[0] else "running..."
|
| 111 |
-
yield bt, r["text"], bs, gs, format_diagnostics(r.get("diagnostics", []))
|
| 112 |
-
|
| 113 |
-
if std_result[0] and glo_result[0]:
|
| 114 |
-
sr, gr_ = std_result[0], glo_result[0]
|
| 115 |
-
yield (sr["text"], gr_["text"],
|
| 116 |
-
f"{sr['tokens']} tokens in {sr['totalTimeMs']/1000:.1f}s ({sr['avgTokenMs']}ms/tok)",
|
| 117 |
-
f"{gr_['tokens']} tokens in {gr_['totalTimeMs']/1000:.1f}s ({gr_['avgTokenMs']}ms/tok)",
|
| 118 |
-
format_diagnostics(gr_.get("diagnostics", [])))
|
| 119 |
|
| 120 |
|
|
|
|
|
|
|
| 121 |
CSS = """
|
| 122 |
.gradio-container { max-width: 1060px !important; margin: 0 auto !important; }
|
| 123 |
.gradio-container, .dark { background: #09090b !important; }
|
|
@@ -144,20 +194,22 @@ footer.svelte-1ax1toq { display: none !important; }
|
|
| 144 |
.built-with { display: none !important; }
|
| 145 |
"""
|
| 146 |
|
|
|
|
|
|
|
| 147 |
with gr.Blocks(css=CSS, theme=gr.themes.Base(primary_hue="purple", neutral_hue="zinc"), title="Glossolalia") as demo:
|
| 148 |
|
| 149 |
gr.HTML("""
|
| 150 |
<div id="hero">
|
| 151 |
<h1><span class="accent">Glossolalia</span></h1>
|
| 152 |
-
<p class="subtitle">Semiotic ensemble inference. Same
|
| 153 |
-
Left: standard top-p
|
| 154 |
-
All inference via Aether
|
| 155 |
</div>
|
| 156 |
""")
|
| 157 |
|
| 158 |
with gr.Row():
|
| 159 |
prompt = gr.Textbox(elem_id="prompt-input", placeholder="What is the shape of failure?", lines=2, label="Prompt", show_label=False, interactive=True, scale=4)
|
| 160 |
-
max_tok = gr.Slider(minimum=8, maximum=
|
| 161 |
|
| 162 |
btn = gr.Button("Generate", elem_id="gen-btn", variant="primary")
|
| 163 |
|
|
@@ -173,28 +225,36 @@ with gr.Blocks(css=CSS, theme=gr.themes.Base(primary_hue="purple", neutral_hue="
|
|
| 173 |
glo_out = gr.Textbox(lines=10, show_label=False, interactive=False, elem_classes=["response-card"])
|
| 174 |
glo_stats = gr.HTML('<p class="stats-text">--</p>')
|
| 175 |
|
| 176 |
-
with gr.Accordion("Agent Diagnostics
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
def run(prompt_text, max_tokens):
|
| 180 |
-
for
|
| 181 |
-
|
|
|
|
| 182 |
|
| 183 |
-
btn.click(run, [prompt, max_tok],
|
| 184 |
-
prompt.submit(run, [prompt, max_tok],
|
| 185 |
|
| 186 |
gr.HTML('<p style="color:#52525b; font-size:0.8rem; margin-top:1.5rem; margin-bottom:0.5rem;">Try these:</p>')
|
| 187 |
with gr.Row():
|
| 188 |
for p in ["What is the shape of failure?", "The theory of everything begins with", "If silence had a color", "Write a haiku about parallel universes"]:
|
| 189 |
gr.Button(p, size="sm", elem_classes=["prompt-chip"]).click(
|
| 190 |
fn=lambda x=p: x, outputs=[prompt]
|
| 191 |
-
).then(fn=run, inputs=[prompt, max_tok], outputs=
|
| 192 |
|
| 193 |
gr.HTML("""
|
| 194 |
<div id="footer">
|
| 195 |
<p style="color:#a1a1aa; font-size:0.85rem; margin-bottom:0.5rem;">
|
| 196 |
-
SmolLM2-360M-Instruct · Q8_0 GGUF · Aether WASM-SIMD ·
|
| 197 |
-
THM-SEMIOTIC-ERASURE (Lean 4)
|
| 198 |
</p>
|
| 199 |
<p>
|
| 200 |
<a href="https://forkracefold.com/">Whitepaper</a> ·
|
|
|
|
| 2 |
Glossolalia -- Semiotic Ensemble Inference
|
| 3 |
Act 2: Fork/Race/Fold at the decoder level.
|
| 4 |
|
| 5 |
+
Standard sampling vs Glossolalia. Same forward pass, different decoder.
|
| 6 |
+
All inference via Aether WASM-SIMD engine. Deep diagnostics: per-token
|
| 7 |
+
perplexity, per-layer norms, attention entropy, vocabulary coverage.
|
| 8 |
"""
|
| 9 |
|
| 10 |
import gradio as gr
|
|
|
|
| 44 |
print("[Glossolalia] WARNING: Aether not ready after 180s", flush=True)
|
| 45 |
|
| 46 |
|
| 47 |
+
def call_aether(endpoint, prompt, max_tokens=256):
|
| 48 |
try:
|
| 49 |
data = json.dumps({"prompt": prompt, "max_tokens": max_tokens}).encode()
|
| 50 |
req = urllib.request.Request(
|
| 51 |
f"http://127.0.0.1:7861/{endpoint}", data=data,
|
| 52 |
headers={"Content-Type": "application/json"},
|
| 53 |
)
|
| 54 |
+
resp = urllib.request.urlopen(req, timeout=600)
|
| 55 |
return json.loads(resp.read())
|
| 56 |
except urllib.error.HTTPError as e:
|
| 57 |
body = e.read().decode() if e.fp else str(e)
|
|
|
|
| 62 |
return {"error": str(e), "text": f"[Error: {e}]", "tokens": 0, "totalTimeMs": 0, "avgTokenMs": 0}
|
| 63 |
|
| 64 |
|
| 65 |
+
# βββ Diagnostic Formatters βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 66 |
+
|
| 67 |
+
def format_glossolalia_diag(diag_list):
|
| 68 |
if not diag_list:
|
| 69 |
+
return "No diagnostics."
|
| 70 |
+
lines = ["GLOSSOLALIA DEEP DIAGNOSTICS", "=" * 60, "",
|
| 71 |
+
"tau={0.4, 0.7, 1.0} | w = 1-H/log(V) | ppl = -log2(P)", ""]
|
| 72 |
+
for step, d in enumerate(diag_list):
|
| 73 |
+
if not isinstance(d, dict):
|
| 74 |
+
continue
|
| 75 |
+
ppl = d.get("perplexity", "?")
|
| 76 |
+
prob = d.get("chosenProb", "?")
|
| 77 |
+
vc = d.get("vocabCoverage", "?")
|
| 78 |
+
lines.append(f"--- Token {step+1} | ppl={ppl} | P={prob} | vocabCov={vc} ---")
|
| 79 |
+
for a in d.get("agents", []):
|
| 80 |
+
if not isinstance(a, dict):
|
| 81 |
+
continue
|
| 82 |
top_str = ", ".join(f"'{t['token']}' ({t['prob']:.3f})" for t in a.get("top3", []))
|
| 83 |
+
lines.append(f" tau={a.get('tau','?'):.1f} | H={a.get('entropy',0):.3f} | w={a.get('weight',0):.3f} | {top_str}")
|
| 84 |
lines.append("")
|
| 85 |
return "\n".join(lines)
|
| 86 |
|
| 87 |
|
| 88 |
+
def format_standard_diag(token_diag):
|
| 89 |
+
if not token_diag:
|
| 90 |
+
return "No diagnostics."
|
| 91 |
+
lines = ["STANDARD SAMPLING DIAGNOSTICS", "=" * 60,
|
| 92 |
+
"ppl = -log2(P(chosen)) | vocabCov = tokens with P>0.1%", ""]
|
| 93 |
+
for step, d in enumerate(token_diag):
|
| 94 |
+
if not isinstance(d, dict):
|
| 95 |
+
continue
|
| 96 |
+
ppl = d.get("perplexity", "?")
|
| 97 |
+
prob = d.get("chosenProb", "?")
|
| 98 |
+
vc = d.get("vocabCoverage", "?")
|
| 99 |
+
top5 = d.get("top5", [])
|
| 100 |
+
top_str = ", ".join(f"'{t['token']}' ({t['prob']:.3f})" for t in top5[:3])
|
| 101 |
+
lines.append(f"Token {step+1} | ppl={ppl} | P={prob} | vc={vc} | {top_str}")
|
| 102 |
+
return "\n".join(lines)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def format_layer_health(diag_list):
|
| 106 |
+
if not diag_list:
|
| 107 |
+
return "No layer data."
|
| 108 |
+
last = diag_list[-1] if diag_list else {}
|
| 109 |
+
if not isinstance(last, dict):
|
| 110 |
+
return "No layer data."
|
| 111 |
+
norms = last.get("layerNorms", [])
|
| 112 |
+
if not norms:
|
| 113 |
+
return "No layer norms."
|
| 114 |
+
lines = ["LAYER HEALTH (last generated token)", "=" * 60,
|
| 115 |
+
"Layer | Hidden Norm | Residual Contribution", "-" * 50]
|
| 116 |
+
for i, n in enumerate(norms):
|
| 117 |
+
if not isinstance(n, dict):
|
| 118 |
+
continue
|
| 119 |
+
norm_val = n.get("norm", 0)
|
| 120 |
+
res_val = n.get("residual", 0)
|
| 121 |
+
bar = "#" * min(int(res_val * 40), 40)
|
| 122 |
+
lines.append(f" {i:2d} | {norm_val:9.2f} | {res_val:.4f} {bar}")
|
| 123 |
+
return "\n".join(lines)
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
# βββ Compare Function ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 127 |
+
|
| 128 |
def compare(prompt, max_tokens):
|
| 129 |
+
empty = ("", "", "", "", "", "", "")
|
| 130 |
if not prompt or not prompt.strip():
|
| 131 |
+
yield empty
|
| 132 |
return
|
| 133 |
|
| 134 |
max_tokens = int(max_tokens)
|
|
|
|
| 140 |
def run_glo():
|
| 141 |
glo_result[0] = call_aether("generate-glossolalia", prompt, max_tokens)
|
| 142 |
|
| 143 |
+
def fmt_stats(r):
|
| 144 |
+
if not r:
|
| 145 |
+
return "running..."
|
| 146 |
+
return f"{r['tokens']} tokens in {r['totalTimeMs']/1000:.1f}s ({r['avgTokenMs']}ms/tok)"
|
| 147 |
+
|
| 148 |
+
def build():
|
| 149 |
+
sr, gr_ = std_result[0], glo_result[0]
|
| 150 |
+
return (
|
| 151 |
+
sr["text"] if sr else "generating...",
|
| 152 |
+
gr_["text"] if gr_ else "generating...",
|
| 153 |
+
fmt_stats(sr),
|
| 154 |
+
fmt_stats(gr_),
|
| 155 |
+
format_glossolalia_diag(gr_.get("diagnostics", [])) if gr_ else "",
|
| 156 |
+
format_standard_diag(sr.get("tokenDiagnostics", [])) if sr else "",
|
| 157 |
+
format_layer_health(gr_.get("diagnostics", [])) if gr_ else "",
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
with ThreadPoolExecutor(max_workers=2) as pool:
|
| 161 |
futures = {pool.submit(run_std): "std", pool.submit(run_glo): "glo"}
|
| 162 |
for future in as_completed(futures):
|
|
|
|
| 163 |
future.result()
|
| 164 |
+
yield build()
|
| 165 |
+
|
| 166 |
+
yield build()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
|
| 169 |
+
# βββ CSS βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 170 |
+
|
| 171 |
CSS = """
|
| 172 |
.gradio-container { max-width: 1060px !important; margin: 0 auto !important; }
|
| 173 |
.gradio-container, .dark { background: #09090b !important; }
|
|
|
|
| 194 |
.built-with { display: none !important; }
|
| 195 |
"""
|
| 196 |
|
| 197 |
+
# βββ Gradio UI βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 198 |
+
|
| 199 |
with gr.Blocks(css=CSS, theme=gr.themes.Base(primary_hue="purple", neutral_hue="zinc"), title="Glossolalia") as demo:
|
| 200 |
|
| 201 |
gr.HTML("""
|
| 202 |
<div id="hero">
|
| 203 |
<h1><span class="accent">Glossolalia</span></h1>
|
| 204 |
+
<p class="subtitle">Semiotic ensemble inference. Same forward pass, different decoder.<br/>
|
| 205 |
+
Left: standard top-p. Right: fork/race/fold with deficit-weighted complement merge.<br/>
|
| 206 |
+
All inference via Aether. Zero ML dependencies. Full diagnostic visibility.</p>
|
| 207 |
</div>
|
| 208 |
""")
|
| 209 |
|
| 210 |
with gr.Row():
|
| 211 |
prompt = gr.Textbox(elem_id="prompt-input", placeholder="What is the shape of failure?", lines=2, label="Prompt", show_label=False, interactive=True, scale=4)
|
| 212 |
+
max_tok = gr.Slider(minimum=8, maximum=512, value=64, step=1, label="Max tokens", scale=1)
|
| 213 |
|
| 214 |
btn = gr.Button("Generate", elem_id="gen-btn", variant="primary")
|
| 215 |
|
|
|
|
| 225 |
glo_out = gr.Textbox(lines=10, show_label=False, interactive=False, elem_classes=["response-card"])
|
| 226 |
glo_stats = gr.HTML('<p class="stats-text">--</p>')
|
| 227 |
|
| 228 |
+
with gr.Accordion("Glossolalia Agent Diagnostics", open=False):
|
| 229 |
+
glo_diag = gr.Textbox(lines=18, show_label=False, interactive=False)
|
| 230 |
+
|
| 231 |
+
with gr.Accordion("Standard Sampling Diagnostics", open=False):
|
| 232 |
+
std_diag = gr.Textbox(lines=12, show_label=False, interactive=False)
|
| 233 |
+
|
| 234 |
+
with gr.Accordion("Layer Health (32 transformer layers)", open=False):
|
| 235 |
+
layer_health = gr.Textbox(lines=18, show_label=False, interactive=False)
|
| 236 |
+
|
| 237 |
+
outputs = [std_out, glo_out, std_stats, glo_stats, glo_diag, std_diag, layer_health]
|
| 238 |
|
| 239 |
def run(prompt_text, max_tokens):
|
| 240 |
+
for vals in compare(prompt_text, max_tokens):
|
| 241 |
+
st, gt, ss, gs, gd, sd, lh = vals
|
| 242 |
+
yield st, gt, f'<p class="stats-text">{ss}</p>', f'<p class="stats-text">{gs}</p>', gd, sd, lh
|
| 243 |
|
| 244 |
+
btn.click(run, [prompt, max_tok], outputs)
|
| 245 |
+
prompt.submit(run, [prompt, max_tok], outputs)
|
| 246 |
|
| 247 |
gr.HTML('<p style="color:#52525b; font-size:0.8rem; margin-top:1.5rem; margin-bottom:0.5rem;">Try these:</p>')
|
| 248 |
with gr.Row():
|
| 249 |
for p in ["What is the shape of failure?", "The theory of everything begins with", "If silence had a color", "Write a haiku about parallel universes"]:
|
| 250 |
gr.Button(p, size="sm", elem_classes=["prompt-chip"]).click(
|
| 251 |
fn=lambda x=p: x, outputs=[prompt]
|
| 252 |
+
).then(fn=run, inputs=[prompt, max_tok], outputs=outputs)
|
| 253 |
|
| 254 |
gr.HTML("""
|
| 255 |
<div id="footer">
|
| 256 |
<p style="color:#a1a1aa; font-size:0.85rem; margin-bottom:0.5rem;">
|
| 257 |
+
SmolLM2-360M-Instruct · Q8_0 GGUF · Aether WASM-SIMD · THM-SEMIOTIC-ERASURE (Lean 4)
|
|
|
|
| 258 |
</p>
|
| 259 |
<p>
|
| 260 |
<a href="https://forkracefold.com/">Whitepaper</a> ·
|