code wiki / _hdl_build / nx_nofloat_serve.nx

nx_nofloat_serve.nx source

↩ module page · 215 lines · 10818 B

1// nx_nofloat_serve.nx -- the DEPLOYABLE no-float LLM daemon (ops shell around the gated pure core 2// nx_nofloat_serve_core). Binds 127.0.0.1:8032 and serves the interactive app + JSON API for the sovereign 3// 100pct-integer Qwen2.5-0.5B: POST /gen {prompt,max_new,mode} -> readable text (byte-level-BPE decoded), 4// GET / app page, GET /health, GET /api. FAIL-FAST startup (Rule 20): the model is loaded and BOTH 5// dequant-once caches are built BEFORE bind/listen -- a daemon that accepts is a daemon that can serve. 6// Single accept loop = requests naturally serialize (one 16-core box, one pool). WSL2 forwards localhost 7// to Windows, so the app is browsable at http://localhost:8032/ on the host. Runs forever; build with 8// --build-only, run deliberately (same pattern as nx_relate_daemon :8027). license_tier: ORIGINAL 9import "nx_nofloat_serve_core.nx" 10const NSD_MAGIC_131072: i64 = 131072 11const NSD_MAGIC_262144: i64 = 262144 12 13const NSD_PORT: i64 = 0x1f60 // 8032 14const NSD_MODEL: *u8 = "/home/elderwesto/nx_stage/nx_real_model.gguf" 15 16func nsd_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17func nsd_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 18 19// bind address as DATA (2026-09-16): argv[3] names the interface this seat listens on. The default stays the 20// loopback contract every existing caller has; "0.0.0.0" (or a LAN address) is the estate's swarm-node door, so a 21// NAS plan row may drive this engine over the LAN (nx_bright_rewrite_run engine=a.b.c.d:port). A LAN bind is an 22// announced decision, never a silent default: the ready line prints the address that actually accepted. 23func nsd_addr(out: *u8, port: i64, a: i64, b: i64, c: i64, d: i64) -> i64 { 24 out[0] = 2 as u8 25 out[1] = 0 as u8 26 out[2] = ((port >> 8) & 0xff) as u8 27 out[3] = (port & 0xff) as u8 28 out[4] = a as u8 29 out[5] = b as u8 30 out[6] = c as u8 31 out[7] = d as u8 32 var i: i64 = 8 33 while i < 16 { out[i] = 0 as u8; i = i + 1 } 34 return 0 35} 36// "a.b.c.d" -> q[0..3]; 1 ok / 0 malformed (any other text keeps the loopback default and is announced as such) 37func nsd_parse_ipv4(s: *u8, q: *i64) -> i64 { 38 var i: i64 = 0 39 var part: i64 = 0 40 var v: i64 = 0 41 var digits: i64 = 0 42 var go: i64 = 1 43 while go == 1 { 44 let c: i64 = s[i] & 0xff 45 if c == 0 { go = 0 } else { 46 if c == 46 { 47 if part > 2 { return 0 } 48 if digits == 0 { return 0 } 49 if v > 255 { return 0 } 50 q[part] = v; part = part + 1; v = 0; digits = 0 51 } else { 52 if c < 48 { return 0 } 53 if c > 57 { return 0 } 54 v = v * 10 + (c - 48); digits = digits + 1 55 } 56 i = i + 1 57 } 58 } 59 if part != 3 { return 0 } 60 if digits == 0 { return 0 } 61 if v > 255 { return 0 } 62 q[3] = v 63 return 1 64} 65func nsd_write_all(fd: i64, buf: *u8, n: i64) -> i64 { 66 var w: i64 = 0 67 while w < n { let k: i64 = sys_write(fd, (buf as i64 + w) as *u8, n - w); if k <= 0 { return 0 - 1 } w = w + k } 68 return 0 69} 70// read ONE full HTTP request: until CRLFCRLF, plus Content-Length body bytes if present. returns total. 71func nsd_read_req(fd: i64, buf: *u8, cap: i64) -> i64 { 72 var n: i64 = 0 73 var hdr_end: i64 = 0 - 1 74 var want: i64 = 0 - 1 75 var go: i64 = 1 76 while go == 1 { 77 if n >= cap - 1 { go = 0 } else { 78 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n) 79 if r <= 0 { go = 0 } else { 80 n = n + r 81 if hdr_end < 0 { 82 var i: i64 = 0 83 while i + 3 < n { 84 if buf[i] == (13 as u8) { if buf[i+1] == (10 as u8) { if buf[i+2] == (13 as u8) { if buf[i+3] == (10 as u8) { hdr_end = i + 4; i = n } } } } 85 i = i + 1 86 } 87 if hdr_end >= 0 { 88 var cl: i64 = 0 - 1 89 let key: *u8 = "Content-Length:" as *u8 90 let kl: i64 = 15 91 var j: i64 = 0 92 while j + kl < hdr_end { 93 var k2: i64 = 0 94 var ok: i64 = 1 95 while k2 < kl { if buf[j+k2] != key[k2] { ok = 0; k2 = kl } else { k2 = k2 + 1 } } 96 if ok == 1 { 97 var p2: i64 = j + kl 98 cl = 0 99 var num: i64 = 1 100 while num == 1 { 101 if p2 >= hdr_end { num = 0 } else { 102 let c: i64 = buf[p2] & 0xff 103 if c == 32 { p2 = p2 + 1 } else { 104 if c >= 48 { if c <= 57 { cl = cl * 10 + (c - 48); p2 = p2 + 1 } else { num = 0 } } else { num = 0 } 105 } 106 } 107 } 108 j = hdr_end 109 } 110 j = j + 1 111 } 112 if cl >= 0 { want = hdr_end + cl } else { want = hdr_end } 113 } 114 } 115 if want >= 0 { if n >= want { go = 0 } } 116 } 117 } 118 } 119 return n 120} 121 122// argv (both optional, defaults = the original :8032 instruct contract -- no hardcode, one binary 123// serves any model/port pair): argv[1]=model gguf path, argv[2]=port. The CODER serve for the forge 124// runs the SAME elf as `nx_nofloat_serve.sov.elf <nx_coder_model.gguf> 8033` (port registry: 125// 8031 survey, 8032 instruct app, 11434/11438 f32 seats -> 8033 = coder no-float serve). 126func main(argc: i64, argv: *i64) -> i64 { 127 var model: *u8 = NSD_MODEL 128 var port: i64 = NSD_PORT 129 if argc >= 2 { model = argv[1] as *u8 } 130 if argc >= 3 { 131 let ps: *u8 = argv[2] as *u8 132 var pv: i64 = 0 133 var pi: i64 = 0 134 while ps[pi] != (0 as u8) { 135 let c: i64 = ps[pi] & 0xff 136 if c >= 48 { if c <= 57 { pv = pv * 10 + (c - 48) } } 137 pi = pi + 1 138 } 139 if pv > 0 { port = pv } 140 } 141 nsd_puts("NX-NOFLOAT-SERVE loading model + building dequant-once caches (fail-fast before bind)...\n" as *u8) 142 nsd_puts(" model=" as *u8) 143 nsd_puts(model) 144 nsd_puts(" port=" as *u8) 145 nsd_pn(port) 146 // argv[4] = weight route: "q4k" = LM4 resident-Q4_K (file-mapped weights dotted in place, no layer caches -- 147 // the only route that fits a 7B in a 16 GB VM); anything else = the incumbent dequant-once i32+i8 caches. 148 // argv[4] = "i8": the memory-proportionate i8-only route (nsv_init_i8, no i32 cache: ~6 GB less at 1.5B), the 149 // route a LAN rewrite engine runs beside other jobs; /gen then defaults to i8 and refuses an explicit i32. 150 var q4k: i64 = 0 151 var i8only: i64 = 0 152 if argc >= 5 { 153 let ms: *u8 = argv[4] as *u8 154 if ms[0] == (113 as u8) { if ms[1] == (52 as u8) { if ms[2] == (107 as u8) { if ms[3] == (0 as u8) { q4k = 1 } } } } 155 if ms[0] == (105 as u8) { if ms[1] == (56 as u8) { if ms[2] == (0 as u8) { i8only = 1 } } } 156 if ms[0] == (113 as u8) { if ms[1] == (56 as u8) { if ms[2] == (0 as u8) { q4k = 1 } } } // "q8": the same resident lane over a Q8_0 gguf (search R0s block-native slots) 157 } 158 if q4k == 1 { nsd_puts(" route=q4k-resident" as *u8) } else { if i8only == 1 { nsd_puts(" route=i8-only" as *u8) } else { nsd_puts(" route=dequant-once-i32+i8" as *u8) } } 159 nsd_puts("\n" as *u8) 160 var rc: i64 = 0 161 if q4k == 1 { rc = nsv_init_q4k(model) } else { if i8only == 1 { rc = nsv_init_i8(model) } else { rc = nsv_init(model) } } 162 if rc != 0 { 163 nsd_puts("NX-NOFLOAT-SERVE init FAILED rc=" as *u8) 164 nsd_pn(rc) 165 nsd_puts(" (model missing/unparseable or cache OOM) -- fail closed, fail loud\n" as *u8) 166 return 1 167 } 168 // argv[3] = bind address (default loopback). A dotted quad binds that interface; anything else keeps the 169 // default and says so, so a typo can never silently expose or silently hide the seat. 170 let q: *i64 = sys_mmap(32) as *i64 171 q[0] = 127; q[1] = 0; q[2] = 0; q[3] = 1 172 var bind_note: *u8 = "loopback (default)" as *u8 173 if argc >= 4 { 174 let bs: *u8 = argv[3] as *u8 175 if nsd_parse_ipv4(bs, q) == 1 { bind_note = "argv[3]" as *u8 } else { q[0] = 127; q[1] = 0; q[2] = 0; q[3] = 1; bind_note = "argv[3] not a dotted quad -- loopback kept" as *u8 } 176 } 177 let addr: *u8 = sys_mmap(16) 178 nsd_addr(addr, port, q[0], q[1], q[2], q[3]) 179 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 180 if lfd < 0 { nsd_puts("NX-NOFLOAT-SERVE socket FAILED\n" as *u8); return 1 } 181 if sys_bind(lfd, addr, 16) < 0 { 182 nsd_puts("NX-NOFLOAT-SERVE bind " as *u8) 183 nsd_pn(q[0]); nsd_puts("." as *u8); nsd_pn(q[1]); nsd_puts("." as *u8); nsd_pn(q[2]); nsd_puts("." as *u8); nsd_pn(q[3]); nsd_puts(":" as *u8) 184 nsd_pn(port) 185 nsd_puts(" FAILED (port busy?)\n" as *u8) 186 return 1 187 } 188 if sys_listen(lfd, 16) < 0 { nsd_puts("NX-NOFLOAT-SERVE listen FAILED\n" as *u8); return 1 } 189 nsd_puts("NX-NOFLOAT-SERVE ready http://" as *u8) 190 nsd_pn(q[0]); nsd_puts("." as *u8); nsd_pn(q[1]); nsd_puts("." as *u8); nsd_pn(q[2]); nsd_puts("." as *u8); nsd_pn(q[3]); nsd_puts(":" as *u8) 191 nsd_pn(port) 192 nsd_puts(" bind=" as *u8); nsd_puts(bind_note) 193 nsd_puts("/ (modes i32 lossless / i8 fast; /gen /embed /health /api; accept loop)\n" as *u8) 194 let reqb: *u8 = sys_mmap(NSD_MAGIC_131072) 195 let resb: *u8 = sys_mmap(NSD_MAGIC_262144) 196 var go: i64 = 1 197 while go == 1 { 198 let cfd: i64 = sys_accept(lfd) 199 // DoS-starvation bound (nx_dos_timeout_scan seq321): one peer declaring a body it never finishes 200 // sending would otherwise starve this accept loop forever. ACCEPT_TMO_S is the shared named bound. 201 if cfd >= 0 { sys_set_socket_timeout(cfd, ACCEPT_TMO_S) } 202 if cfd >= 0 { 203 let rn: i64 = nsd_read_req(cfd, reqb, NSD_MAGIC_131072) 204 if rn > 0 { 205 // streaming route first (SSE writes straight to the socket); 0 = not-a-stream -> buffered path 206 if nsv_handle_stream(cfd, reqb, rn) == 0 { 207 let on: i64 = nsv_handle(reqb, rn, resb, NSD_MAGIC_262144) 208 nsd_write_all(cfd, resb, on) 209 } 210 } 211 sys_close(cfd) 212 } 213 } 214 return 0 215}