code wiki / (root) / nx_llm_run_v2_test.nx

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}