nx_llm_run_v2_test.nx source
↩ module page · 243 lines · 9450 B
1// nx_llm_run_v2_test.nx -- end-to-end smoke for nx_llm_run_v2.nx.
2//
3// Builds the FULL Llama-shape GGUF (12 tensors) for n_layers=1 with
4// all-zero F32 weights, builds a tiny BPE vocab, and runs
5// nx_llm_generate_one_v2. With all-zero weights the forward yields
6// uniform logits and the sampler returns a token in [0, vocab_size).
7//
8// This is the integration proof: every loader + composer brick
9// shipped this session walks end-to-end from text prompt to emitted
10// token ID via pure NishiLang.
11
12import "nx_syscalls.nx"
13import "nx_tier.nx"
14import "nx_le.nx"
15import "nx_tensor.nx"
16import "nx_bpe.nx"
17import "nx_model_spec.nx"
18import "nx_prng.nx"
19import "nx_gguf.nx"
20import "nx_gguf_load.nx"
21import "nx_llm_run_v2.nx"
22
23func _write_ti(buf: *u8, off: i64,
24 name: *u8, name_len: i64,
25 n_dims: i64, dim_0: i64, dim_1: i64,
26 ggml_type: i64, data_offset: i64) -> i64 {
27 nx_le_write_u64(buf, off, name_len)
28 var o: i64 = off + 8
29 var i: i64 = 0
30 while i < name_len { buf[o + i] = name[i]; i = i + 1 }
31 o = o + name_len
32 nx_le_write_u32(buf, o, n_dims); o = o + 4
33 nx_le_write_u64(buf, o, dim_0); o = o + 8
34 if n_dims >= 2 { nx_le_write_u64(buf, o, dim_1); o = o + 8 }
35 nx_le_write_u32(buf, o, ggml_type); o = o + 4
36 nx_le_write_u64(buf, o, data_offset); o = o + 8
37 return o
38}
39
40func _mk_blk_name(suffix: *u8, suffix_len: nx_int, out: *u8) -> nx_int {
41 out[0]=0x62; out[1]=0x6c; out[2]=0x6b; out[3]=0x2e
42 out[4]=0x30 // layer 0
43 out[5]=0x2e
44 var i: nx_int = 0
45 while i < suffix_len {
46 out[6 + i] = suffix[i]
47 i = i + 1
48 }
49 return 6 + suffix_len
50}
51
52func main() -> i64 {
53 // ----- Verdict gate -----
54 var vi: nx_int = 0
55 while vi < NX_LR2_N_VERDICTS {
56 if nx_lr2_verdict_is_valid(vi) != 1 { return 5 + vi }
57 vi = vi + 1
58 }
59
60 let buf: *u8 = sys_mmap(4096)
61 buf[0]=0x47; buf[1]=0x47; buf[2]=0x55; buf[3]=0x46
62 buf[4]=3
63 nx_le_write_u64(buf, 8, 12) // 12 tensors total
64 nx_le_write_u64(buf, 16, 0)
65
66 // ----- Top-level tensor names -----
67 let n_te: *u8 = sys_mmap(17)
68 n_te[0]=0x74; n_te[1]=0x6f; n_te[2]=0x6b; n_te[3]=0x65
69 n_te[4]=0x6e; n_te[5]=0x5f; n_te[6]=0x65; n_te[7]=0x6d
70 n_te[8]=0x62; n_te[9]=0x64; n_te[10]=0x2e; n_te[11]=0x77
71 n_te[12]=0x65; n_te[13]=0x69; n_te[14]=0x67; n_te[15]=0x68
72 n_te[16]=0x74
73
74 let n_on: *u8 = sys_mmap(18)
75 n_on[0]=0x6f; n_on[1]=0x75; n_on[2]=0x74; n_on[3]=0x70
76 n_on[4]=0x75; n_on[5]=0x74; n_on[6]=0x5f; n_on[7]=0x6e
77 n_on[8]=0x6f; n_on[9]=0x72; n_on[10]=0x6d; n_on[11]=0x2e
78 n_on[12]=0x77; n_on[13]=0x65; n_on[14]=0x69; n_on[15]=0x67
79 n_on[16]=0x68; n_on[17]=0x74
80
81 let n_ow: *u8 = sys_mmap(13)
82 n_ow[0]=0x6f; n_ow[1]=0x75; n_ow[2]=0x74; n_ow[3]=0x70
83 n_ow[4]=0x75; n_ow[5]=0x74; n_ow[6]=0x2e; n_ow[7]=0x77
84 n_ow[8]=0x65; n_ow[9]=0x69; n_ow[10]=0x67; n_ow[11]=0x68
85 n_ow[12]=0x74
86
87 // ----- Per-layer tensor suffixes -----
88 let s_an: *u8 = sys_mmap(16)
89 s_an[0]=0x61; s_an[1]=0x74; s_an[2]=0x74; s_an[3]=0x6e
90 s_an[4]=0x5f; s_an[5]=0x6e; s_an[6]=0x6f; s_an[7]=0x72
91 s_an[8]=0x6d; s_an[9]=0x2e; s_an[10]=0x77; s_an[11]=0x65
92 s_an[12]=0x69; s_an[13]=0x67; s_an[14]=0x68; s_an[15]=0x74
93
94 let s_q: *u8 = sys_mmap(13)
95 s_q[0]=0x61; s_q[1]=0x74; s_q[2]=0x74; s_q[3]=0x6e
96 s_q[4]=0x5f; s_q[5]=0x71; s_q[6]=0x2e; s_q[7]=0x77
97 s_q[8]=0x65; s_q[9]=0x69; s_q[10]=0x67; s_q[11]=0x68; s_q[12]=0x74
98
99 let s_k: *u8 = sys_mmap(13)
100 s_k[0]=0x61; s_k[1]=0x74; s_k[2]=0x74; s_k[3]=0x6e
101 s_k[4]=0x5f; s_k[5]=0x6b; s_k[6]=0x2e; s_k[7]=0x77
102 s_k[8]=0x65; s_k[9]=0x69; s_k[10]=0x67; s_k[11]=0x68; s_k[12]=0x74
103
104 let s_v: *u8 = sys_mmap(13)
105 s_v[0]=0x61; s_v[1]=0x74; s_v[2]=0x74; s_v[3]=0x6e
106 s_v[4]=0x5f; s_v[5]=0x76; s_v[6]=0x2e; s_v[7]=0x77
107 s_v[8]=0x65; s_v[9]=0x69; s_v[10]=0x67; s_v[11]=0x68; s_v[12]=0x74
108
109 let s_o: *u8 = sys_mmap(18)
110 s_o[0]=0x61; s_o[1]=0x74; s_o[2]=0x74; s_o[3]=0x6e
111 s_o[4]=0x5f; s_o[5]=0x6f; s_o[6]=0x75; s_o[7]=0x74
112 s_o[8]=0x70; s_o[9]=0x75; s_o[10]=0x74; s_o[11]=0x2e
113 s_o[12]=0x77; s_o[13]=0x65; s_o[14]=0x69; s_o[15]=0x67
114 s_o[16]=0x68; s_o[17]=0x74
115
116 let s_fn: *u8 = sys_mmap(15)
117 s_fn[0]=0x66; s_fn[1]=0x66; s_fn[2]=0x6e; s_fn[3]=0x5f
118 s_fn[4]=0x6e; s_fn[5]=0x6f; s_fn[6]=0x72; s_fn[7]=0x6d
119 s_fn[8]=0x2e; s_fn[9]=0x77; s_fn[10]=0x65; s_fn[11]=0x69
120 s_fn[12]=0x67; s_fn[13]=0x68; s_fn[14]=0x74
121
122 let s_fg: *u8 = sys_mmap(15)
123 s_fg[0]=0x66; s_fg[1]=0x66; s_fg[2]=0x6e; s_fg[3]=0x5f
124 s_fg[4]=0x67; s_fg[5]=0x61; s_fg[6]=0x74; s_fg[7]=0x65
125 s_fg[8]=0x2e; s_fg[9]=0x77; s_fg[10]=0x65; s_fg[11]=0x69
126 s_fg[12]=0x67; s_fg[13]=0x68; s_fg[14]=0x74
127
128 let s_fu: *u8 = sys_mmap(13)
129 s_fu[0]=0x66; s_fu[1]=0x66; s_fu[2]=0x6e; s_fu[3]=0x5f
130 s_fu[4]=0x75; s_fu[5]=0x70; s_fu[6]=0x2e; s_fu[7]=0x77
131 s_fu[8]=0x65; s_fu[9]=0x69; s_fu[10]=0x67; s_fu[11]=0x68; s_fu[12]=0x74
132
133 let s_fd: *u8 = sys_mmap(15)
134 s_fd[0]=0x66; s_fd[1]=0x66; s_fd[2]=0x6e; s_fd[3]=0x5f
135 s_fd[4]=0x64; s_fd[5]=0x6f; s_fd[6]=0x77; s_fd[7]=0x6e
136 s_fd[8]=0x2e; s_fd[9]=0x77; s_fd[10]=0x65; s_fd[11]=0x69
137 s_fd[12]=0x67; s_fd[13]=0x68; s_fd[14]=0x74
138
139 let n_an: *u8 = sys_mmap(32); let l_an: nx_int = _mk_blk_name(s_an, 16, n_an)
140 let n_q: *u8 = sys_mmap(32); let l_q: nx_int = _mk_blk_name(s_q, 13, n_q)
141 let n_k: *u8 = sys_mmap(32); let l_k: nx_int = _mk_blk_name(s_k, 13, n_k)
142 let n_v: *u8 = sys_mmap(32); let l_v: nx_int = _mk_blk_name(s_v, 13, n_v)
143 let n_o: *u8 = sys_mmap(32); let l_o: nx_int = _mk_blk_name(s_o, 18, n_o)
144 let n_fn: *u8 = sys_mmap(32); let l_fn: nx_int = _mk_blk_name(s_fn, 15, n_fn)
145 let n_fg: *u8 = sys_mmap(32); let l_fg: nx_int = _mk_blk_name(s_fg, 15, n_fg)
146 let n_fu: *u8 = sys_mmap(32); let l_fu: nx_int = _mk_blk_name(s_fu, 13, n_fu)
147 let n_fd: *u8 = sys_mmap(32); let l_fd: nx_int = _mk_blk_name(s_fd, 15, n_fd)
148
149 // Cumulative byte offsets per F32 tensor (each at byte offset
150 // relative to data_off):
151 // token_embd [4,2] = 32 (off 0)
152 // output_norm [2] = 8 (off 32)
153 // output [2,4] = 32 (off 40)
154 // attn_norm [2] = 8 (off 72)
155 // attn_q [2,2] = 16 (off 80)
156 // attn_k [2,2] = 16 (off 96)
157 // attn_v [2,2] = 16 (off 112)
158 // attn_output [2,2] = 16 (off 128)
159 // ffn_norm [2] = 8 (off 144)
160 // ffn_gate [2,4] = 32 (off 152)
161 // ffn_up [2,4] = 32 (off 184)
162 // ffn_down [4,2] = 32 (off 216)
163 // total 248 bytes
164
165 var p: i64 = 24
166 p = _write_ti(buf, p, n_te, 17, 2, 4, 2, NX_GGML_TYPE_F32, 0)
167 p = _write_ti(buf, p, n_on, 18, 1, 2, 1, NX_GGML_TYPE_F32, 32)
168 p = _write_ti(buf, p, n_ow, 13, 2, 2, 4, NX_GGML_TYPE_F32, 40)
169 p = _write_ti(buf, p, n_an, l_an, 1, 2, 1, NX_GGML_TYPE_F32, 72)
170 p = _write_ti(buf, p, n_q, l_q, 2, 2, 2, NX_GGML_TYPE_F32, 80)
171 p = _write_ti(buf, p, n_k, l_k, 2, 2, 2, NX_GGML_TYPE_F32, 96)
172 p = _write_ti(buf, p, n_v, l_v, 2, 2, 2, NX_GGML_TYPE_F32, 112)
173 p = _write_ti(buf, p, n_o, l_o, 2, 2, 2, NX_GGML_TYPE_F32, 128)
174 p = _write_ti(buf, p, n_fn, l_fn, 1, 2, 1, NX_GGML_TYPE_F32, 144)
175 p = _write_ti(buf, p, n_fg, l_fg, 2, 2, 4, NX_GGML_TYPE_F32, 152)
176 p = _write_ti(buf, p, n_fu, l_fu, 2, 2, 4, NX_GGML_TYPE_F32, 184)
177 p = _write_ti(buf, p, n_fd, l_fd, 2, 4, 2, NX_GGML_TYPE_F32, 216)
178
179 let data_off: i64 = (p + 31) / 32 * 32
180
181 // Zero out the 248-byte data section. sys_mmap may not zero by
182 // default depending on substrate config, so write explicit zeros.
183 var zi: nx_int = 0
184 while zi < 248 {
185 buf[data_off + zi] = 0
186 zi = zi + 1
187 }
188
189 // ----- Parse the GGUF -----
190 let hdr: *NxGgufHeader = sys_mmap(NX_GGUF_HDR_BYTES) as *NxGgufHeader
191 let vp: nx_int = nx_gguf_parse(buf, 4096, hdr)
192 if vp != NX_GGUF_OK { return 20 + vp }
193 if hdr.n_tensors != 12 { return 30 }
194
195 // ----- Model spec -----
196 let spec: *NxModelSpec = nx_model_spec_new()
197 spec.n_layers = 1
198 spec.hidden_dim = 2
199 spec.n_heads = 1
200 spec.head_dim = 2
201 spec.n_kv_heads = 1
202 spec.ffn_dim = 4
203 spec.vocab_size = 4
204 spec.max_seq_len = 8
205 if nx_model_spec_validate(spec) != NX_MS_OK { return 40 }
206
207 // ----- Tiny BPE vocab: 4 single-byte tokens 'a' 'b' 'c' 'd' -----
208 let bpe: *NxBpeVocab = nx_bpe_vocab_new(256, 16, 8)
209 let ba: *u8 = sys_mmap(1); ba[0] = 0x61
210 let bb: *u8 = sys_mmap(1); bb[0] = 0x62
211 let bc: *u8 = sys_mmap(1); bc[0] = 0x63
212 let bd: *u8 = sys_mmap(1); bd[0] = 0x64
213 nx_bpe_add_token(bpe, ba, 1)
214 nx_bpe_add_token(bpe, bb, 1)
215 nx_bpe_add_token(bpe, bc, 1)
216 nx_bpe_add_token(bpe, bd, 1)
217
218 // Prompt = "a" (1 byte)
219 let prompt: *u8 = sys_mmap(1); prompt[0] = 0x61
220
221 // PRNG
222 let prng: *i64 = sys_mmap(8) as *i64
223 nx_prng_init(prng, 0xcafebabe)
224
225 // ----- Run! -----
226 // temperature_q10 = 1024 (1.0)
227 // top_k = 4 (entire vocab)
228 // rope_base = 10000
229 // attn_scale_q10 = 724 (~ 1/sqrt(2))
230 let next_token: nx_int = nx_llm_generate_one_v2(
231 spec, buf, hdr, bpe,
232 prompt, 1,
233 1024, 4,
234 prng,
235 10000, 724)
236
237 // Negative return = error verdict
238 if next_token < 0 { return 100 - next_token }
239 // Token must be in [0, vocab_size)
240 if next_token >= spec.vocab_size { return 200 }
241
242 return 0
243}