nx_gguf_fixture_tiny.nx source
↩ module page · 297 lines · 11526 B
1// nx_gguf_fixture_tiny.nx -- reusable tiny-Llama GGUF fixture builder.
2//
3// Encapsulates the ~150 lines of byte-by-byte synthetic GGUF
4// construction that test smokes for nx_llm_run_v2 and the v2 LLM
5// actor adapters currently duplicate. V1 builds the canonical
6// n_layers=1, hidden=2, head=2, vocab=4, ffn=4 shape with all-zero
7// F32 weights -- the same fixture nx_llm_run_v2_test.nx ships --
8// plus the BPE vocab (4 single-byte tokens 'a' 'b' 'c' 'd'), PRNG,
9// model spec, and a vocab-id-to-byte map for autoregressive smokes
10// to roll the previous token's bytes into the next prompt.
11//
12// One call -> entire test fixture ready to feed nx_llm_generate_one_v2
13// or any actor adapter that wraps it. Closes the combined-autoreg-
14// over-real-transformer smoke gap documented in
15// nx_actor_role_llm_v2_autoreg_test.nx.
16//
17// Honest scope: V1 is a SINGLE-shape fixture -- there are no knobs.
18// Future V2 will add a builder-pattern (caller-set hidden_dim /
19// vocab_size / n_layers). V1 keeps the API surface tiny.
20
21import "nx_syscalls.nx"
22import "nx_tier.nx"
23import "nx_le.nx"
24import "nx_gguf.nx"
25import "nx_gguf_load.nx"
26import "nx_bpe.nx"
27import "nx_model_spec.nx"
28import "nx_prng.nx"
29const NX_MAGIC_4096: i64 = 4096
30
31// ===== Sealed enum: NxGftVerdict ==================================
32
33const NX_GFT_OK: nx_int = 0
34const NX_GFT_ERR_PARSE: nx_int = 1
35const NX_GFT_ERR_SPEC_INVALID: nx_int = 2
36const NX_GFT_ERR_BPE_BUILD: nx_int = 3
37const NX_GFT_ERR_NULL: nx_int = 4
38const NX_GFT_N: nx_int = 5
39
40func nx_gft_v_is_valid(v: nx_int) -> nx_int {
41 if v < 0 { return 0 }
42 if v >= NX_GFT_N { return 0 }
43 return 1
44}
45
46// ===== Struct: NxGgufFixtureBundle ================================
47
48struct NxGgufFixtureBundle {
49 gguf_buf: *u8,
50 hdr: *NxGgufHeader,
51 spec: *NxModelSpec,
52 bpe: *NxBpeVocab,
53 prng_state: *i64,
54 vocab_byte_map: *u8,
55 vocab_size: nx_int,
56 hidden_dim: nx_int,
57 head_dim: nx_int,
58 n_layers: nx_int,
59 ffn_dim: nx_int,
60 n_heads: nx_int,
61 max_seq_len: nx_int,
62 verdict: nx_int,
63}
64
65const NX_GFT_BUNDLE_BYTES: nx_int = 112 // 14 fields * 8
66
67// ===== Internal fixture builders (mirror nx_llm_run_v2_test layout) =====
68
69func _gft_write_ti(buf: *u8, off: i64,
70 name: *u8, name_len: i64,
71 n_dims: i64, dim_0: i64, dim_1: i64,
72 ggml_type: i64, data_offset: i64) -> i64 {
73 nx_le_write_u64(buf, off, name_len)
74 var o: i64 = off + 8
75 var i: i64 = 0
76 while i < name_len { buf[o + i] = name[i]; i = i + 1 }
77 o = o + name_len
78 nx_le_write_u32(buf, o, n_dims); o = o + 4
79 nx_le_write_u64(buf, o, dim_0); o = o + 8
80 if n_dims >= 2 { nx_le_write_u64(buf, o, dim_1); o = o + 8 }
81 nx_le_write_u32(buf, o, ggml_type); o = o + 4
82 nx_le_write_u64(buf, o, data_offset); o = o + 8
83 return o
84}
85
86func _gft_mk_blk_name(suffix: *u8, suffix_len: nx_int, out: *u8) -> nx_int {
87 out[0]=0x62; out[1]=0x6c; out[2]=0x6b; out[3]=0x2e
88 out[4]=0x30; out[5]=0x2e
89 var i: nx_int = 0
90 while i < suffix_len { out[6 + i] = suffix[i]; i = i + 1 }
91 return 6 + suffix_len
92}
93
94// ===== Public: nx_gft_build_tiny_llama =============================
95//
96// Allocates an NxGgufFixtureBundle and fills in every field. Returns
97// the bundle pointer on success; bundle.verdict carries the NX_GFT_*
98// result. Caller owns the bundle and the substructures (the
99// fixture's lifetime is the bundle's lifetime; sys_munmap is queued
100// per conductor Phase E).
101
102func nx_gft_build_tiny_llama(prng_seed: i64) -> *NxGgufFixtureBundle {
103 let raw: *u8 = sys_mmap(NX_GFT_BUNDLE_BYTES)
104 let b: *NxGgufFixtureBundle = raw as *NxGgufFixtureBundle
105 b.vocab_size = 4
106 b.hidden_dim = 2
107 b.head_dim = 2
108 b.n_layers = 1
109 b.ffn_dim = 4
110 b.n_heads = 1
111 b.max_seq_len = 8
112 b.verdict = NX_GFT_OK
113
114 // ===== Build 12-tensor GGUF byte buffer =====
115 let buf: *u8 = sys_mmap(NX_MAGIC_4096)
116 buf[0]=0x47; buf[1]=0x47; buf[2]=0x55; buf[3]=0x46
117 buf[4]=3
118 nx_le_write_u64(buf, 8, 12)
119 nx_le_write_u64(buf, 16, 0)
120 b.gguf_buf = buf
121
122 // Top-level tensor names
123 let n_te: *u8 = sys_mmap(17)
124 n_te[0]=0x74; n_te[1]=0x6f; n_te[2]=0x6b; n_te[3]=0x65
125 n_te[4]=0x6e; n_te[5]=0x5f; n_te[6]=0x65; n_te[7]=0x6d
126 n_te[8]=0x62; n_te[9]=0x64; n_te[10]=0x2e; n_te[11]=0x77
127 n_te[12]=0x65; n_te[13]=0x69; n_te[14]=0x67; n_te[15]=0x68
128 n_te[16]=0x74
129
130 let n_on: *u8 = sys_mmap(18)
131 n_on[0]=0x6f; n_on[1]=0x75; n_on[2]=0x74; n_on[3]=0x70
132 n_on[4]=0x75; n_on[5]=0x74; n_on[6]=0x5f; n_on[7]=0x6e
133 n_on[8]=0x6f; n_on[9]=0x72; n_on[10]=0x6d; n_on[11]=0x2e
134 n_on[12]=0x77; n_on[13]=0x65; n_on[14]=0x69; n_on[15]=0x67
135 n_on[16]=0x68; n_on[17]=0x74
136
137 let n_ow: *u8 = sys_mmap(13)
138 n_ow[0]=0x6f; n_ow[1]=0x75; n_ow[2]=0x74; n_ow[3]=0x70
139 n_ow[4]=0x75; n_ow[5]=0x74; n_ow[6]=0x2e; n_ow[7]=0x77
140 n_ow[8]=0x65; n_ow[9]=0x69; n_ow[10]=0x67; n_ow[11]=0x68
141 n_ow[12]=0x74
142
143 // Per-layer tensor suffixes
144 let s_an: *u8 = sys_mmap(16)
145 s_an[0]=0x61; s_an[1]=0x74; s_an[2]=0x74; s_an[3]=0x6e
146 s_an[4]=0x5f; s_an[5]=0x6e; s_an[6]=0x6f; s_an[7]=0x72
147 s_an[8]=0x6d; s_an[9]=0x2e; s_an[10]=0x77; s_an[11]=0x65
148 s_an[12]=0x69; s_an[13]=0x67; s_an[14]=0x68; s_an[15]=0x74
149
150 let s_q: *u8 = sys_mmap(13)
151 s_q[0]=0x61; s_q[1]=0x74; s_q[2]=0x74; s_q[3]=0x6e
152 s_q[4]=0x5f; s_q[5]=0x71; s_q[6]=0x2e; s_q[7]=0x77
153 s_q[8]=0x65; s_q[9]=0x69; s_q[10]=0x67; s_q[11]=0x68; s_q[12]=0x74
154
155 let s_k: *u8 = sys_mmap(13)
156 s_k[0]=0x61; s_k[1]=0x74; s_k[2]=0x74; s_k[3]=0x6e
157 s_k[4]=0x5f; s_k[5]=0x6b; s_k[6]=0x2e; s_k[7]=0x77
158 s_k[8]=0x65; s_k[9]=0x69; s_k[10]=0x67; s_k[11]=0x68; s_k[12]=0x74
159
160 let s_v: *u8 = sys_mmap(13)
161 s_v[0]=0x61; s_v[1]=0x74; s_v[2]=0x74; s_v[3]=0x6e
162 s_v[4]=0x5f; s_v[5]=0x76; s_v[6]=0x2e; s_v[7]=0x77
163 s_v[8]=0x65; s_v[9]=0x69; s_v[10]=0x67; s_v[11]=0x68; s_v[12]=0x74
164
165 let s_o: *u8 = sys_mmap(18)
166 s_o[0]=0x61; s_o[1]=0x74; s_o[2]=0x74; s_o[3]=0x6e
167 s_o[4]=0x5f; s_o[5]=0x6f; s_o[6]=0x75; s_o[7]=0x74
168 s_o[8]=0x70; s_o[9]=0x75; s_o[10]=0x74; s_o[11]=0x2e
169 s_o[12]=0x77; s_o[13]=0x65; s_o[14]=0x69; s_o[15]=0x67
170 s_o[16]=0x68; s_o[17]=0x74
171
172 let s_fn: *u8 = sys_mmap(15)
173 s_fn[0]=0x66; s_fn[1]=0x66; s_fn[2]=0x6e; s_fn[3]=0x5f
174 s_fn[4]=0x6e; s_fn[5]=0x6f; s_fn[6]=0x72; s_fn[7]=0x6d
175 s_fn[8]=0x2e; s_fn[9]=0x77; s_fn[10]=0x65; s_fn[11]=0x69
176 s_fn[12]=0x67; s_fn[13]=0x68; s_fn[14]=0x74
177
178 let s_fg: *u8 = sys_mmap(15)
179 s_fg[0]=0x66; s_fg[1]=0x66; s_fg[2]=0x6e; s_fg[3]=0x5f
180 s_fg[4]=0x67; s_fg[5]=0x61; s_fg[6]=0x74; s_fg[7]=0x65
181 s_fg[8]=0x2e; s_fg[9]=0x77; s_fg[10]=0x65; s_fg[11]=0x69
182 s_fg[12]=0x67; s_fg[13]=0x68; s_fg[14]=0x74
183
184 let s_fu: *u8 = sys_mmap(13)
185 s_fu[0]=0x66; s_fu[1]=0x66; s_fu[2]=0x6e; s_fu[3]=0x5f
186 s_fu[4]=0x75; s_fu[5]=0x70; s_fu[6]=0x2e; s_fu[7]=0x77
187 s_fu[8]=0x65; s_fu[9]=0x69; s_fu[10]=0x67; s_fu[11]=0x68; s_fu[12]=0x74
188
189 let s_fd: *u8 = sys_mmap(15)
190 s_fd[0]=0x66; s_fd[1]=0x66; s_fd[2]=0x6e; s_fd[3]=0x5f
191 s_fd[4]=0x64; s_fd[5]=0x6f; s_fd[6]=0x77; s_fd[7]=0x6e
192 s_fd[8]=0x2e; s_fd[9]=0x77; s_fd[10]=0x65; s_fd[11]=0x69
193 s_fd[12]=0x67; s_fd[13]=0x68; s_fd[14]=0x74
194
195 let n_an: *u8 = sys_mmap(32); let l_an: nx_int = _gft_mk_blk_name(s_an, 16, n_an)
196 let n_q: *u8 = sys_mmap(32); let l_q: nx_int = _gft_mk_blk_name(s_q, 13, n_q)
197 let n_k: *u8 = sys_mmap(32); let l_k: nx_int = _gft_mk_blk_name(s_k, 13, n_k)
198 let n_v: *u8 = sys_mmap(32); let l_v: nx_int = _gft_mk_blk_name(s_v, 13, n_v)
199 let n_o: *u8 = sys_mmap(32); let l_o: nx_int = _gft_mk_blk_name(s_o, 18, n_o)
200 let n_fn: *u8 = sys_mmap(32); let l_fn: nx_int = _gft_mk_blk_name(s_fn, 15, n_fn)
201 let n_fg: *u8 = sys_mmap(32); let l_fg: nx_int = _gft_mk_blk_name(s_fg, 15, n_fg)
202 let n_fu: *u8 = sys_mmap(32); let l_fu: nx_int = _gft_mk_blk_name(s_fu, 13, n_fu)
203 let n_fd: *u8 = sys_mmap(32); let l_fd: nx_int = _gft_mk_blk_name(s_fd, 15, n_fd)
204
205 var p: i64 = 24
206 p = _gft_write_ti(buf, p, n_te, 17, 2, 4, 2, NX_GGML_TYPE_F32, 0)
207 p = _gft_write_ti(buf, p, n_on, 18, 1, 2, 1, NX_GGML_TYPE_F32, 32)
208 p = _gft_write_ti(buf, p, n_ow, 13, 2, 2, 4, NX_GGML_TYPE_F32, 40)
209 p = _gft_write_ti(buf, p, n_an, l_an, 1, 2, 1, NX_GGML_TYPE_F32, 72)
210 p = _gft_write_ti(buf, p, n_q, l_q, 2, 2, 2, NX_GGML_TYPE_F32, 80)
211 p = _gft_write_ti(buf, p, n_k, l_k, 2, 2, 2, NX_GGML_TYPE_F32, 96)
212 p = _gft_write_ti(buf, p, n_v, l_v, 2, 2, 2, NX_GGML_TYPE_F32, 112)
213 p = _gft_write_ti(buf, p, n_o, l_o, 2, 2, 2, NX_GGML_TYPE_F32, 128)
214 p = _gft_write_ti(buf, p, n_fn, l_fn, 1, 2, 1, NX_GGML_TYPE_F32, 144)
215 p = _gft_write_ti(buf, p, n_fg, l_fg, 2, 2, 4, NX_GGML_TYPE_F32, 152)
216 p = _gft_write_ti(buf, p, n_fu, l_fu, 2, 2, 4, NX_GGML_TYPE_F32, 184)
217 p = _gft_write_ti(buf, p, n_fd, l_fd, 2, 4, 2, NX_GGML_TYPE_F32, 216)
218
219 let data_off: i64 = (p + 31) / 32 * 32
220 var zi: nx_int = 0
221 while zi < 248 { buf[data_off + zi] = 0; zi = zi + 1 }
222
223 // ===== Parse the header =====
224 let hdr: *NxGgufHeader = sys_mmap(NX_GGUF_HDR_BYTES) as *NxGgufHeader
225 if nx_gguf_parse(buf, NX_MAGIC_4096, hdr) != NX_GGUF_OK {
226 b.verdict = NX_GFT_ERR_PARSE
227 return b
228 }
229 b.hdr = hdr
230
231 // ===== Model spec =====
232 let spec: *NxModelSpec = nx_model_spec_new()
233 spec.n_layers = 1
234 spec.hidden_dim = 2
235 spec.n_heads = 1
236 spec.head_dim = 2
237 spec.n_kv_heads = 1
238 spec.ffn_dim = 4
239 spec.vocab_size = 4
240 spec.max_seq_len = 8
241 if nx_model_spec_validate(spec) != NX_MS_OK {
242 b.verdict = NX_GFT_ERR_SPEC_INVALID
243 return b
244 }
245 b.spec = spec
246
247 // ===== BPE vocab (4 single-byte tokens) + vocab-id-to-byte map =====
248 let bpe: *NxBpeVocab = nx_bpe_vocab_new(256, 16, 8)
249 let ba: *u8 = sys_mmap(1); ba[0] = 0x61
250 let bb: *u8 = sys_mmap(1); bb[0] = 0x62
251 let bc: *u8 = sys_mmap(1); bc[0] = 0x63
252 let bd: *u8 = sys_mmap(1); bd[0] = 0x64
253 nx_bpe_add_token(bpe, ba, 1)
254 nx_bpe_add_token(bpe, bb, 1)
255 nx_bpe_add_token(bpe, bc, 1)
256 nx_bpe_add_token(bpe, bd, 1)
257 b.bpe = bpe
258
259 let vocab_map: *u8 = sys_mmap(4)
260 vocab_map[0] = 0x61
261 vocab_map[1] = 0x62
262 vocab_map[2] = 0x63
263 vocab_map[3] = 0x64
264 b.vocab_byte_map = vocab_map
265
266 // ===== PRNG =====
267 let prng: *i64 = sys_mmap(8) as *i64
268 nx_prng_init(prng, prng_seed)
269 b.prng_state = prng
270
271 return b
272}
273
274// ===== Accessors / queries ========================================
275
276func nx_gft_verdict(b: *NxGgufFixtureBundle) -> nx_int {
277 if (b as i64) == 0 { return NX_GFT_ERR_NULL }
278 return b.verdict
279}
280
281func nx_gft_vocab_byte(b: *NxGgufFixtureBundle, token_id: nx_int) -> nx_int {
282 if (b as i64) == 0 { return -1 }
283 if token_id < 0 { return -1 }
284 if token_id >= b.vocab_size { return -1 }
285 return b.vocab_byte_map[token_id] as nx_int
286}
287
288func nx_gft_is_built(b: *NxGgufFixtureBundle) -> nx_int {
289 if (b as i64) == 0 { return 0 }
290 if b.verdict != NX_GFT_OK { return 0 }
291 if (b.gguf_buf as i64) == 0 { return 0 }
292 if (b.hdr as i64) == 0 { return 0 }
293 if (b.spec as i64) == 0 { return 0 }
294 if (b.bpe as i64) == 0 { return 0 }
295 if (b.prng_state as i64) == 0 { return 0 }
296 return 1
297}