code wiki / _hdl_build / nx_nofloat_incontext_gate.nx
nx_nofloat_incontext_gate.nx source
↩ module page · 144 lines · 8072 B
1// nx_nofloat_incontext_gate.nx -- IN-CONTEXT COPYING (CAP-NF-INCONTEXT): the basis of in-context learning.
2// Task = ECHO: at each position predict the PREVIOUS token (tgt[i]=S[i-1]). EVERY training sequence is FRESH
3// RANDOM (LCG), so the model CANNOT memorize sequences -- it must learn the copy OPERATION (a "previous-token
4// attention head": attend to relative position -1 and copy its token). Then it echoes NEVER-SEEN random
5// sequences -> generalization to unseen DATA, the foundation of in-context learning.
6// T1 held-out echo accuracy >> chance (1/V) on fresh random sequences = the model copies arbitrary unseen content.
7// T2 same on a DIFFERENT test seed = the generalization is robust (not seed-luck).
8// Pure integer Q16, attention-only block (2 clm_fwd call sites). HONEST: copy-back-1 (a previous-token head),
9// the simplest in-context copy -- not full content-based induction. Sovereign: nx_nofloat_autograd + nx_syscalls.
10// expect_exit: 0
11import "nx_nofloat_autograd.nx"
12import "nx_syscalls.nx"
13import "nx_gate_emit_lib.nx"
14import "nx_gate_verdict.nx"
15const Q16: i64 = 65536
16
17
18func dini(a: *i64, n: i64, sd: i64) -> i64 { var i: i64=0; while i<n { a[i]=(((i*7+sd*13+1)%11)-5)*13107; i=i+1 } return 0 }
19func lcg(st: *i64) -> i64 { st[0]=(st[0]*1103515245 + 12345) & 2147483647; return (st[0] >> 15) }
20// fill S[0..P-1] random in [0,V) and tgt[i]=S[i-1] (echo target; tgt[0]=S[0])
21func make_ex(S: *i64, tgt: *i64, P: i64, V: i64, st: *i64) -> i64 {
22 var i: i64=0; while i<P { S[i]=lcg(st)%V; i=i+1 }
23 tgt[0]=S[0]; i=1; while i<P { tgt[i]=S[i-1]; i=i+1 }
24 return 0
25}
26
27func clm_fwd(tape: *i64, vals: *i64, st: *i64, W: *i64, ids: *i64, tgt: *i64, T: i64, dm: i64, V: i64, scale: i64, leaves: *i64) -> i64 {
28 let E: *i64=W[0] as *i64; let Wq: *i64=W[1] as *i64; let Wk: *i64=W[2] as *i64; let Wv: *i64=W[3] as *i64; let Wo: *i64=W[4] as *i64; let Wlm: *i64=W[5] as *i64
29 st[0]=0; st[1]=0
30 let nE: i64=nfa_leaf(tape,vals,st,V,dm,E,0)
31 let nWq: i64=nfa_leaf(tape,vals,st,dm,dm,Wq,0)
32 let nWk: i64=nfa_leaf(tape,vals,st,dm,dm,Wk,0)
33 let nWv: i64=nfa_leaf(tape,vals,st,dm,dm,Wv,0)
34 let nWo: i64=nfa_leaf(tape,vals,st,dm,dm,Wo,0)
35 let nWlm: i64=nfa_leaf(tape,vals,st,dm,V,Wlm,0)
36 let nX: i64=nfa_embed(tape,vals,st,nE,ids,T)
37 let nXn: i64=nfa_rmsnorm_rows(tape,vals,st,nX)
38 let nQ: i64=nfa_matmul(tape,vals,st,nXn,nWq)
39 let nK: i64=nfa_matmul(tape,vals,st,nXn,nWk)
40 let nV: i64=nfa_matmul(tape,vals,st,nXn,nWv)
41 let nQr: i64=nfa_rope(tape,vals,st,nQ)
42 let nKr: i64=nfa_rope(tape,vals,st,nK)
43 let nS: i64=nfa_matmul_nt(tape,vals,st,nQr,nKr)
44 let nSs: i64=nfa_cmul(tape,vals,st,nS,scale)
45 let nA: i64=nfa_softmax_rows(tape,vals,st,nSs,1)
46 let nO: i64=nfa_matmul(tape,vals,st,nA,nV)
47 let nOp: i64=nfa_matmul(tape,vals,st,nO,nWo)
48 let nH: i64=nfa_vadd(tape,vals,st,nX,nOp)
49 let nHn: i64=nfa_rmsnorm_rows(tape,vals,st,nH)
50 let nLg: i64=nfa_matmul(tape,vals,st,nHn,nWlm)
51 let nLoss: i64=nfa_softce_rows(tape,vals,st,nLg,tgt)
52 leaves[0]=nE; leaves[1]=nWq; leaves[2]=nWk; leaves[3]=nWv; leaves[4]=nWo; leaves[5]=nWlm; leaves[6]=nLg
53 return nLoss
54}
55func step_all(tape: *i64, grads: *i64, W: *i64, WN: *i64, leaves: *i64, nW: i64, lr: i64, clip: i64, gb: *i64) -> i64 {
56 var i: i64=0
57 while i<nW { let ar: *i64=W[i] as *i64; let cn: i64=WN[i]; let nd: i64=leaves[i]; var c: i64=0; while c<cn { var g: i64=nfa_grad(tape,grads,nd,c); if g>clip{g=clip} if g<0-clip{g=0-clip} gb[c]=g; c=c+1 } nfa_sgd(ar,gb,cn,lr); i=i+1 }
58 return 0
59}
60// call site 1: train on FRESH random echo examples (st_data advances each step -> never repeats)
61func do_train(tape: *i64, vals: *i64, grads: *i64, st: *i64, W: *i64, WN: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, V: i64, scale: i64, leaves: *i64, gb: *i64, steps: i64, sdat: *i64) -> i64 {
62 var ep: i64=0
63 while ep < steps {
64 make_ex(S, tgt, P, V, sdat)
65 let nl: i64=clm_fwd(tape,vals,st,W,S,tgt,P,dm,V,scale,leaves)
66 nfa_backward(tape,vals,grads,st[0],nl)
67 step_all(tape,grads,W,WN,leaves,6,6554,262144,gb)
68 ep=ep+1
69 }
70 return 0
71}
72// call site 2: echo accuracy over N fresh random examples (positions 1..P-1: predict S[i-1]); returns correct count
73func eval_echo(tape: *i64, vals: *i64, st: *i64, W: *i64, S: *i64, tgt: *i64, P: i64, dm: i64, V: i64, scale: i64, leaves: *i64, N: i64, sdat: *i64, totp: *i64) -> i64 {
74 var ok: i64=0; var tp: i64=0; var e: i64=0
75 while e<N {
76 make_ex(S, tgt, P, V, sdat)
77 let nl: i64=clm_fwd(tape,vals,st,W,S,tgt,P,dm,V,scale,leaves)
78 let off: i64=tape[7*leaves[6]+5]
79 var p: i64=1
80 while p<P {
81 var b: i64=0; var bv: i64=vals[off+p*V]; var j: i64=1
82 while j<V { if vals[off+p*V+j]>bv { bv=vals[off+p*V+j]; b=j } j=j+1 }
83 if b==S[p-1] { ok=ok+1 }
84 tp=tp+1
85 p=p+1
86 }
87 e=e+1
88 }
89 totp[0]=tp
90 return ok
91}
92
93func main() -> i64 {
94 g_puts("nx_nofloat_incontext gate (IN-CONTEXT copy/echo head, pure integer Q16)\n" as *u8)
95 var pass: i64=0; var total: i64=0
96 let V: i64=6; let P: i64=6; let dm: i64=24; let scale: i64=13377
97 let tape: *i64 = sys_mmap(512*7*8) as *i64
98 let vals: *i64 = sys_mmap(65536*8) as *i64
99 let grads: *i64 = sys_mmap(65536*8) as *i64
100 let st: *i64 = sys_mmap(2*8) as *i64
101 let nW: i64=6
102 let W: *i64 = sys_mmap(nW*8) as *i64
103 let WN: *i64 = sys_mmap(nW*8) as *i64
104 WN[0]=V*dm; WN[1]=dm*dm; WN[2]=dm*dm; WN[3]=dm*dm; WN[4]=dm*dm; WN[5]=dm*V
105 var wi: i64=0
106 while wi<nW { let a: *i64=sys_mmap(WN[wi]*8) as *i64; dini(a,WN[wi],wi+1); W[wi]=a as i64; wi=wi+1 }
107 let leaves: *i64 = sys_mmap(8*8) as *i64
108 let gbuf: *i64 = sys_mmap(4096*8) as *i64
109 let S: *i64 = sys_mmap(P*8) as *i64; let tgt: *i64 = sys_mmap(P*8) as *i64
110 let totp: *i64 = sys_mmap(8) as *i64
111 let sdat: *i64 = sys_mmap(8) as *i64
112
113 sdat[0]=12345
114 do_train(tape,vals,grads,st,W,WN,S,tgt,P,dm,V,scale,leaves,gbuf,30000,sdat)
115
116 // held-out test seed A (fresh sequences the model never trained on)
117 sdat[0]=987654321
118 let okA: i64 = eval_echo(tape,vals,st,W,S,tgt,P,dm,V,scale,leaves,200,sdat,totp)
119 let tpA: i64 = totp[0]
120 // held-out test seed B (different)
121 sdat[0]=192837465
122 let okB: i64 = eval_echo(tape,vals,st,W,S,tgt,P,dm,V,scale,leaves,200,sdat,totp)
123 let tpB: i64 = totp[0]
124 g_puts(" [measure] held-out echo accuracy: seedA=" as *u8); g_pn(okA); g_puts("/" as *u8); g_pn(tpA); g_puts(" seedB=" as *u8); g_pn(okB); g_puts("/" as *u8); g_pn(tpB); g_puts(" (chance~1/" as *u8); g_pn(V); g_puts(")\n" as *u8)
125
126 var t1: i64=0; if okA*100 >= tpA*70 { t1=1 } // >= 70% on never-seen sequences (>> 17% chance)
127 pass=pass+g_check("T1: in-context copy -- echoes NEVER-SEEN random sequences >> chance (learned the operation)" as *u8, t1); total=total+1
128 var t2: i64=0; if okB*100 >= tpB*70 { t2=1 } // robust on a different test seed
129 pass=pass+g_check("T2: robust -- same high echo accuracy on a DIFFERENT held-out seed (not seed-luck)" as *u8, t2); total=total+1
130
131 var okall: i64=0; if pass==total { okall=1 }
132 let logf: i64 = sys_openat_append("knowledge/status/nofloat_incontext.log" as *u8, 420)
133 if logf >= 0 { let w0: i64=sys_write(logf,"NOFLOATINCONTEXT in-context echo head measured\n" as *u8,46); sys_close(logf) }
134 g_puts("---- incontext gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
135 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
136 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
137 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
138 let ctr__dry: *i64 = gv_ctr()
139 ctr__dry[0] = pass
140 ctr__dry[1] = total
141 let rc__dry: i64 = gv_verdict("NOFLOAT-INCONTEXT-GATE" as *u8, ctr__dry, "in-context copy head: echoes arbitrary unseen sequences -- the basis of in-context learning)" as *u8)
142 sys_exit(rc__dry)
143 return rc__dry
144}