nx_nofloat_arch.nx source
↩ module page · 74 lines · 4724 B
1// nx_nofloat_arch.nx -- ARCH-CONFIGURABLE inference: read a model's dims from GGUF METADATA instead of
2// hardcoding Qwen2.5-0.5B. The no-float forward (nx_nofloat_llm) is ALREADY cfg-parameterized -- only the
3// gate/serve main()s hardcode ne/n_layers/heads/ffn. This reader fills those from the metadata KVs that
4// llama.cpp's convert writes (`<arch>.embedding_length`, `.block_count`, `.attention.head_count`,
5// `.attention.head_count_kv`, `.feed_forward_length`), so ANY Qwen2/Llama-schema gguf runs -- the real
6// 0.5B AND a small from-scratch model (closing the sovereign train->serve loop). Pure funcs, no main.
7// license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_le.nx"
10import "nx_gguf.nx"
11import "nx_gguf_meta.nx"
12import "nx_nofloat_llm.nx" // isqrt for the attention scale
13
14// cfg layout the reader fills (i64): [0]=D(embedding) [1]=n_layers [2]=n_heads [3]=n_kv [4]=head_dim
15// [5]=q_dim(=D) [6]=kv_dim(=head_dim*n_kv) [7]=ffn [8]=scale_q16(=65536/sqrt(head_dim)) [9]=rope_base [10]=ok
16func nac_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
17// build "<prefix bytes><suffix cstr>" into out; return length.
18func nac_key(prefix: *u8, plen: i64, suffix: *u8, out: *u8) -> i64 {
19 var i: i64=0; while i<plen { out[i]=prefix[i]; i=i+1 }
20 var j: i64=0; while suffix[j]!=(0 as u8) { out[plen+j]=suffix[j]; j=j+1 }
21 return plen+j
22}
23func nac_u32(buf: *u8, len: i64, hdr: *NxGgufHeader, prefix: *u8, plen: i64, suffix: *u8) -> i64 {
24 let key: *u8=sys_mmap(160); let kl: i64=nac_key(prefix, plen, suffix, key)
25 let voff: *i64=sys_mmap(8) as *i64; let vty: *i64=sys_mmap(8) as *i64
26 if nx_gguf_meta_find(buf, len, hdr, key, kl, voff, vty)==NX_GMETA_OK { return nx_gguf_meta_read_u32(buf, voff[0]) }
27 return 0-1
28}
29// read an f32 metadata value, truncated to an integer (for rope base etc.); returns dflt if absent.
30func nac_f32_int(buf: *u8, len: i64, hdr: *NxGgufHeader, prefix: *u8, plen: i64, suffix: *u8, dflt: i64) -> i64 {
31 let key: *u8=sys_mmap(160); let kl: i64=nac_key(prefix, plen, suffix, key)
32 let voff: *i64=sys_mmap(8) as *i64; let vty: *i64=sys_mmap(8) as *i64
33 if nx_gguf_meta_find(buf, len, hdr, key, kl, voff, vty)==NX_GMETA_OK {
34 let q16: i64 = f32_to_q16(nx_le_read_u32(buf, voff[0])) // f32 bits -> Q16 (nx_nofloat_llm decoder)
35 return q16 >> 16
36 }
37 return dflt
38}
39// read the whole config from metadata. returns 0 ok, -1 missing keys. `arch_out` (>=32B) gets the arch string.
40func nac_read_config(buf: *u8, len: i64, hdr: *NxGgufHeader, cfg: *i64, arch_out: *u8) -> i64 {
41 cfg[10]=0
42 // general.architecture -> the key prefix (e.g. "qwen2")
43 let voff: *i64=sys_mmap(8) as *i64; let vty: *i64=sys_mmap(8) as *i64
44 let ka: *u8="general.architecture" as *u8
45 if nx_gguf_meta_find(buf, len, hdr, ka, 20, voff, vty)!=NX_GMETA_OK { return 0-1 }
46 let alen: i64=nx_gguf_meta_read_string_len(buf, voff[0]); let ap: *u8=nx_gguf_meta_read_string_ptr(buf, voff[0])
47 if alen<1 { return 0-1 }
48 if alen>30 { return 0-1 }
49 var i: i64=0; while i<alen { arch_out[i]=ap[i]; i=i+1 } arch_out[alen]=0 as u8
50 let D: i64=nac_u32(buf, len, hdr, ap, alen, ".embedding_length" as *u8)
51 let NL: i64=nac_u32(buf, len, hdr, ap, alen, ".block_count" as *u8)
52 let NH: i64=nac_u32(buf, len, hdr, ap, alen, ".attention.head_count" as *u8)
53 let NKV: i64=nac_u32(buf, len, hdr, ap, alen, ".attention.head_count_kv" as *u8)
54 let FF: i64=nac_u32(buf, len, hdr, ap, alen, ".feed_forward_length" as *u8)
55 if D<1 { return 0-1 }
56 if NL<1 { return 0-1 }
57 if NH<1 { return 0-1 }
58 if NKV<1 { return 0-1 }
59 if FF<1 { return 0-1 }
60 let hd: i64=D/NH
61 cfg[0]=D; cfg[1]=NL; cfg[2]=NH; cfg[3]=NKV; cfg[4]=hd; cfg[5]=D; cfg[6]=hd*NKV; cfg[7]=FF
62 // EXACT attention scale in Q16 = 1/sqrt(hd) (debt-eaten 2026-07-15): sqrt(hd) in Q16 = isqrt(hd<<32);
63 // scale = 2^32 / that. IDENTITY-PRESERVING at hd=64 (isqrt(64<<32)=524288, 2^32/524288 = 8192 = the old
64 // 65536/isqrt(64)); CORRECT at hd=128 (old 65536/11=5957 was ~2.8% high; new = 5792). Every future
65 // non-perfect-square head_dim now gets the true scale instead of the isqrt-floor approximation.
66 let sqhd: i64 = isqrt(hd << 32); if sqhd < 1 { return 0-1 }
67 cfg[8] = 4294967296 / sqhd
68 // rope base FROM THE MODEL (debt-eaten): <arch>.rope.freq_base (f32); default 1e6 (Qwen2) if absent.
69 // OLMoE/Llama carry 1e4/5e5 -- the hardcoded 1e6 would have garbled their attention.
70 cfg[9] = nac_f32_int(buf, len, hdr, ap, alen, ".rope.freq_base" as *u8, 1000000)
71 cfg[11] = fx_ln_int(cfg[9]) // ln(base) in Q16 -> rope_freqs_base (rope now base-correct for any model)
72 cfg[10]=1
73 return 0
74}