code wiki / (root) / nx_nofloat_serve_core.nx

nx_nofloat_serve_core.nx source

↩ module page · 1382 lines · 69093 B

1// nx_nofloat_serve_core.nx -- the PURE CORE of the no-float LLM serve organ (2026-07-10): model session + 2// greedy generation + HTTP request handler, NO sockets (the daemon shell owns those; the gate exercises this 3// core in-process with synthetic requests -- the proven pure-core+gate+daemon idiom). 4// nsv_init(path) one-time: load GGUF, tokenizer meta, dequant-once i32 (lossless hero) + i8 (fast) caches. 5// nsv_generate(gp) ctx-bundle: sequential CACHED prefill (decode_step per prompt token -- mathematically 6// identical to batch prefill under causal masking) then greedy decode; text out through 7// the byte-level-BPE inverse (nx_nofloat_tokdec) so ' Paris' renders as real text. 8// nsv_handle(...) routes: GET / (app page) GET /health GET /api POST /gen {prompt,max_new,mode}. 9// license_tier: ORIGINAL No hw writes (Rule 26). 10import "nx_syscalls.nx" 11import "nx_tier.nx" 12import "nx_le.nx" 13import "nx_tensor.nx" 14import "nx_gguf.nx" 15import "nx_gguf_load.nx" 16import "nx_gguf_meta.nx" 17import "nx_nofloat_llm.nx" 18import "nx_nofloat_tok.nx" 19import "nx_nofloat_tokdec.nx" 20import "nx_nofloat_arch.nx" 21import "nx_nofloat_q4k.nx" // LM4 resident-Q4_K decode (2026-09-02): the 7B fits because the weights stay in the file map 22 23const NSV_MAXT: i64 = 2048 // final prompt+gen TOKEN cap (KV cache rows). L2 raise 384->2048 (FORGE 2026-07-12) 24 // so a mini-pack (~1300 tok) + task + whole-organ generation fits. Decode buffers + 25 // KV cache scale with this: ~+200MB at 2048 for the 0.5B coder (24L, kvd=128, ne=896) 26 // -- well within WSL 16GB alongside the ~700MB model + i32/i8 caches. Gated L2. 27const NSV_MAXIN: i64 = 16384 // max prompt BYTES for the tokenizer's byte-level pretokenize scratch (tok_ptr/tok_len). 28 // L2 raise 8192->16384 for the full mini-pack (3911B) + task headroom. 29 // ⚠ tk_bpe_encode seeds 1 slot per INPUT BYTE -> those buffers MUST be sized by bytes, 30 // NOT NSV_MAXT (the old NSV_MAXT*8 page-rounded to 512 entries -> SIGSEGV on >512-byte prompts). 31const NSV_MAXNEW: i64 = 512 // per-request generation cap (L2 raise 96->512 for whole small organs) 32const NSV_CHATML_IDS: i64 = 8 // ids the ChatML wrapper adds around the content (two markers plus the user, newline and assistant pieces) 33const NSV_ERR_TOO_LONG: i64 = 3 // meta[5] for a prompt past the byte cap or the token cap: refused at the door, never half-encoded 34const NSV_PREFILL_BATCHED_DEFAULT: i64 = 1 // R0r: the i8 route prefills in blocks through nf_prefill_batched (nx_nofloat_prefill_gate proves it bit-identical); declared here because its first reader is the scratch allocator 35const NSV_EOS1: i64 = 151643 36const NSV_EOS2: i64 = 151645 37 38static g_nsv_buf: *u8 39static g_nsv_hdr: *NxGgufHeader 40static g_nsv_wc32: *i64 41static g_nsv_wc8: *i64 42static g_nsv_wq4: *i64 // LM4: per-layer resident-Q4_K slot tables (nx_nofloat_q4k), built instead of wc8 when g_nsv_q4k 43static g_nsv_q4k: i64 // 1 = resident-Q4_K serve: model file-mapped, no i32/i16 layer caches, decode mode 3 44static g_nsv_q4st: *i64 // NQ_ST_WORDS census of the q4k build (in-place vs fallback tensors and bytes) 45static g_nsv_hcp: *i64 46static g_nsv_sb: *i64 47static g_nsv_kvc: *i64 48static g_nsv_freqs: *i64 49static g_nsv_cfgA: *i64 50static g_nsv_cfgF: *i64 51static g_nsv_tmp: *i64 52static g_nsv_x1: *i64 53static g_nsv_h1: *i64 54static g_nsv_xt: *i64 // R0r: the prompt's dequantised embedding rows (NSV_MAXT x ne) 55static g_nsv_prefill_batched: i64 // R0r: 1 = blocks through nf_prefill_batched on the i8 route, 0 = the sequential control 56static g_nsv_normed: *i64 57static g_nsv_gout: *i64 58static g_nsv_idout: *i64 59static g_nsv_lgout: *i64 60static g_nsv_nmbuf: *u8 61static g_nsv_ids: *i64 62static g_nsv_tokp: *i64 63static g_nsv_tokl: *i64 64static g_nsv_lgv: *i64 // full vocab logits (sampling path) 65static g_nsv_mt: *i64 // [0]=mfirst [1]=nm_c [2]=vfirst [3]=vocab [4]=te_base [5]=te_ty [6]=ready [7]=init_ms 66static g_nsv_mpath: *u8 // the ACTUAL loaded model path (health must not lie about which model serves) 67static g_nsv_dims: *i64 // arch-config (nac_read_config 2026-07-15): [0]=D [1]=n_layers [2]=n_heads [3]=n_kv [4]=head_dim [5]=q_dim [6]=kv_dim [7]=ffn [8]=scale_q16 [9]=rope_base [10]=ok 68static g_nsv_kvsnap: *i64 // PREFIX-KV-CACHE (2026-07-15): snapshot of KV rows 0..P-1 (the fixed prompt prefix) for reuse across requests 69static g_nsv_snap_p: i64 // number of prefix tokens currently snapshotted (0 = none) 70static g_nsv_crib_ids: *i64 // the snapshotted prefix's token ids (for common-prefix safety vs BPE re-tokenization) 71 72func nsv_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 73func nsv_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off+i]=s[i];i=i+1} return off+i } 74func nsv_catb(dst: *u8, off: i64, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n {dst[off+i]=s[i];i=i+1} return off+n } 75func nsv_catn(dst: *u8, off: i64, v: i64) -> i64 { 76 var o: i64=off 77 var m: i64=v 78 if m<0 { dst[o]=45 as u8; o=o+1; m=0-m } 79 let t: *u8=sys_mmap(28) 80 var k: i64=0 81 if m==0 { t[0]=48 as u8; k=1 } 82 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 83 var i: i64=0 84 while i<k { dst[o+i]=t[k-1-i]; i=i+1 } 85 return o+k 86} 87 88func nsv_log(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 89 90// g_nsv_mt layout: [0]=mfirst [1]=nm_c [2]=vfirst [3]=vocab [4]=te_base [5]=te_ty [6]=ready [7]=init_ms 91// [8]=oh_base [9]=oh_ty (head tensor -- passed to nsv_build_caches via statics) 92 93// STAGE 1: read model, parse, resolve tokenizer meta + the 3 tensors, load output-norm. NO pooled calls. 94// Split from nsv_init (single responsibility + lean frame: the fused 150-line init hit an nx_cc large-frame 95// codegen edge -- a GP fault at the first pooled call -- that vanishes when each stage is its own function). 96func nsv_load_meta(path: *u8) -> i64 { 97 let len_out: *i64 = sys_mmap(8) as *i64 98 len_out[0]=0 99 if g_nsv_q4k == 1 { 100 // LM4: the weights are READ IN PLACE, so the model must be a file-backed map (evictable page cache), 101 // never a 4.7 GB anonymous copy. sys_map_file is read-only by construction (Rule 26). 102 nsv_log(" [init] mapping model (file-backed, resident-Q4_K)...\n" as *u8) 103 g_nsv_buf = sys_map_file(path, len_out) 104 } else { 105 nsv_log(" [init] reading model...\n" as *u8) 106 g_nsv_buf = sys_read_file(path, len_out) 107 } 108 if (g_nsv_buf as i64) == 0 { return 1 } 109 g_nsv_hdr = sys_mmap(NX_GGUF_HDR_BYTES) as *NxGgufHeader 110 nsv_log(" [init] parsing gguf...\n" as *u8) 111 if nx_gguf_parse(g_nsv_buf, len_out[0], g_nsv_hdr) != NX_GGUF_OK { return 2 } 112 // ARCH-CONFIG (2026-07-15): dims from the model's own metadata (nac_read_config, gate-proven 07-10) -- 113 // ANY Qwen2/Llama-schema gguf serves; for the 0.5B these are the SAME numbers, now read instead of assumed. 114 g_nsv_dims = sys_mmap(16*8) as *i64 115 let arch_out: *u8 = sys_mmap(48) 116 if nac_read_config(g_nsv_buf, len_out[0], g_nsv_hdr, g_nsv_dims, arch_out) != 0 { return 8 } 117 if g_nsv_dims[10] != 1 { return 8 } 118 // FAIL-FAST TYPE SCAN (2026-07-15 debt-eaten): every tensor's quant type must be supported BEFORE we 119 // serve. Unknown types used to zero/wrong-decode SILENTLY mid-token; now init refuses (error 10) and 120 // the daemon never comes up on a model we cannot faithfully decode. (⚠hsc is a FRESH local -- the 121 // first cut used `hloc` which is declared LATER in this fn; nx_cc accepts use-before-declare of a 122 // local and reads stack garbage -> SEGV. The LOCAL sibling of the fwd-static-ref gotcha.) 123 let hsc: *NxGgufHeader = g_nsv_hdr 124 let vbts: *i64 = sys_mmap(16) as *i64 125 var tscan: i64 = 0 126 while tscan < hsc.tensor_count { 127 let tsi: *NxGgufTensorInfo = nx_gguf_tensor_at(hsc, tscan) 128 if nf_type_stride(tsi.ggml_type, vbts) != 0 { return 10 } 129 tscan = tscan + 1 130 } 131 let ne: i64 = g_nsv_dims[0] 132 // hloc: local copy of the static header pointer. This organ FOUND the static-base member-access 133 // miscompile (g_nsv_hdr.data_off returned the pointer, not the field) -- ROOT-FIXED + BLESSED 134 // 2026-07-10 (nx_parse VK_GLOBAL unwrap, nx_static_field_probe pins it). The local copy stays as 135 // style: one load, then cheap field reads. 136 let hloc: *NxGgufHeader = g_nsv_hdr 137 g_nsv_mt = sys_mmap(16*8) as *i64 138 let voff: *i64=sys_mmap(8) as *i64 139 let vty: *i64=sys_mmap(8) as *i64 140 let km: *u8="tokenizer.ggml.merges" as *u8 141 let kt: *u8="tokenizer.ggml.tokens" as *u8 142 if nx_gguf_meta_find(g_nsv_buf, len_out[0], g_nsv_hdr, km, nsv_slen(km), voff, vty)==NX_GMETA_OK { 143 g_nsv_mt[1]=nx_gguf_meta_array_count(g_nsv_buf, voff[0]) 144 g_nsv_mt[0]=nx_gguf_meta_array_first_elt_off(g_nsv_buf, voff[0]) 145 } else { return 3 } 146 if nx_gguf_meta_find(g_nsv_buf, len_out[0], g_nsv_hdr, kt, nsv_slen(kt), voff, vty)==NX_GMETA_OK { 147 g_nsv_mt[3]=nx_gguf_meta_array_count(g_nsv_buf, voff[0]) 148 g_nsv_mt[2]=nx_gguf_meta_array_first_elt_off(g_nsv_buf, voff[0]) 149 } else { return 4 } 150 let nt: *u8="token_embd.weight" as *u8 151 let no: *u8="output.weight" as *u8 152 let nn: *u8="output_norm.weight" as *u8 153 let ie: nx_int=nx_gguf_find_tensor(g_nsv_hdr, nt, 17) 154 var io: nx_int=nx_gguf_find_tensor(g_nsv_hdr, no, 13) 155 let inn: nx_int=nx_gguf_find_tensor(g_nsv_hdr, nn, 18) 156 if ie<0 { return 5 } 157 if io<0 { io = ie } // tied-embeddings fallback: qwen2-0.5b ties lm_head to token_embd; embedding-model GGUFs (jina) omit output.weight entirely 158 if inn<0 { return 5 } 159 let te: *NxGgufTensorInfo=nx_gguf_tensor_at(hloc, ie) 160 g_nsv_mt[4]=hloc.data_off+te.offset 161 g_nsv_mt[5]=te.ggml_type 162 let oh: *NxGgufTensorInfo=nx_gguf_tensor_at(hloc, io) 163 g_nsv_mt[8]=hloc.data_off+oh.offset 164 g_nsv_mt[9]=oh.ggml_type 165 nsv_log(" [init] tensors located; loading output norm...\n" as *u8) 166 g_nsv_gout=sys_mmap(ne*8) as *i64 167 load_named_q16(g_nsv_buf, g_nsv_hdr, nn, 18, g_nsv_gout, ne) 168 return 0 169} 170 171// STAGE 2: allocate all per-request scratch + KV caches (sized to the serve MAXT). NO pooled calls. 172func nsv_alloc_scratch() -> i64 { 173 let ne: i64 = g_nsv_dims[0] 174 let qd: i64 = g_nsv_dims[5] 175 let kvd: i64 = g_nsv_dims[6] 176 let fd: i64 = g_nsv_dims[7] 177 let nl: i64 = g_nsv_dims[1] 178 let hd: i64 = g_nsv_dims[4] 179 nsv_log(" [init] allocating scratch + kv...\n" as *u8) 180 g_nsv_sb=sys_mmap(14*8) as *i64 181 g_nsv_sb[0]=sys_mmap(NSV_MAXT*ne*8) as i64 182 g_nsv_sb[1]=sys_mmap(NSV_MAXT*qd*8) as i64 183 g_nsv_sb[2]=sys_mmap(NSV_MAXT*kvd*8) as i64 184 g_nsv_sb[3]=sys_mmap(NSV_MAXT*kvd*8) as i64 185 g_nsv_sb[4]=sys_mmap(NSV_MAXT*qd*8) as i64 186 g_nsv_sb[5]=sys_mmap(NSV_MAXT*8) as i64 187 g_nsv_sb[6]=sys_mmap(NSV_MAXT*8) as i64 188 g_nsv_sb[7]=sys_mmap(NSV_MAXT*ne*8) as i64 189 g_nsv_sb[8]=sys_mmap(NSV_MAXT*fd*8) as i64 190 g_nsv_sb[9]=sys_mmap(NSV_MAXT*fd*8) as i64 191 g_nsv_sb[10]=sys_mmap(NSV_MAXT*fd*8) as i64 192 g_nsv_sb[11]=sys_mmap(NSV_MAXT*ne*8) as i64 193 g_nsv_sb[12]=sys_mmap(NSV_MAXT*ne*8) as i64 194 g_nsv_sb[13]=sys_mmap(NSV_MAXT*ne*8) as i64 195 g_nsv_kvc=sys_mmap(2*nl*8) as *i64 196 var kl: i64=0 197 while kl<nl { g_nsv_kvc[2*kl]=sys_mmap(NSV_MAXT*kvd*8) as i64; g_nsv_kvc[2*kl+1]=sys_mmap(NSV_MAXT*kvd*8) as i64; kl=kl+1 } 198 g_nsv_nmbuf=sys_mmap(64) 199 g_nsv_freqs=sys_mmap(hd*8) as *i64 200 rope_freqs(g_nsv_freqs, hd) 201 g_nsv_tmp=sys_mmap(64*256*8) as *i64 202 g_nsv_x1=sys_mmap(ne*8) as *i64 203 g_nsv_h1=sys_mmap(ne*8) as *i64 204 g_nsv_xt=sys_mmap(NSV_MAXT*ne*8) as *i64 205 g_nsv_prefill_batched=NSV_PREFILL_BATCHED_DEFAULT 206 g_nsv_normed=sys_mmap(ne*8) as *i64 207 g_nsv_idout=sys_mmap(8) as *i64 208 g_nsv_lgout=sys_mmap(8) as *i64 209 g_nsv_ids=sys_mmap((NSV_MAXIN + NSV_CHATML_IDS)*8) as *i64 // sized by BYTES like tokp/tokl (a token covers >= 1 byte, so ntok <= bytes): the token-cap check below is then always reached instead of an overrun (2026-09-17: a 19222-byte BRIGHT query overran the 2048-entry buffer and the serving engine died in tk_rank_fast) 210 g_nsv_tokp=sys_mmap(NSV_MAXIN*8) as *i64 // 1 slot per INPUT BYTE (byte-level pretokenize) -> size by BYTES 211 g_nsv_tokl=sys_mmap(NSV_MAXIN*8) as *i64 212 let vcl: i64 = g_nsv_mt[3] 213 g_nsv_lgv=sys_mmap(vcl*8) as *i64 214 g_nsv_cfgA=sys_mmap(8*8) as *i64 215 g_nsv_cfgA[1]=ne 216 g_nsv_cfgA[2]=g_nsv_dims[2] 217 g_nsv_cfgA[3]=g_nsv_dims[3] 218 g_nsv_cfgA[4]=hd 219 g_nsv_cfgA[5]=qd 220 g_nsv_cfgA[6]=kvd 221 g_nsv_cfgA[7]=g_nsv_dims[8] 222 g_nsv_cfgF=sys_mmap(4*8) as *i64 223 g_nsv_cfgF[1]=ne 224 g_nsv_cfgF[2]=fd 225 return 0 226} 227 228// ---- one-time session init (fail-fast: any error -> nonzero, organ must not serve). Thin orchestrator 229// over three lean stages -- each its own frame so the pooled STAGE 3 never shares a frame with the big 230// STAGE 1/2 setup (the large-frame codegen edge that GP-faulted the fused version). ---- 231// LIGHT INIT (2026-07-16, memory-proportionate loading): i8-only serve skips the i32 weight cache (~4 bytes/param 232// -- the single biggest allocation; ~6GB at 1.5B) so a mode-1-pinned organ fits comfortably inside the WSL VM 233// (host-pressure kills root-caused: 32GB host, dual-cache 1.5B init ~11GB -> intermittent SIGKILL of the tree). 234// Head cache stays (sampling needs full logits). CONTRACT: after nsv_init_i8, callers MUST pin mode=1 (gp[3]=1); 235// mode 0 would read the absent i32 cache. 236static g_nsv_i8only: i64 237static g_nsv_noi8: i64 // 1 = lossless-only init: the i32 cache and NO i8 cache (the quantisation-gap probe on a 16 GB VM) 238func nsv_init_i8(path: *u8) -> i64 { 239 g_nsv_i8only = 1 240 return nsv_init(path) 241} 242// LOSSLESS-ONLY INIT (2026-09-17, the quantisation-gap probe): the i32 cache and NO i8 cache, so a probe that decodes 243// mode 0 only fits beside the running i8 engine on a 16 GB VM. CONTRACT: callers pin mode=0 (gp[3]=0); mode 1 would 244// read the absent i8 cache. 245func nsv_init_i32only(path: *u8) -> i64 { 246 g_nsv_noi8 = 1 247 return nsv_init(path) 248} 249// LM4 RESIDENT-Q4_K INIT (2026-09-02): no i32 layer cache, no i16 layer cache -- every Q4_K projection is dotted 250// in place from the file map (nx_nofloat_q4k); non-Q4_K tensors fall back per tensor to i16 and are counted. 251// Head cache stays i32 (sampling needs full logits). CONTRACT: callers use decode mode 3 (the request parser 252// defaults to it and refuses i32/i8, whose caches were never built). 253func nsv_init_q4k(path: *u8) -> i64 { 254 g_nsv_q4k = 1 255 g_nsv_i8only = 1 256 return nsv_init(path) 257} 258func nsv_init(path: *u8) -> i64 { 259 let t0: i64 = sys_now_ms() 260 g_nsv_mpath = path 261 // Spawn the worker pool at startup (fail-fast: workers ready before the first request, not on first 262 // token). nf_pool is idempotent -> the cache build + every decode reuse this instance. 263 nsv_log(" [init] pre-warming worker pool...\n" as *u8) 264 nf_pool() 265 let rc1: i64 = nsv_load_meta(path) 266 if rc1 != 0 { return rc1 } 267 nsv_alloc_scratch() 268 let brc: i64 = nsv_build_caches() 269 if brc != 0 { return brc } 270 g_nsv_mt[7]=sys_now_ms()-t0 271 g_nsv_mt[6]=1 272 return 0 273} 274 275// STAGE 3: build the dequant-once caches (i32 head + i32 layers + i8 layers). The ONLY pooled stage; 276// reads oh_base/oh_ty from g_nsv_mt[8]/[9]. Lean frame = no GP fault at nf_pool() first-touch. 277func nsv_build_caches() -> i64 { 278 let ne: i64 = g_nsv_dims[0] 279 let qd: i64 = g_nsv_dims[5] 280 let kvd: i64 = g_nsv_dims[6] 281 let fd: i64 = g_nsv_dims[7] 282 let nl: i64 = g_nsv_dims[1] 283 let oh_base: i64 = g_nsv_mt[8] 284 let oh_ty: i64 = g_nsv_mt[9] 285 let vcb: i64 = g_nsv_mt[3] 286 nsv_log(" [init] building i32 head cache...\n" as *u8) 287 let hcache: *i32 = nf_dequant_head_all_i32(g_nsv_buf, oh_base, oh_ty, vcb, ne) 288 if (hcache as i64) <= 0 { return 7 } 289 if g_nsv_i8only == 0 { 290 nsv_log(" [init] building i32 weight cache (dequant-once)...\n" as *u8) 291 g_nsv_wc32=sys_mmap(nl*8) as *i64 292 let ovf: i64=nf_dequant_all_layers_i32(g_nsv_buf, g_nsv_hdr, g_nsv_wc32, nl, ne, qd, kvd, fd) 293 if ovf != 0 { return 6 } 294 } else { 295 nsv_log(" [init] i8-only: skipping i32 weight cache (memory-proportionate)\n" as *u8) 296 } 297 if g_nsv_q4k == 1 { 298 nsv_log(" [init] building resident-Q4_K slot tables (weights stay in the file map)...\n" as *u8) 299 g_nsv_wq4=sys_mmap(nl*8) as *i64 300 g_nsv_q4st=sys_mmap(NQ_ST_WORDS*8) as *i64 301 if nq_build_layers(g_nsv_buf, g_nsv_hdr, g_nsv_wq4, nl, ne, qd, kvd, fd, g_nsv_nmbuf, g_nsv_q4st) != 0 { return 11 } 302 nsv_log(" [init] q4k layers=" as *u8); nsv_logn(g_nsv_q4st[3]) 303 nsv_log(" inplace_tensors=" as *u8); nsv_logn(g_nsv_q4st[0]) 304 nsv_log(" inplace_file_bytes=" as *u8); nsv_logn(g_nsv_q4st[4]) 305 nsv_log(" fallback_i16_tensors=" as *u8); nsv_logn(g_nsv_q4st[1]) 306 nsv_log(" fallback_anon_bytes=" as *u8); nsv_logn(g_nsv_q4st[2]) 307 nsv_log(" q8_tensors=" as *u8); nsv_logn(g_nsv_q4st[5]); nsv_log(" q8_file_bytes=" as *u8); nsv_logn(g_nsv_q4st[6]) 308 nsv_log("\n" as *u8) 309 } else { if g_nsv_noi8 == 1 { 310 nsv_log(" [init] lossless-only: skipping i8 weight cache (this process decodes mode 0 only)\n" as *u8) 311 } else { 312 nsv_log(" [init] building i8 weight cache...\n" as *u8) 313 g_nsv_wc8=sys_mmap(nl*8) as *i64 314 nf_dequant_all_layers_i8(g_nsv_buf, g_nsv_hdr, g_nsv_wc8, nl, ne, qd, kvd, fd) 315 } } 316 nsv_log(" [init] caches ready\n" as *u8) 317 g_nsv_hcp=sys_mmap(6*8) as *i64 318 g_nsv_hcp[0]=hcache as i64 319 g_nsv_hcp[1]=g_nsv_normed as i64 320 g_nsv_hcp[2]=g_nsv_mt[3] 321 g_nsv_hcp[3]=ne 322 g_nsv_hcp[4]=g_nsv_idout as i64 323 g_nsv_hcp[5]=g_nsv_lgout as i64 324 return 0 325} 326 327func nsv_logn(v: i64) -> i64 { let t: *u8 = sys_mmap(32); let n: i64 = nsv_catn(t, 0, v); sys_write(1, t, n); return 0 } 328 329// one cached decode step at pos in the requested mode (0=i32 lossless, 1=i8 SIMD fast, 3=resident-Q4_K in place). 330const NSV_MODE_I32: i64 = 0 331const NSV_MODE_I8: i64 = 1 332const NSV_MODE_Q4K: i64 = 3 // 2 is the GPU embed grading mode (nsv_embed) -- never reuse it for a decode route 333func nsv_step(pos: i64, mode: i64) -> i64 { 334 if mode == NSV_MODE_Q4K { 335 decode_step_kv_q4k(g_nsv_x1, g_nsv_h1, g_nsv_wq4, g_nsv_sb, g_nsv_freqs, g_nsv_kvc, pos, g_nsv_cfgA, g_nsv_cfgF, g_nsv_dims[1]) 336 return 0 337 } 338 if mode == 1 { 339 decode_step_kv_cached_i8(g_nsv_buf, g_nsv_hdr, g_nsv_x1, g_nsv_h1, g_nsv_wc8, g_nsv_sb, g_nsv_nmbuf, g_nsv_freqs, g_nsv_kvc, pos, g_nsv_cfgA, g_nsv_cfgF, g_nsv_dims[1]) 340 } else { 341 decode_step_kv_cached_i32(g_nsv_buf, g_nsv_hdr, g_nsv_x1, g_nsv_h1, g_nsv_wc32, g_nsv_sb, g_nsv_nmbuf, g_nsv_freqs, g_nsv_kvc, pos, g_nsv_cfgA, g_nsv_cfgF, g_nsv_dims[1]) 342 } 343 return 0 344} 345 346// R0r: the sequential prefill (one cached step per prompt token) -- the control nx_nofloat_prefill_gate measures against. 347func nsv_prefill_seq(nprompt: i64, mode: i64) -> i64 { 348 let ne: i64 = g_nsv_cfgA[1] 349 var i: i64 = 0 350 while i < nprompt { 351 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[i], ne, g_nsv_x1, g_nsv_tmp) 352 nsv_step(i, mode) 353 i = i + 1 354 } 355 return 0 356} 357// R0r: the prompt's rows through nf_prefill_batched in blocks of NF_PREFILL_M positions (one weight pass per block; the 358// block keeps the activation rows L2-resident). Leaves g_nsv_h1 exactly as the sequential path leaves it. The i8 route 359// only: the i32 and Q4_K routes keep nsv_prefill_seq, and nsv_generate_pfx (the forge's prefix-cache path) stays sequential. 360func nsv_prefill_i8_batched(nprompt: i64) -> i64 { 361 let ne: i64 = g_nsv_cfgA[1] 362 var i: i64 = 0 363 while i < nprompt { 364 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[i], ne, ((g_nsv_xt as i64)+i*ne*8) as *i64, g_nsv_tmp) 365 i = i + 1 366 } 367 var b: i64 = 0 368 while b < nprompt { 369 var T: i64 = NF_PREFILL_M 370 if b + T > nprompt { T = nprompt - b } 371 nf_prefill_batched(g_nsv_buf, g_nsv_hdr, ((g_nsv_xt as i64)+b*ne*8) as *i64, g_nsv_h1, g_nsv_wc8, g_nsv_sb, g_nsv_nmbuf, g_nsv_freqs, g_nsv_kvc, b, T, g_nsv_cfgA, g_nsv_cfgF, g_nsv_dims[1]) 372 b = b + T 373 } 374 return 0 375} 376 377// xorshift64* PRNG step; state at sp[0] (never 0). Deterministic per seed -- "same in -> same bytes" holds 378// with the seed as part of the in. 379func nsv_rand(sp: *i64) -> i64 { 380 var s: i64 = sp[0] 381 s = s ^ (s >> 12) 382 s = s ^ (s << 25) 383 s = s ^ (s >> 27) 384 sp[0] = s 385 var r: i64 = s * 2685821657736338717 386 if r < 0 { r = 0 - r } 387 if r < 0 { r = 0 } 388 return r 389} 390// temperature/top-k/top-p sampling over the full logit vector -- 100 percent integer (logits are Q16 head 391// convention; fx_exp is the same Q16 exp the attention softmax rides). sp = [lgv, vocab, temp_pm, top_p_pm, 392// top_k, seed_state_ptr]. Returns the sampled token id. 393func nsv_sample(sp: *i64) -> i64 { 394 let lgv: *i64 = sp[0] as *i64 395 let vocab: i64 = sp[1] 396 var temp_pm: i64 = sp[2] 397 var top_p_pm: i64 = sp[3] 398 var k: i64 = sp[4] 399 let sd: *i64 = sp[5] as *i64 400 if temp_pm < 1 { temp_pm = 1 } 401 if temp_pm > 5000 { temp_pm = 5000 } 402 if top_p_pm < 1 { top_p_pm = 1 } 403 if top_p_pm > 1000 { top_p_pm = 1000 } 404 if k < 1 { k = 1 } 405 if k > 256 { k = 256 } 406 // top-k select (insertion into a small descending array; common case = 1 compare reject) 407 let kid: *i64 = sys_mmap(256*8) as *i64 408 let klg: *i64 = sys_mmap(256*8) as *i64 409 var n: i64 = 0 410 var v: i64 = 0 411 while v < vocab { 412 let l: i64 = lgv[v] 413 var take: i64 = 0 414 if n < k { take = 1 } else { if l > klg[n-1] { take = 1 } } 415 if take == 1 { 416 var pos: i64 = n 417 if pos >= k { pos = k - 1 } 418 var j: i64 = pos 419 while j > 0 { if l > klg[j-1] { klg[j]=klg[j-1]; kid[j]=kid[j-1]; j=j-1 } else { j = 0 - j } } 420 if j < 0 { j = 0 - j } 421 klg[j]=l 422 kid[j]=v 423 if n < k { n = n + 1 } 424 } 425 v = v + 1 426 } 427 // temperature -> Q16 exp weights (max-subtracted so fx_exp sees <= 0) 428 let ev: *i64 = sys_mmap(256*8) as *i64 429 let base: i64 = klg[0] 430 var total: i64 = 0 431 var i: i64 = 0 432 while i < n { 433 let x: i64 = ((klg[i] - base) * 1000) / temp_pm 434 let e: i64 = fx_exp(x) 435 ev[i] = e 436 total = total + e 437 i = i + 1 438 } 439 if total <= 0 { return kid[0] } 440 // top-p nucleus: keep the smallest prefix (descending) whose mass >= top_p_pm/1000 of total 441 let cutoff: i64 = (top_p_pm * total) / 1000 442 var m: i64 = 0 443 var cum: i64 = 0 444 var going: i64 = 1 445 while going == 1 { 446 if m >= n { going = 0 } else { 447 cum = cum + ev[m] 448 m = m + 1 449 if cum >= cutoff { going = 0 } 450 } 451 } 452 if m < 1 { m = 1 } 453 var mtotal: i64 = 0 454 i = 0 455 while i < m { mtotal = mtotal + ev[i]; i = i + 1 } 456 if mtotal <= 0 { return kid[0] } 457 // draw 458 let r: i64 = nsv_rand(sd) % mtotal 459 var c2: i64 = 0 460 i = 0 461 while i < m { c2 = c2 + ev[i]; if c2 > r { return kid[i] } i = i + 1 } 462 return kid[m-1] 463} 464// pick the next token from the current normed hidden state. np = [temp_pm, top_p_pm, top_k, seed_state_ptr]. 465// temp_pm==0 -> greedy argmax (the bit-exact hero path, unchanged); else full-logits head + seeded sampling. 466func nsv_next_token(np: *i64) -> i64 { 467 if np[0] == 0 { return head_argmax_cached_i32(g_nsv_hcp) } 468 let hlp: *i64 = sys_mmap(6*8) as *i64 469 hlp[0]=g_nsv_hcp[0] 470 hlp[1]=g_nsv_normed as i64 471 hlp[2]=g_nsv_mt[3] 472 hlp[3]=g_nsv_cfgA[1] 473 hlp[4]=g_nsv_lgv as i64 474 head_logits_cached_i32(hlp) 475 let sp: *i64 = sys_mmap(6*8) as *i64 476 sp[0]=g_nsv_lgv as i64 477 sp[1]=g_nsv_mt[3] 478 sp[2]=np[0] 479 sp[3]=np[1] 480 sp[4]=np[2] 481 sp[5]=np[3] 482 return nsv_sample(sp) 483} 484// decode token `tok` to text: append to the out buffer AND (if ep[3]=fd >= 0) emit one SSE frame 485// `data: {"piece":"..."}` to the stream. ep = [out, olen, ocap, fd]. Returns the new olen. 486func nsv_emit_piece(tok: i64, ep: *i64) -> i64 { 487 let out: *u8 = ep[0] as *u8 488 var olen: i64 = ep[1] 489 let ocap: i64 = ep[2] 490 let fd: i64 = ep[3] 491 let off: i64 = tk_decode_off(g_nsv_buf, g_nsv_mt[2], tok) 492 let pl: i64 = nx_gguf_meta_read_string_len(g_nsv_buf, off) 493 if pl < 1 { return olen } 494 let tmp: *u8 = sys_mmap(1024) 495 let tn: i64 = td_piece_decode(nx_gguf_meta_read_string_ptr(g_nsv_buf, off), pl, tmp, 0, 1000) 496 var i: i64 = 0 497 while i < tn { if olen < ocap { out[olen]=tmp[i]; olen=olen+1 } i = i + 1 } 498 if fd >= 0 { 499 let fr: *u8 = sys_mmap(4096) 500 var fo: i64 = nsv_cat(fr, 0, "data: {\"piece\":\"" as *u8) 501 fo = nsv_jesc(fr, fo, tmp, tn) 502 fo = nsv_cat(fr, fo, "\"}\n\n" as *u8) 503 var w: i64 = 0 504 while w < fo { let kw: i64 = sys_write(fd, ((fr as i64)+w) as *u8, fo-w); if kw <= 0 { w = fo } else { w = w + kw } } 505 } 506 return olen 507} 508 509// build a ChatML prompt id sequence into g_nsv_ids: 510// <|im_start|>user\n{content}<|im_end|>\n<|im_start|>assistant\n 511// special ids 151644 (im_start) / 151645 (im_end == NSV_EOS2) are SPLICED directly (tk_bpe_encode 512// is pure byte-BPE and would byte-encode the marker text). Everything INLINE -- no multi-data-arg 513// helper (the documented 3+-arg miscompile class). Returns nprompt (total ids). Lets the INSTRUCT 514// model see turn structure. tmpids: tk_bpe_encode writes from index 0, so encode into it then copy. 515func nsv_chatml_ids(content: *u8, clen: i64) -> i64 { 516 let base: i64 = g_nsv_ids as i64 517 var off: i64 = 0 518 // <|im_start|> 519 g_nsv_ids[off] = 151644 520 off = off + 1 521 // user\n (encode IN-PLACE into g_nsv_ids[off..] -- the proven single-call buffer) 522 let po1: i64 = base + off*8 523 let ip1: *i64 = po1 as *i64 524 let nu: i64 = tk_bpe_encode(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], "user\n" as *u8, 5, g_nsv_tokp, g_nsv_tokl, ip1) 525 off = off + nu 526 // content 527 let po2: i64 = base + off*8 528 let ip2: *i64 = po2 as *i64 529 let nc: i64 = tk_bpe_encode_b(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], content, clen, g_nsv_tokp, g_nsv_tokl, NSV_MAXIN, ip2, NSV_MAXIN + NSV_CHATML_IDS - off) 530 if nc == TK_REFUSED_TOO_LONG { return TK_REFUSED_TOO_LONG } 531 off = off + nc 532 // <|im_end|> 533 g_nsv_ids[off] = 151645 534 off = off + 1 535 // \n 536 let po3: i64 = base + off*8 537 let ip3: *i64 = po3 as *i64 538 let nn: i64 = tk_bpe_encode(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], "\n" as *u8, 1, g_nsv_tokp, g_nsv_tokl, ip3) 539 off = off + nn 540 // <|im_start|> 541 g_nsv_ids[off] = 151644 542 off = off + 1 543 // assistant\n 544 let po4: i64 = base + off*8 545 let ip4: *i64 = po4 as *i64 546 let na: i64 = tk_bpe_encode(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], "assistant\n" as *u8, 10, g_nsv_tokp, g_nsv_tokl, ip4) 547 off = off + na 548 return off 549} 550 551// THE DOOR (2026-09-17): a prompt is admitted by its BYTE length before a byte of it is tokenised. tk_bpe_encode seeds 552// one scratch slot per input byte into g_nsv_tokp and g_nsv_tokl (NSV_MAXIN entries) and writes ids unbounded, so the 553// old order (encode, then check the token count) let a 19222-byte query overrun the scratch and kill the serving 554// engine inside tk_rank_fast (reproduced on a debug build, resolved by nx_addr2line). 0 admitted, NSV_ERR_TOO_LONG refused. 555func nsv_prompt_admit(plen: i64) -> i64 { 556 if plen > NSV_MAXIN { return NSV_ERR_TOO_LONG } 557 return 0 558} 559 560// generation. gp = [prompt, plen, max_new, mode, out_text, otcap, meta, stream_fd(-1=none), 561// temp_pm(0=greedy), top_p_pm, top_k, seed, chatml(1=wrap prompt in ChatML)]. 562// meta out: [0]=n_prompt [1]=n_gen [2]=ms_total [3]=ms_per_tok [4]=eos [5]=err. returns text length (-1 on err). 563func nsv_generate(gp: *i64) -> i64 { 564 let prompt: *u8 = gp[0] as *u8 565 let plen: i64 = gp[1] 566 var max_new: i64 = gp[2] 567 let mode: i64 = gp[3] 568 let out: *u8 = gp[4] as *u8 569 let ocap: i64 = gp[5] 570 let meta: *i64 = gp[6] as *i64 571 meta[0]=0 572 meta[1]=0 573 meta[2]=0 574 meta[3]=0 575 meta[4]=0 576 meta[5]=0 577 if g_nsv_mt[6] != 1 { meta[5]=9; return 0-1 } 578 if plen < 1 { meta[5]=1; return 0-1 } 579 if nsv_prompt_admit(plen) != 0 { meta[5]=NSV_ERR_TOO_LONG; return 0-1 } 580 if max_new < 1 { max_new = 24 } 581 if max_new > NSV_MAXNEW { max_new = NSV_MAXNEW } 582 var nprompt: i64 = 0 583 if gp[12] == 1 { nprompt = nsv_chatml_ids(prompt, plen) } 584 else { nprompt = tk_bpe_encode_b(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], prompt, plen, g_nsv_tokp, g_nsv_tokl, NSV_MAXIN, g_nsv_ids, NSV_MAXIN + NSV_CHATML_IDS) } 585 if nprompt == TK_REFUSED_TOO_LONG { meta[5]=NSV_ERR_TOO_LONG; return 0-1 } 586 if nprompt < 1 { meta[5]=2; return 0-1 } 587 if nprompt >= NSV_MAXT - 2 { meta[5]=3; return 0-1 } 588 if nprompt + max_new >= NSV_MAXT { max_new = NSV_MAXT - 1 - nprompt } 589 meta[0]=nprompt 590 let ne: i64 = g_nsv_cfgA[1] 591 // sampling params (gp[8]=temp_pm 0=greedy, gp[9]=top_p_pm, gp[10]=top_k, gp[11]=seed) + stream fd (gp[7]) 592 let np: *i64 = sys_mmap(4*8) as *i64 593 let sd: *i64 = sys_mmap(8) as *i64 594 var seed: i64 = gp[11] 595 if seed == 0 { seed = 88172645463325252 } 596 sd[0]=seed 597 np[0]=gp[8] 598 np[1]=gp[9] 599 np[2]=gp[10] 600 np[3]=sd as i64 601 let ep: *i64 = sys_mmap(4*8) as *i64 602 ep[0]=out as i64 603 ep[1]=0 604 ep[2]=ocap 605 ep[3]=gp[7] 606 let t0: i64 = sys_now_ms() 607 // CACHED prefill. R0r (2026-09-17): the i8 route runs the prompt in blocks through nf_prefill_batched (one weight 608 // pass per NF_PREFILL_M positions) unless g_nsv_prefill_batched is 0; every other route runs the sequential 609 // per-token step. Both are bit-identical under causal masking (row t only ever attends 0..t) and both ride the 610 // dequant-once caches, so there is NO per-request re-dequant of the model. meta[6] carries the prefill ms. 611 var seqpre: i64 = 1 612 if mode == NSV_MODE_I8 { if g_nsv_prefill_batched == 1 { seqpre = 0 } } 613 if seqpre == 1 { nsv_prefill_seq(nprompt, mode) } else { nsv_prefill_i8_batched(nprompt) } 614 meta[6] = sys_now_ms() - t0 615 rmsnorm_gamma_row_q24(g_nsv_h1, g_nsv_gout, 0, ne, g_nsv_normed, 0) 616 var next: i64 = nsv_next_token(np) 617 var T: i64 = nprompt 618 g_nsv_ids[T]=next 619 T=T+1 620 var ngen: i64 = 1 621 var stop: i64 = 0 622 if next==NSV_EOS1 { stop=1; meta[4]=1 } 623 if next==NSV_EOS2 { stop=1; meta[4]=1 } 624 if stop == 0 { ep[1] = nsv_emit_piece(next, ep) } 625 while stop == 0 { 626 if ngen >= max_new { stop = 1 } else { if T >= NSV_MAXT { stop = 1 } else { 627 let pos: i64 = T - 1 628 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[pos], ne, g_nsv_x1, g_nsv_tmp) 629 nsv_step(pos, mode) 630 rmsnorm_gamma_row_q24(g_nsv_h1, g_nsv_gout, 0, ne, g_nsv_normed, 0) 631 next = nsv_next_token(np) 632 g_nsv_ids[T]=next 633 T=T+1 634 ngen=ngen+1 635 if next==NSV_EOS1 { stop=1; meta[4]=1 } 636 if next==NSV_EOS2 { stop=1; meta[4]=1 } 637 if meta[4] == 0 { ep[1] = nsv_emit_piece(next, ep) } 638 } } 639 } 640 let t1: i64 = sys_now_ms() 641 meta[1]=ngen 642 meta[2]=t1-t0 643 if ngen > 0 { meta[3]=(t1-t0)/(nprompt+ngen) } 644 return ep[1] 645} 646 647// ---- PREFIX-KV-CACHE (2026-07-15): the forge re-prefills a FIXED crib (~130 tok) on every task. Snapshot the 648// crib's KV rows 0..P-1 ONCE, restore them per task -> skip re-prefilling the crib (~P fewer prefill steps/task). 649// BIT-EXACT by causal masking: row t only attends 0..t, so the crib K/V are identical with or without the suffix 650// (the code already relies on this for sequential==batch prefill). Additive: the live nsv_generate is untouched. 651func nsv_kv_snapshot(P: i64) -> i64 { 652 let kvd: i64 = g_nsv_dims[6] 653 let nl: i64 = g_nsv_dims[1] 654 let per: i64 = P * kvd 655 g_nsv_kvsnap = sys_mmap(2 * nl * per * 8) as *i64 656 g_nsv_snap_p = P 657 g_nsv_crib_ids = sys_mmap(P * 8) as *i64 658 var s: i64 = 0 659 while s < P { g_nsv_crib_ids[s] = g_nsv_ids[s]; s = s + 1 } 660 var L: i64 = 0 661 while L < nl { 662 let K: *i64 = g_nsv_kvc[2*L] as *i64 663 let V: *i64 = g_nsv_kvc[2*L+1] as *i64 664 let base: i64 = (2*L) * per 665 var e: i64 = 0 666 while e < per { 667 g_nsv_kvsnap[base + e] = K[e] 668 g_nsv_kvsnap[base + per + e] = V[e] 669 e = e + 1 670 } 671 L = L + 1 672 } 673 return 0 674} 675func nsv_kv_restore() -> i64 { 676 if (g_nsv_kvsnap as i64) == 0 { return 0 - 1 } 677 let kvd: i64 = g_nsv_dims[6] 678 let nl: i64 = g_nsv_dims[1] 679 let P: i64 = g_nsv_snap_p 680 let per: i64 = P * kvd 681 var L: i64 = 0 682 while L < nl { 683 let K: *i64 = g_nsv_kvc[2*L] as *i64 684 let V: *i64 = g_nsv_kvc[2*L+1] as *i64 685 let base: i64 = (2*L) * per 686 var e: i64 = 0 687 while e < per { 688 K[e] = g_nsv_kvsnap[base + e] 689 V[e] = g_nsv_kvsnap[base + per + e] 690 e = e + 1 691 } 692 L = L + 1 693 } 694 return 0 695} 696// DISK-PERSISTED snapshot (2026-07-15): the crib KV survives process restarts -- a fresh process loads the 697// snapshot instead of re-prefilling (the WSL/daemon-restart pattern). Format: [P][nl][kvd] then crib ids 698// (P i64) then per-layer K rows then V rows (P*kvd i64 each). Load fail-safe: any dim mismatch -> -1, caller 699// falls back to full prefill (never a wrong cache). 700func nsv_kv_snapshot_save(path: *u8) -> i64 { 701 if (g_nsv_kvsnap as i64) == 0 { return 0 - 1 } 702 let kvd: i64 = g_nsv_dims[6] 703 let nl: i64 = g_nsv_dims[1] 704 let P: i64 = g_nsv_snap_p 705 let per: i64 = P * kvd 706 let fd: i64 = sys_openat_wr(path, 0x1a4) 707 if fd < 0 { return 0 - 2 } 708 let hdrb: *i64 = sys_mmap(3*8) as *i64 709 hdrb[0] = P 710 hdrb[1] = nl 711 hdrb[2] = kvd 712 sys_write(fd, hdrb as *u8, 24) 713 sys_write(fd, g_nsv_crib_ids as *u8, P*8) 714 sys_write(fd, g_nsv_kvsnap as *u8, 2*nl*per*8) 715 sys_close(fd) 716 return 0 717} 718func nsv_kv_snapshot_load(path: *u8) -> i64 { 719 let kvd: i64 = g_nsv_dims[6] 720 let nl: i64 = g_nsv_dims[1] 721 let fd: i64 = sys_openat_rd(path) 722 if fd < 0 { return 0 - 1 } 723 let hdrb: *i64 = sys_mmap(3*8) as *i64 724 if sys_read(fd, hdrb as *u8, 24) != 24 { sys_close(fd); return 0 - 2 } 725 let P: i64 = hdrb[0] 726 if P < 1 { sys_close(fd); return 0 - 3 } 727 if P >= NSV_MAXT { sys_close(fd); return 0 - 3 } 728 if hdrb[1] != nl { sys_close(fd); return 0 - 4 } 729 if hdrb[2] != kvd { sys_close(fd); return 0 - 4 } 730 let per: i64 = P * kvd 731 g_nsv_crib_ids = sys_mmap(P*8) as *i64 732 g_nsv_kvsnap = sys_mmap(2*nl*per*8) as *i64 733 var need: i64 = P*8 734 var got: i64 = 0 735 var q: *u8 = g_nsv_crib_ids as *u8 736 while got < need { let r: i64 = sys_read(fd, (q as i64 + got) as *u8, need - got); if r <= 0 { sys_close(fd); return 0 - 5 } got = got + r } 737 need = 2*nl*per*8 738 got = 0 739 q = g_nsv_kvsnap as *u8 740 while got < need { let r2: i64 = sys_read(fd, (q as i64 + got) as *u8, need - got); if r2 <= 0 { sys_close(fd); return 0 - 5 } got = got + r2 } 741 sys_close(fd) 742 g_nsv_snap_p = P 743 return P 744} 745 746// nsv_generate with prefix-KV-cache. prefix_len = # prompt tokens shared with the snapshot; use_snap: 0 = prefill 747// all + snapshot rows 0..prefix_len-1; 1 = restore the snapshot + prefill only [prefix_len..nprompt). Requires 748// prefix_len < nprompt when use_snap==1 (a suffix must exist). Everything after prefill is byte-identical to 749// nsv_generate (same decode, sampling, emit) -> the OUTPUT must match nsv_generate exactly (the gate proves it). 750func nsv_generate_pfx(gp: *i64, prefix_len: i64, use_snap: i64) -> i64 { 751 let prompt: *u8 = gp[0] as *u8 752 let plen: i64 = gp[1] 753 var max_new: i64 = gp[2] 754 let mode: i64 = gp[3] 755 let out: *u8 = gp[4] as *u8 756 let ocap: i64 = gp[5] 757 let meta: *i64 = gp[6] as *i64 758 meta[0]=0 759 meta[1]=0 760 meta[2]=0 761 meta[3]=0 762 meta[4]=0 763 meta[5]=0 764 if g_nsv_mt[6] != 1 { meta[5]=9; return 0-1 } 765 if plen < 1 { meta[5]=1; return 0-1 } 766 if nsv_prompt_admit(plen) != 0 { meta[5]=NSV_ERR_TOO_LONG; return 0-1 } 767 if max_new < 1 { max_new = 24 } 768 if max_new > NSV_MAXNEW { max_new = NSV_MAXNEW } 769 var nprompt: i64 = 0 770 if gp[12] == 1 { nprompt = nsv_chatml_ids(prompt, plen) } 771 else { nprompt = tk_bpe_encode_b(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], prompt, plen, g_nsv_tokp, g_nsv_tokl, NSV_MAXIN, g_nsv_ids, NSV_MAXIN + NSV_CHATML_IDS) } 772 if nprompt == TK_REFUSED_TOO_LONG { meta[5]=NSV_ERR_TOO_LONG; return 0-1 } 773 if nprompt < 1 { meta[5]=2; return 0-1 } 774 if nprompt >= NSV_MAXT - 2 { meta[5]=3; return 0-1 } 775 if nprompt + max_new >= NSV_MAXT { max_new = NSV_MAXT - 1 - nprompt } 776 meta[0]=nprompt 777 let ne: i64 = g_nsv_cfgA[1] 778 let np: *i64 = sys_mmap(4*8) as *i64 779 let sd: *i64 = sys_mmap(8) as *i64 780 var seed: i64 = gp[11] 781 if seed == 0 { seed = 88172645463325252 } 782 sd[0]=seed 783 np[0]=gp[8] 784 np[1]=gp[9] 785 np[2]=gp[10] 786 np[3]=sd as i64 787 let ep: *i64 = sys_mmap(4*8) as *i64 788 ep[0]=out as i64 789 ep[1]=0 790 ep[2]=ocap 791 ep[3]=gp[7] 792 let t0: i64 = sys_now_ms() 793 // no-snapshot fallback: use_snap=1 with no prior snapshot degrades to a full prefill (never crashes) 794 var us: i64 = use_snap 795 if us == 1 { if (g_nsv_kvsnap as i64) == 0 { us = 0 } } 796 var i: i64 = 0 797 if us == 1 { 798 nsv_kv_restore() 799 // BOUNDARY-SAFE: only the token rows that ACTUALLY match the snapshotted crib are trusted; the first 800 // divergent token (BPE may re-tokenize the crib/task seam) and everything after is re-prefilled fresh. 801 var cp: i64 = 0 802 var go: i64 = 1 803 while go == 1 { 804 if cp >= g_nsv_snap_p { go = 0 } 805 else { if cp >= nprompt { go = 0 } 806 else { if g_nsv_ids[cp] == g_nsv_crib_ids[cp] { cp = cp + 1 } else { go = 0 } } } 807 } 808 // stale-h1 guard: if the snapshot covers the WHOLE prompt (identical prompt, e.g. best-of-N resample), 809 // still re-run the LAST prompt token so g_nsv_h1 is the state after token nprompt-1, not a stale gen state. 810 // Rewriting KV row nprompt-1 with the same values is harmless; skipping it leaves h1 wrong. 811 if cp >= nprompt { cp = nprompt - 1 } 812 i = cp 813 } 814 while i < nprompt { 815 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[i], ne, g_nsv_x1, g_nsv_tmp) 816 nsv_step(i, mode) 817 i = i + 1 818 } 819 if us == 0 { 820 var snl: i64 = prefix_len 821 if snl > nprompt { snl = nprompt } 822 if snl > 0 { nsv_kv_snapshot(snl) } 823 } 824 rmsnorm_gamma_row_q24(g_nsv_h1, g_nsv_gout, 0, ne, g_nsv_normed, 0) 825 var next: i64 = nsv_next_token(np) 826 var T: i64 = nprompt 827 g_nsv_ids[T]=next 828 T=T+1 829 var ngen: i64 = 1 830 var stop: i64 = 0 831 if next==NSV_EOS1 { stop=1; meta[4]=1 } 832 if next==NSV_EOS2 { stop=1; meta[4]=1 } 833 if stop == 0 { ep[1] = nsv_emit_piece(next, ep) } 834 while stop == 0 { 835 if ngen >= max_new { stop = 1 } else { if T >= NSV_MAXT { stop = 1 } else { 836 let pos: i64 = T - 1 837 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[pos], ne, g_nsv_x1, g_nsv_tmp) 838 nsv_step(pos, mode) 839 rmsnorm_gamma_row_q24(g_nsv_h1, g_nsv_gout, 0, ne, g_nsv_normed, 0) 840 next = nsv_next_token(np) 841 g_nsv_ids[T]=next 842 T=T+1 843 ngen=ngen+1 844 if next==NSV_EOS1 { stop=1; meta[4]=1 } 845 if next==NSV_EOS2 { stop=1; meta[4]=1 } 846 if meta[4] == 0 { ep[1] = nsv_emit_piece(next, ep) } 847 } } 848 } 849 let t1: i64 = sys_now_ms() 850 meta[1]=ngen 851 meta[2]=t1-t0 852 if ngen > 0 { meta[3]=(t1-t0)/(nprompt+ngen) } 853 return ep[1] 854} 855 856// ---- GPU ORACLE socket client (e4) -- ⚠BENCH LANE ONLY, NEVER THE RUN LANE (operator law 857// 2026-07-15: "sovereign from the hardware first byte up"; C/libcuda = benchmark oracle like 858// WARP/fxc/gcc). mode 2 is invoked ONLY by in-process gates (nx_gpu_embed_gate) to grade the 859// sovereign CPU path against the resident-weight GPU oracle; the daemon HTTP surface cannot 860// select it. The production /embed and /gen paths are 100%-sovereign CPU until the NishiLang 861// GPU driver (#22) exists. Protocol per token: send [pos=-(i+1):i64][x1: ne i64] -> 862// recv [normed: ne i64]. NO silent fallback: absent oracle = a loud error. 863func nsv_gwall(fd: i64, buf: *u8, count: i64) -> i64 { 864 var off: i64 = 0 865 while off < count { 866 let q: *u8 = buf + off 867 let w: i64 = sys_write(fd, q, count - off) 868 if w <= 0 { return 0 - 1 } 869 off = off + w 870 } 871 return 0 872} 873 874func nsv_grall(fd: i64, buf: *u8, count: i64) -> i64 { 875 var off: i64 = 0 876 while off < count { 877 let q: *u8 = buf + off 878 let r: i64 = sys_read(fd, q, count - off) 879 if r <= 0 { return 0 - 1 } 880 off = off + r 881 } 882 return 0 883} 884 885func nsv_gpu_connect() -> i64 { 886 let fd: i64 = sys_socket(1, 1, 0) 887 if fd < 0 { return 0 - 1 } 888 let sa: *u8 = sys_mmap(128) as *u8 889 sa[0] = 1 as u8 890 sa[1] = 0 as u8 891 let path: *u8 = "/home/elderwesto/nx_stage/nx_gpu.sock" as *u8 892 var i: i64 = 0 893 while path[i] != (0 as u8) { sa[2 + i] = path[i]; i = i + 1 } 894 let cr: i64 = sys_connect(fd, sa, 110) 895 if cr < 0 { sys_close(fd); return 0 - 2 } 896 return fd 897} 898 899// EMBEDDING (jina-code-embeddings recipe, arXiv:2508.21290): a code/text embedding is the LAST-TOKEN 900// pooled FINAL-NORM hidden state == exactly g_nsv_normed after the sequential prefill. No ChatML, no 901// generation -- the caller prepends the task instruction prefix (nl2code/qa/code2code/...) to the text. 902// Fresh sequence by construction: prefill restarts at pos=0 (KV rows 0..n-1 overwritten; causal attention 903// never reads beyond pos -> no state leak between embeds; same semantics as the GPU serve pos==0). 904// outvec receives ne i64s (Q24 scale). Returns n_prompt_tokens (>0) or negative error. 905func nsv_embed(text: *u8, tlen: i64, mode: i64, outvec: *i64) -> i64 { 906 if g_nsv_mt[6] != 1 { return 0-9 } 907 if tlen < 1 { return 0-1 } 908 if nsv_prompt_admit(tlen) != 0 { return 0-3 } 909 let nprompt: i64 = tk_bpe_encode_b(g_nsv_buf, g_nsv_mt[0], g_nsv_mt[1], g_nsv_mt[2], g_nsv_mt[3], text, tlen, g_nsv_tokp, g_nsv_tokl, NSV_MAXIN, g_nsv_ids, NSV_MAXIN + NSV_CHATML_IDS) 910 if nprompt == TK_REFUSED_TOO_LONG { return 0-3 } 911 if nprompt < 1 { return 0-2 } 912 if nprompt >= NSV_MAXT - 2 { return 0-3 } 913 let ne: i64 = g_nsv_cfgA[1] 914 if mode == 2 { 915 // GPU backend: forward+norm run on the resident-weight server, bit-exact vs the CPU i8 path 916 // (gate nx_gpu_embed_gate). Reply lands directly in outvec; the last token's reply stays. 917 let gs: i64 = nsv_gpu_connect() 918 if gs < 0 { return 0 - 10 } 919 let posb: *i64 = sys_mmap(8) as *i64 920 var k: i64 = 0 921 while k < nprompt { 922 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[k], ne, g_nsv_x1, g_nsv_tmp) 923 posb[0] = 0 - (k + 1) 924 if nsv_gwall(gs, posb as *u8, 8) != 0 { sys_close(gs); return 0 - 11 } 925 if nsv_gwall(gs, g_nsv_x1 as *u8, ne * 8) != 0 { sys_close(gs); return 0 - 11 } 926 if nsv_grall(gs, outvec as *u8, ne * 8) != 0 { sys_close(gs); return 0 - 12 } 927 k = k + 1 928 } 929 sys_close(gs) 930 return nprompt 931 } 932 var i: i64 = 0 933 while i < nprompt { 934 dequant_row(g_nsv_buf, g_nsv_mt[4], g_nsv_mt[5], g_nsv_ids[i], ne, g_nsv_x1, g_nsv_tmp) 935 nsv_step(i, mode) 936 i = i + 1 937 } 938 rmsnorm_gamma_row_q24(g_nsv_h1, g_nsv_gout, 0, ne, g_nsv_normed, 0) 939 var j: i64 = 0 940 while j < ne { outvec[j] = g_nsv_normed[j]; j = j + 1 } 941 return nprompt 942} 943 944// ---- HTTP layer (in-process; the daemon shell only moves bytes) ---- 945func nsv_resp(resb: *u8, rescap: i64, code: i64, ctype: *u8, body: *u8, blen: i64) -> i64 { 946 var o: i64 = 0 947 o = nsv_cat(resb, o, "HTTP/1.1 " as *u8) 948 o = nsv_catn(resb, o, code) 949 if code == 200 { o = nsv_cat(resb, o, " OK" as *u8) } else { o = nsv_cat(resb, o, " X" as *u8) } 950 o = nsv_cat(resb, o, "\r\nContent-Type: " as *u8) 951 o = nsv_cat(resb, o, ctype) 952 o = nsv_cat(resb, o, "\r\nContent-Length: " as *u8) 953 o = nsv_catn(resb, o, blen) 954 o = nsv_cat(resb, o, "\r\nConnection: close\r\n\r\n" as *u8) 955 if o + blen < rescap { o = nsv_catb(resb, o, body, blen) } 956 return o 957} 958// JSON-escape ONE byte into dst at o; returns new o (early-return ladder -- no else-chains). 959func nsv_jesc1(dst: *u8, o: i64, c: i64) -> i64 { 960 if c == 34 { dst[o]=92 as u8; dst[o+1]=34 as u8; return o+2 } 961 if c == 92 { dst[o]=92 as u8; dst[o+1]=92 as u8; return o+2 } 962 if c == 10 { dst[o]=92 as u8; dst[o+1]=110 as u8; return o+2 } 963 if c == 13 { dst[o]=92 as u8; dst[o+1]=114 as u8; return o+2 } 964 if c == 9 { dst[o]=92 as u8; dst[o+1]=116 as u8; return o+2 } 965 if c < 32 { dst[o]=32 as u8; return o+1 } 966 dst[o]=c as u8 967 return o+1 968} 969// JSON-escape src[0,n) into dst at off 970func nsv_jesc(dst: *u8, off: i64, src: *u8, n: i64) -> i64 { 971 var o: i64 = off 972 var i: i64 = 0 973 while i < n { o = nsv_jesc1(dst, o, src[i] & 0xff); i = i + 1 } 974 return o 975} 976// find "key": in body[0,n); return index just after the colon, -1 if absent. 977func nsv_jkey(body: *u8, n: i64, key: *u8) -> i64 { 978 let kl: i64 = nsv_slen(key) 979 var i: i64 = 0 980 while i + kl + 3 < n { 981 if body[i] == (34 as u8) { 982 var k: i64 = 0 983 var ok: i64 = 1 984 while k < kl { if body[i+1+k] != key[k] { ok = 0; k = kl } else { k = k + 1 } } 985 if ok == 1 { if body[i+1+kl] == (34 as u8) { 986 var j: i64 = i + 2 + kl 987 while j < n { if body[j] == (58 as u8) { return j + 1 } if body[j] == (34 as u8) { j = n } else { j = j + 1 } } 988 } } 989 } 990 i = i + 1 991 } 992 return 0 - 1 993} 994// extract a JSON string value starting at/after p (skips ws to the opening quote); unescapes into dst; returns len (-1 if absent). 995func nsv_jstr(body: *u8, n: i64, p: i64, dst: *u8, dcap: i64) -> i64 { 996 var i: i64 = p 997 while i < n { if body[i] == (34 as u8) { i = i + 1; var o: i64 = 0 998 while i < n { 999 let c: i64 = body[i] & 0xff 1000 if c == 34 { return o } 1001 if c == 92 { if i + 1 < n { 1002 let e: i64 = body[i+1] & 0xff 1003 var w: i64 = e 1004 if e == 110 { w = 10 } 1005 if e == 116 { w = 9 } 1006 if e == 114 { w = 13 } 1007 if o < dcap { dst[o] = w as u8; o = o + 1 } 1008 i = i + 2 1009 } else { i = i + 1 } } else { 1010 if o < dcap { dst[o] = c as u8; o = o + 1 } 1011 i = i + 1 1012 } 1013 } 1014 return 0 - 1 1015 } 1016 if body[i] == (32 as u8) { i = i + 1 } else { if body[i] == (9 as u8) { i = i + 1 } else { return 0 - 1 } } 1017 } 1018 return 0 - 1 1019} 1020// extract a JSON integer at/after p; returns value (def if absent). 1021func nsv_jint(body: *u8, n: i64, p: i64, def: i64) -> i64 { 1022 if p < 0 { return def } 1023 var i: i64 = p 1024 var skipping: i64 = 1 1025 while skipping == 1 { 1026 if i >= n { skipping = 0 } else { 1027 if body[i] == (32 as u8) { i = i + 1 } else { skipping = 0 } 1028 } 1029 } 1030 var v: i64 = 0 1031 var any: i64 = 0 1032 var going: i64 = 1 1033 while going == 1 { 1034 if i >= n { going = 0 } else { 1035 let c: i64 = body[i] & 0xff 1036 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; i = i + 1 } else { going = 0 } } else { going = 0 } 1037 } 1038 } 1039 if any == 0 { return def } 1040 return v 1041} 1042 1043// the app page: served at GET /. NOTE: NishiLang literals cannot carry the two banned bytes, so the page uses 1044// rgb() colors, class selectors and no doctype -- functional, clean, dark. 1045func nsv_page(dst: *u8, cap: i64) -> i64 { 1046 var o: i64 = 0 1047 o = nsv_cat(dst, o, "<html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nishi No-Float LLM</title><style>body{font-family:system-ui,Segoe UI,Roboto,sans-serif;background:rgb(16,17,22);color:rgb(226,228,235);max-width:760px;margin:4vh auto;padding:0 20px;line-height:1.55}h1{font-size:1.4rem;margin-bottom:.2rem}p.sub{color:rgb(150,155,170);font-size:.9rem;margin-top:0}textarea{width:100%;min-height:90px;background:rgb(28,30,38);color:rgb(230,232,240);border:1px solid rgb(60,63,75);border-radius:8px;padding:10px;font-size:1rem;box-sizing:border-box}select,input{background:rgb(28,30,38);color:rgb(230,232,240);border:1px solid rgb(60,63,75);border-radius:6px;padding:6px 8px}button{background:rgb(58,110,235);color:white;border:none;border-radius:8px;padding:9px 18px;font-size:1rem;cursor:pointer}button:disabled{opacity:.5}.row{display:flex;gap:10px;align-items:center;margin:10px 0;flex-wrap:wrap}.out{white-space:pre-wrap;background:rgb(24,26,33);border:1px solid rgb(55,58,70);border-radius:8px;padding:12px;min-height:60px;margin-top:8px;font-size:1.02rem}.st{color:rgb(140,200,150);font-size:.85rem;min-height:1.2em}.ft{margin-top:2rem;color:rgb(120,124,138);font-size:.78rem}</style></head><body><h1>Nishi No-Float LLM</h1><p class=\"sub\">Qwen2.5-0.5B-Instruct on the sovereign 100 percent integer inference stack. Deterministic: same prompt, same bytes.</p><textarea class=\"pr\" placeholder=\"Type a prompt...\">The capital of France is</textarea><div class=\"row\"><label>tokens <input class=\"mn\" type=\"number\" value=\"24\" min=\"1\" max=\"96\" style=\"width:70px\"></label><label>mode <select class=\"md\"><option value=\"i32\">i32 lossless</option><option value=\"i8\">i8 fast</option></select></label><label>temp <select class=\"tp\"><option value=\"0\">0 (greedy, bit-exact)</option><option value=\"700\">0.7</option><option value=\"800\">0.8</option><option value=\"1000\">1.0</option><option value=\"1200\">1.2</option></select></label><label>seed <input class=\"sd\" type=\"number\" value=\"12345\" style=\"width:90px\"></label><button class=\"go\" onclick=\"go()\">Generate</button></div><div class=\"st\"></div><div class=\"out\"></div><div class=\"ft\">endpoints: POST /gen · GET /health · GET /api — served by nx_nofloat_serve (no gcc, no python, no float)</div><script>async function go(){var b=document.querySelector('.go');var st=document.querySelector('.st');var out=document.querySelector('.out');var t=document.querySelector('.pr').value;var mn=parseInt(document.querySelector('.mn').value);var md=document.querySelector('.md').value;var tp=parseInt(document.querySelector('.tp').value);var sd=parseInt(document.querySelector('.sd').value);b.disabled=true;st.textContent='thinking...';out.textContent=t;try{var r=await fetch('/gen',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:t,max_new:mn,mode:md,temp:tp,seed:sd,stream:1})});var rd=r.body.getReader();var dec=new TextDecoder();var acc='';var SEP=String.fromCharCode(10)+String.fromCharCode(10);var going=true;while(going){var ch=await rd.read();if(ch.done){going=false}else{acc=acc+dec.decode(ch.value,{stream:true});var parts=acc.split(SEP);acc=parts.pop();for(var pi=0;pi<parts.length;pi=pi+1){var ln=parts[pi];if(ln.indexOf('data: ')==0){var j=JSON.parse(ln.slice(6));if(j.piece){out.textContent=out.textContent+j.piece}if(j.done==1){if(j.ok==1){st.textContent=j.gen_tokens+' tokens · '+j.ms_per_token+' ms/token · '+md+(tp>0?' · temp '+(tp/1000)+' seed '+sd:' · greedy')+(j.eos==1?' · eos':'')}else{st.textContent='error '+j.err}}}}}}}catch(e){st.textContent='request failed: '+e}b.disabled=false;}</script></body></html>" as *u8) 1048 return o 1049} 1050 1051// parse a POST /gen request body into gp: [0]=prompt [1]=plen [2]=max_new [3]=mode(0=i32,1=i8) 1052// [8]=temp_pm(0=greedy) [9]=top_p_pm [10]=top_k [11]=seed [12]=stream(0/1). 0 ok, -1 bad. 1053func nsv_parse_gen(req: *u8, rn: i64, gp: *i64) -> i64 { 1054 var hb: i64 = 0 - 1 1055 var i: i64 = 0 1056 while i + 3 < rn { 1057 if req[i]==(13 as u8) { if req[i+1]==(10 as u8) { if req[i+2]==(13 as u8) { if req[i+3]==(10 as u8) { hb = i + 4; i = rn } } } } 1058 i = i + 1 1059 } 1060 if hb < 0 { return 0 - 1 } 1061 let bb: *u8 = ((req as i64) + hb) as *u8 1062 let bn: i64 = rn - hb 1063 let prompt: *u8 = sys_mmap(32768) 1064 let kp: i64 = nsv_jkey(bb, bn, "prompt" as *u8) 1065 var pl2: i64 = 0 - 1 1066 if kp >= 0 { pl2 = nsv_jstr(bb, bn, kp, prompt, 32760) } 1067 if pl2 < 1 { return 0 - 1 } 1068 gp[0]=prompt as i64 1069 gp[1]=pl2 1070 gp[2]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "max_new" as *u8), 24) 1071 // mode: default is the route whose caches this serve actually built -- a resident-Q4_K serve has NO i32/i16 1072 // layer cache, so an explicit i32/i8 there is REFUSED (400) rather than dereferencing an absent cache; and 1073 // "q4k" on a serve that did not build the slot tables is refused the same way. 1074 var mode: i64 = NSV_MODE_I32 1075 if g_nsv_q4k == 1 { mode = NSV_MODE_Q4K } 1076 // an i8-only serve (nsv_init_i8: no i32 cache) defaults to i8 and REFUSES an explicit i32 -- mode 0 there would 1077 // read the absent cache (2026-09-16, the LAN rewrite engine runs i8-only beside other jobs in a 16 GB VM) 1078 if g_nsv_i8only == 1 { if g_nsv_q4k == 0 { mode = NSV_MODE_I8 } } 1079 let kd: i64 = nsv_jkey(bb, bn, "mode" as *u8) 1080 if kd >= 0 { 1081 let ms: *u8 = sys_mmap(16) 1082 let ml: i64 = nsv_jstr(bb, bn, kd, ms, 8) 1083 if ml == 2 { if ms[0]==(105 as u8) { if ms[1]==(56 as u8) { mode = NSV_MODE_I8 } } } 1084 if ml == 3 { if ms[0]==(105 as u8) { if ms[1]==(51 as u8) { if ms[2]==(50 as u8) { mode = NSV_MODE_I32 } } } } 1085 if ml == 3 { if ms[0]==(113 as u8) { if ms[1]==(52 as u8) { if ms[2]==(107 as u8) { mode = NSV_MODE_Q4K } } } } 1086 if ml == 2 { if ms[0]==(113 as u8) { if ms[1]==(56 as u8) { mode = NSV_MODE_Q4K } } } // "q8": the resident lane over a Q8_0 gguf (search R0s) 1087 if g_nsv_q4k == 1 { if mode != NSV_MODE_Q4K { return 0 - 1 } } 1088 if g_nsv_q4k == 0 { if mode == NSV_MODE_Q4K { return 0 - 1 } } 1089 if g_nsv_i8only == 1 { if mode == NSV_MODE_I32 { return 0 - 1 } } 1090 } 1091 gp[3]=mode 1092 gp[8]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "temp" as *u8), 0) 1093 gp[9]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "top_p" as *u8), 950) 1094 gp[10]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "top_k" as *u8), 64) 1095 gp[11]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "seed" as *u8), 12345) 1096 // SLOT-COLLISION FIX (2026-07-15): "stream" used to land in gp[12], but the forge-era nsv_generate 1097 // contract made gp[12] = CHATML -- so every streamed request silently chatml-wrapped (caught by the 1098 // serve gate T6: streamed 'The capital of France is' returned chat-'Paris', 13 prompt tokens, not the 1099 // raw ' Paris' continuation, 5 tokens). Streaming discriminator now gp[13]; gp[12] = the EXPLICIT 1100 // "chat" body key (default 0 = raw) -- both transports get both behaviors, explicitly. 1101 gp[12]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "chat" as *u8), 0) 1102 gp[13]=nsv_jint(bb, bn, nsv_jkey(bb, bn, "stream" as *u8), 0) 1103 return 0 1104} 1105// jina-code-embeddings task instruction prefixes (VERBATIM from the jina-code-embeddings-0.5b model card / 1106// arXiv:2508.21290 -- protocol constants, cited not invented). Task selected by (len, first byte): 1107// qa=2, code2code=9, code2completion=15, code2nl=7+'c', default nl2code. kq=1 -> query prefix, else passage. 1108func nsv_embed_prefix(task: *u8, tl: i64, kq: i64) -> *u8 { 1109 if tl == 2 { 1110 if kq == 1 { return "Find the most relevant answer given the following question:\n" as *u8 } 1111 return "Candidate answer:\n" as *u8 1112 } 1113 if tl == 9 { 1114 if kq == 1 { return "Find an equivalent code snippet given the following code snippet:\n" as *u8 } 1115 return "Candidate code snippet:\n" as *u8 1116 } 1117 if tl == 15 { 1118 if kq == 1 { return "Find the most relevant completion given the following start of code snippet:\n" as *u8 } 1119 return "Candidate completion:\n" as *u8 1120 } 1121 if tl == 7 { if task[0] == (99 as u8) { 1122 if kq == 1 { return "Find the most relevant comment given the following code snippet:\n" as *u8 } 1123 return "Candidate comment:\n" as *u8 1124 } } 1125 if kq == 1 { return "Find the most relevant code snippet given the following query:\n" as *u8 } 1126 return "Candidate code snippet:\n" as *u8 1127} 1128 1129// parse POST /embed body {"text","task","kind","mode"} -> ep: [0]=text ptr [1]=text len [2]=mode(1=i8 default) 1130// [3]=kind_q(1=query default) [4]=task ptr [5]=task len (0 = default nl2code). 0 ok, -1 bad (text required). 1131func nsv_parse_embed(req: *u8, rn: i64, ep: *i64) -> i64 { 1132 var hb: i64 = 0 - 1 1133 var i: i64 = 0 1134 while i + 3 < rn { 1135 if req[i]==(13 as u8) { if req[i+1]==(10 as u8) { if req[i+2]==(13 as u8) { if req[i+3]==(10 as u8) { hb = i + 4; i = rn } } } } 1136 i = i + 1 1137 } 1138 if hb < 0 { return 0 - 1 } 1139 let bb: *u8 = ((req as i64) + hb) as *u8 1140 let bn: i64 = rn - hb 1141 let text: *u8 = sys_mmap(8192) 1142 let kt: i64 = nsv_jkey(bb, bn, "text" as *u8) 1143 var tl: i64 = 0 - 1 1144 if kt >= 0 { tl = nsv_jstr(bb, bn, kt, text, 8100) } 1145 if tl < 1 { return 0 - 1 } 1146 ep[0]=text as i64 1147 ep[1]=tl 1148 var mode: i64 = 1 1149 let kd: i64 = nsv_jkey(bb, bn, "mode" as *u8) 1150 if kd >= 0 { 1151 let ms: *u8 = sys_mmap(16) 1152 let ml: i64 = nsv_jstr(bb, bn, kd, ms, 8) 1153 // NOTE: mode 2 (GPU oracle) is BENCH-ONLY and deliberately NOT reachable from the HTTP 1154 // surface -- the run lane is sovereign CPU end-to-end (operator law 2026-07-15: C/libcuda 1155 // = benchmark oracle, never the run lane). Gates drive mode 2 in-process. 1156 if ml == 3 { mode = 0 } 1157 } 1158 ep[2]=mode 1159 var kq: i64 = 1 1160 let kk: i64 = nsv_jkey(bb, bn, "kind" as *u8) 1161 if kk >= 0 { 1162 let ks: *u8 = sys_mmap(16) 1163 let kl: i64 = nsv_jstr(bb, bn, kk, ks, 12) 1164 if kl > 0 { if ks[0]==(112 as u8) { kq = 0 } } 1165 } 1166 ep[3]=kq 1167 let task: *u8 = sys_mmap(32) 1168 var tkl: i64 = 0 1169 let kta: i64 = nsv_jkey(bb, bn, "task" as *u8) 1170 if kta >= 0 { 1171 let r: i64 = nsv_jstr(bb, bn, kta, task, 24) 1172 if r > 0 { tkl = r } 1173 } 1174 ep[4]=task as i64 1175 ep[5]=tkl 1176 return 0 1177} 1178 1179// STREAMING route: if the request is POST /gen with "stream":1, serve it as Server-Sent Events DIRECTLY on 1180// fd (headers -> start frame -> one data frame per token from nsv_generate -> done frame with meta) and 1181// return 1. Any other request returns 0 (caller falls through to the buffered nsv_handle). The daemon calls 1182// this FIRST; the gate drives it with a file fd -- same bytes either way. 1183func nsv_handle_stream(fd: i64, req: *u8, rn: i64) -> i64 { 1184 var is_post: i64 = 0 1185 if rn > 5 { if req[0]==(80 as u8) { is_post = 1 } } 1186 if is_post == 0 { return 0 } 1187 if req[6] != (103 as u8) { return 0 } 1188 let gp: *i64 = sys_mmap(16*8) as *i64 1189 let prc: i64 = nsv_parse_gen(req, rn, gp) 1190 if prc != 0 { return 0 } 1191 if gp[13] != 1 { return 0 } 1192 let hdrs: *u8 = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nCache-Control: no-cache\r\nConnection: close\r\n\r\n" as *u8 1193 var hl: i64 = nsv_slen(hdrs) 1194 var w: i64 = 0 1195 while w < hl { let k1: i64 = sys_write(fd, ((hdrs as i64)+w) as *u8, hl-w); if k1 <= 0 { w = hl } else { w = w + k1 } } 1196 let text: *u8 = sys_mmap(65536) 1197 let meta: *i64 = sys_mmap(8*8) as *i64 1198 gp[4]=text as i64 1199 gp[5]=65000 1200 gp[6]=meta as i64 1201 gp[7]=fd 1202 let tl: i64 = nsv_generate(gp) 1203 let fin: *u8 = sys_mmap(1024) 1204 var fo: i64 = 0 1205 if tl < 0 { 1206 fo = nsv_cat(fin, 0, "data: {\"done\":1,\"ok\":0,\"err\":" as *u8) 1207 fo = nsv_catn(fin, fo, meta[5]) 1208 fo = nsv_cat(fin, fo, "}\n\n" as *u8) 1209 } else { 1210 fo = nsv_cat(fin, 0, "data: {\"done\":1,\"ok\":1,\"prompt_tokens\":" as *u8) 1211 fo = nsv_catn(fin, fo, meta[0]) 1212 fo = nsv_cat(fin, fo, ",\"gen_tokens\":" as *u8) 1213 fo = nsv_catn(fin, fo, meta[1]) 1214 fo = nsv_cat(fin, fo, ",\"ms_per_token\":" as *u8) 1215 fo = nsv_catn(fin, fo, meta[3]) 1216 fo = nsv_cat(fin, fo, ",\"prefill_ms\":" as *u8) 1217 fo = nsv_catn(fin, fo, meta[6]) 1218 fo = nsv_cat(fin, fo, ",\"eos\":" as *u8) 1219 fo = nsv_catn(fin, fo, meta[4]) 1220 fo = nsv_cat(fin, fo, "}\n\n" as *u8) 1221 } 1222 w = 0 1223 while w < fo { let k2: i64 = sys_write(fd, ((fin as i64)+w) as *u8, fo-w); if k2 <= 0 { w = fo } else { w = w + k2 } } 1224 return 1 1225} 1226 1227// route + serve one request. returns response length in resb. 1228func nsv_handle(req: *u8, rn: i64, resb: *u8, rescap: i64) -> i64 { 1229 let body: *u8 = sys_mmap(65536) 1230 var blen: i64 = 0 1231 // method + path 1232 var is_get: i64 = 0 1233 var is_post: i64 = 0 1234 if rn > 4 { if req[0]==(71 as u8) { is_get=1 } } 1235 if rn > 5 { if req[0]==(80 as u8) { is_post=1 } } 1236 var ps: i64 = 4 1237 if is_post == 1 { ps = 5 } 1238 var pe: i64 = ps 1239 var scanning: i64 = 1 1240 while scanning == 1 { 1241 if pe >= rn { scanning = 0 } else { 1242 if req[pe]==(32 as u8) { scanning = 0 } else { pe = pe + 1 } 1243 } 1244 } 1245 let plen: i64 = pe - ps 1246 // GET / 1247 if is_get == 1 { if plen == 1 { if req[ps]==(47 as u8) { 1248 let page: *u8 = sys_mmap(16384) 1249 let pn: i64 = nsv_page(page, 16384) 1250 return nsv_resp(resb, rescap, 200, "text/html; charset=utf-8" as *u8, page, pn) 1251 } } } 1252 // GET /health 1253 if is_get == 1 { if plen == 7 { if req[ps+1]==(104 as u8) { 1254 var o: i64 = 0 1255 o = nsv_cat(body, o, "{\"ok\":" as *u8) 1256 o = nsv_catn(body, o, g_nsv_mt[6]) 1257 o = nsv_cat(body, o, ",\"model\":\"" as *u8) 1258 o = nsv_jesc(body, o, g_nsv_mpath, nsv_slen(g_nsv_mpath)) 1259 if g_nsv_q4k == 1 { o = nsv_cat(body, o, "\",\"modes\":[\"q4k\"],\"route\":\"q4k-resident\",\"maxt\":" as *u8) } else { 1260 o = nsv_cat(body, o, "\",\"modes\":[\"i32\",\"i8\"],\"route\":\"dequant-once-i32+i8\",\"maxt\":" as *u8) } 1261 o = nsv_catn(body, o, NSV_MAXT) 1262 o = nsv_cat(body, o, ",\"init_ms\":" as *u8) 1263 o = nsv_catn(body, o, g_nsv_mt[7]) 1264 if g_nsv_q4k == 1 { 1265 // per-route decode profile (cumulative since init; diff two reads around one generation): where a token's 1266 // time goes is a measurement here, never a guess in a seat 1267 o = nsv_cat(body, o, ",\"prof\":{\"q4k_gemm_ns\":" as *u8); o = nsv_catn(body, o, nq_prof_get(NQ_PROF_Q4K_NS)) 1268 o = nsv_cat(body, o, ",\"q4k_gemm_calls\":" as *u8); o = nsv_catn(body, o, nq_prof_get(NQ_PROF_Q4K_CALLS)) 1269 o = nsv_cat(body, o, ",\"i16_ns\":" as *u8); o = nsv_catn(body, o, nq_prof_get(NQ_PROF_I16_NS)) 1270 o = nsv_cat(body, o, ",\"i16_calls\":" as *u8); o = nsv_catn(body, o, nq_prof_get(NQ_PROF_I16_CALLS)) 1271 o = nsv_cat(body, o, ",\"inplace_tensors\":" as *u8); o = nsv_catn(body, o, g_nsv_q4st[0]) 1272 o = nsv_cat(body, o, ",\"fallback_i16_tensors\":" as *u8); o = nsv_catn(body, o, g_nsv_q4st[1]) 1273 o = nsv_cat(body, o, "}" as *u8) 1274 } 1275 o = nsv_cat(body, o, "}" as *u8) 1276 return nsv_resp(resb, rescap, 200, "application/json" as *u8, body, o) 1277 } } } 1278 // GET /api 1279 if is_get == 1 { if plen == 4 { if req[ps+1]==(97 as u8) { 1280 let o: i64 = nsv_cat(body, 0, "{\"organ\":\"nx_nofloat_serve\",\"endpoints\":[{\"m\":\"POST\",\"p\":\"/gen\",\"body\":{\"prompt\":\"str\",\"max_new\":\"int 1-96 (default 24)\",\"mode\":\"i32|i8|q4k (q4k only on a route=q4k-resident serve; i32/i8 refused there)\",\"stream\":\"0|1 SSE\",\"chat\":\"0|1 ChatML wrap\"}},{\"m\":\"POST\",\"p\":\"/embed\",\"body\":{\"text\":\"str required <=8100B\",\"task\":\"nl2code|qa|code2code|code2nl|code2completion (default nl2code)\",\"kind\":\"query|passage (default query)\",\"mode\":\"i8|i32 (default i8)\"},\"returns\":\"dim=896 q24 int vector (last-token pooled final-norm hidden, arXiv 2508.21290)\"},{\"m\":\"GET\",\"p\":\"/health\"},{\"m\":\"GET\",\"p\":\"/\"}],\"stack\":\"sovereign 100pct-integer Qwen2.5-0.5B, dequant-once i32 lossless + i8 SIMD fast, KV-cached greedy\"}" as *u8) 1281 return nsv_resp(resb, rescap, 200, "application/json" as *u8, body, o) 1282 } } } 1283 // POST /gen 1284 if is_post == 1 { if plen == 4 { if req[ps+1]==(103 as u8) { 1285 let gp: *i64 = sys_mmap(16*8) as *i64 1286 let prc: i64 = nsv_parse_gen(req, rn, gp) 1287 if prc != 0 { 1288 let o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":1}" as *u8) 1289 return nsv_resp(resb, rescap, 400, "application/json" as *u8, body, o) 1290 } 1291 let text: *u8 = sys_mmap(65536) 1292 let meta: *i64 = sys_mmap(8*8) as *i64 1293 gp[4]=text as i64 1294 gp[5]=65000 1295 gp[6]=meta as i64 1296 gp[7]=0-1 1297 let mode: i64 = gp[3] 1298 let tl: i64 = nsv_generate(gp) 1299 if tl < 0 { 1300 var o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":" as *u8) 1301 o = nsv_catn(body, o, meta[5]) 1302 o = nsv_cat(body, o, "}" as *u8) 1303 return nsv_resp(resb, rescap, 400, "application/json" as *u8, body, o) 1304 } 1305 var o: i64 = 0 1306 o = nsv_cat(body, o, "{\"ok\":1,\"mode\":\"" as *u8) 1307 if mode == NSV_MODE_Q4K { o = nsv_cat(body, o, "q4k" as *u8) } else { 1308 if mode == 1 { o = nsv_cat(body, o, "i8" as *u8) } else { o = nsv_cat(body, o, "i32" as *u8) } } 1309 o = nsv_cat(body, o, "\",\"prompt_tokens\":" as *u8) 1310 o = nsv_catn(body, o, meta[0]) 1311 o = nsv_cat(body, o, ",\"gen_tokens\":" as *u8) 1312 o = nsv_catn(body, o, meta[1]) 1313 o = nsv_cat(body, o, ",\"ms_total\":" as *u8) 1314 o = nsv_catn(body, o, meta[2]) 1315 o = nsv_cat(body, o, ",\"ms_per_token\":" as *u8) 1316 o = nsv_catn(body, o, meta[3]) 1317 o = nsv_cat(body, o, ",\"prefill_ms\":" as *u8) 1318 o = nsv_catn(body, o, meta[6]) 1319 o = nsv_cat(body, o, ",\"prefill\":\"" as *u8) 1320 if g_nsv_prefill_batched == 1 { o = nsv_cat(body, o, "batched" as *u8) } else { o = nsv_cat(body, o, "sequential" as *u8) } 1321 o = nsv_cat(body, o, "\",\"eos\":" as *u8) 1322 o = nsv_catn(body, o, meta[4]) 1323 o = nsv_cat(body, o, ",\"temp\":" as *u8) 1324 o = nsv_catn(body, o, gp[8]) 1325 o = nsv_cat(body, o, ",\"seed\":" as *u8) 1326 o = nsv_catn(body, o, gp[11]) 1327 o = nsv_cat(body, o, ",\"text\":\"" as *u8) 1328 o = nsv_jesc(body, o, text, tl) 1329 o = nsv_cat(body, o, "\"}" as *u8) 1330 return nsv_resp(resb, rescap, 200, "application/json" as *u8, body, o) 1331 } } } 1332 // POST /embed (jina-code-embeddings recipe arXiv:2508.21290: the embedding IS the last-token pooled 1333 // final-norm hidden state; instruction prefix prepended server-side). Returns the raw Q24 int vector -- 1334 // cosine/ranking is the caller's (or the index organ's) job, integer math end to end. 1335 if is_post == 1 { if plen == 6 { if req[ps+1]==(101 as u8) { 1336 if g_nsv_mt[6] != 1 { 1337 let o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":9}" as *u8) 1338 return nsv_resp(resb, rescap, 503, "application/json" as *u8, body, o) 1339 } 1340 let ep: *i64 = sys_mmap(8*8) as *i64 1341 let erc: i64 = nsv_parse_embed(req, rn, ep) 1342 if erc != 0 { 1343 let o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":1}" as *u8) 1344 return nsv_resp(resb, rescap, 400, "application/json" as *u8, body, o) 1345 } 1346 let pre: *u8 = nsv_embed_prefix(ep[4] as *u8, ep[5], ep[3]) 1347 let txt: *u8 = sys_mmap(NSV_MAXIN) 1348 var l: i64 = nsv_cat(txt, 0, pre) 1349 l = nsv_catb(txt, l, ep[0] as *u8, ep[1]) 1350 let ne: i64 = g_nsv_cfgA[1] 1351 let vec: *i64 = sys_mmap(ne*8) as *i64 1352 let t0: i64 = sys_now_ms() 1353 let n: i64 = nsv_embed(txt, l, ep[2], vec) 1354 let t1: i64 = sys_now_ms() 1355 if n < 1 { 1356 var o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":" as *u8) 1357 o = nsv_catn(body, o, n) 1358 o = nsv_cat(body, o, "}" as *u8) 1359 return nsv_resp(resb, rescap, 400, "application/json" as *u8, body, o) 1360 } 1361 var o: i64 = 0 1362 o = nsv_cat(body, o, "{\"ok\":1,\"dim\":" as *u8) 1363 o = nsv_catn(body, o, ne) 1364 o = nsv_cat(body, o, ",\"ntok\":" as *u8) 1365 o = nsv_catn(body, o, n) 1366 o = nsv_cat(body, o, ",\"ms\":" as *u8) 1367 o = nsv_catn(body, o, t1 - t0) 1368 o = nsv_cat(body, o, ",\"scale\":\"q24\",\"mode\":\"" as *u8) 1369 if ep[2] == 1 { o = nsv_cat(body, o, "i8" as *u8) } else { o = nsv_cat(body, o, "i32" as *u8) } 1370 o = nsv_cat(body, o, "\",\"vec\":[" as *u8) 1371 var vi: i64 = 0 1372 while vi < ne { 1373 if vi > 0 { o = nsv_cat(body, o, "," as *u8) } 1374 o = nsv_catn(body, o, vec[vi]) 1375 vi = vi + 1 1376 } 1377 o = nsv_cat(body, o, "]}" as *u8) 1378 return nsv_resp(resb, rescap, 200, "application/json" as *u8, body, o) 1379 } } } 1380 let o: i64 = nsv_cat(body, 0, "{\"ok\":0,\"err\":404}" as *u8) 1381 return nsv_resp(resb, rescap, 404, "application/json" as *u8, body, o) 1382}