code wiki / (root) / nx_research_synth_qwen.nx

nx_research_synth_qwen.nx source

↩ module page · 369 lines · 15708 B

1// nx_research_synth_qwen.nx -- S1 of the Tesla growth ladder: SOVEREIGN GROUNDED SYNTHESIS. 2// Given a question + N retrieved source passages, the pretrained sovereign Qwen (nsv_generate, in-process, 3// no HTTP, $0, integer-deterministic) generates a MULTI-SENTENCE answer that cites each claim [n] back to a 4// numbered source. The organ's RESONANT property (Tesla law #1) is not the generation -- it is the 5// DETERMINISTIC GROUNDING CHECK that runs at $0 with NO model: every content word of the answer must trace 6// to a cited source, and every citation must be in range. A hallucinated claim (word absent from all sources) 7// or a fabricated citation ([5] when 2 sources exist) is caught mechanically. This is the anti-hallucination 8// discipline FARS lacked (its own audit: 5.7% hallucinated citations, 7.4% fabricated results). 9// 10// Composes: nx_nofloat_serve_core (nsv_init/nsv_generate). Model-call pattern mirrors nx_qwen_extract (proven). 11// The grounding functions (rsq_ground_report / rsq_parse_cites / rsq_is_refusal) need NO model -> the gate 12// proves the mechanism in miniature (law #3), and the generative path is marker-gated for NAS measurement. 13// NEXT (S2): each ungrounded claim -> nx_evidence_verify_gate for external confirm/discredit. license_tier: ORIGINAL 14import "nx_syscalls.nx" 15import "nx_nofloat_serve_core.nx" 16import "nx_text_sentences.nx" 17 18const RSQ_MODEL: *u8 = "/home/elderwesto/nx_stage/nx_real_model.gguf" 19const RSQ_SRCCAP: i64 = 600 // per-source byte cap inside the prompt 20const RSQ_MAXPROMPT: i64 = 4000 // hard byte guard (<< NSV_MAXIN=16384 tok-scratch; ~1600 tok < NSV_MAXT=2048) 21const RSQ_MAXNEW: i64 = 64 // synthesis needs a 2-4 sentence answer (extraction used 16) 22const RSQ_MODE: i64 = 0 // 0 = i32 lossless (faithful default) 23const RSQ_MINWORD: i64 = 5 // a content word is len>=5 (filters most function words) 24 25static g_rsq_ready: i64 // 0 until nsv_init succeeds (BSS-zero, safe to read pre-init) 26static g_rsq_pr: *u8 // preallocated prompt buffer 27static g_rsq_out: *u8 // model output buffer 28static g_rsq_meta: *i64 // nsv meta block 29static g_rsq_gp: *i64 // nsv generate-params block 30static g_rsq_ctp: *i64 // one-time scratch for txt_parse_cite (Consolidation STEP C; lazy-init, NOT mmap-per-call) 31static g_rsq_ctp_init: i64 32 33// ---- small byte helpers (declared before use; fwd static-ref would miscompile) ---- 34func rsq_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 35func rsq_lc(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c } 36func rsq_is_alnum(c: i64) -> i64 { 37 if c >= 48 { if c <= 57 { return 1 } } 38 if c >= 65 { if c <= 90 { return 1 } } 39 if c >= 97 { if c <= 122 { return 1 } } 40 return 0 41} 42func rsq_cat(dst: *u8, off: i64, s: *u8, n: i64, cap: i64) -> i64 { 43 var i: i64 = 0; var o: i64 = off 44 while i < n { if o < cap { dst[o] = s[i]; o = o + 1 } i = i + 1 } 45 return o 46} 47func rsq_cats(dst: *u8, off: i64, s: *u8, cap: i64) -> i64 { 48 var i: i64 = 0; var o: i64 = off 49 while s[i] != (0 as u8) { if o < cap { dst[o] = s[i]; o = o + 1 } i = i + 1 } 50 return o 51} 52func rsq_catd(dst: *u8, off: i64, d: i64, cap: i64) -> i64 { 53 var o: i64 = off 54 if o < cap { dst[o] = (48 + d) as u8; o = o + 1 } 55 return o 56} 57 58// case-insensitive: does the (ptr,wlen) word occur anywhere in buf[0,blen)? 59func rsq_ci_match_at(buf: *u8, pos: i64, blen: i64, word: *u8, wlen: i64) -> i64 { 60 var k: i64 = 0 61 while k < wlen { 62 if pos + k >= blen { return 0 } 63 if rsq_lc(buf[pos+k] as i64 & 0xff) != rsq_lc(word[k] as i64 & 0xff) { return 0 } 64 k = k + 1 65 } 66 return 1 67} 68func rsq_ci_contains(buf: *u8, blen: i64, word: *u8, wlen: i64) -> i64 { 69 if wlen == 0 { return 0 } 70 var i: i64 = 0 71 while i + wlen <= blen { 72 if rsq_ci_match_at(buf, i, blen, word, wlen) == 1 { return 1 } 73 i = i + 1 74 } 75 return 0 76} 77// end of the alnum run starting at i (i points at an alnum byte); always returns > i 78func rsq_word_end(ans: *u8, i: i64, alen: i64) -> i64 { 79 var j: i64 = i 80 var go: i64 = 1 81 while go == 1 { 82 go = 0 83 if j < alen { if rsq_is_alnum(ans[j] as i64 & 0xff) == 1 { j = j + 1; go = 1 } } 84 } 85 return j 86} 87// case-insensitive equality of answer span [off,off+wlen) to a NUL-terminated word 88func rsq_eqword(ans: *u8, off: i64, wlen: i64, w: *u8) -> i64 { 89 var k: i64 = 0 90 while k < wlen { 91 if w[k] == (0 as u8) { return 0 } 92 if rsq_lc(ans[off+k] as i64 & 0xff) != rsq_lc(w[k] as i64 & 0xff) { return 0 } 93 k = k + 1 94 } 95 if w[wlen] != (0 as u8) { return 0 } 96 return 1 97} 98// a small len>=5 function-word list so the hallucination signal is about CONTENT, not grammar 99func rsq_is_stop(ans: *u8, off: i64, wlen: i64) -> i64 { 100 if rsq_eqword(ans, off, wlen, "which" as *u8) == 1 { return 1 } 101 if rsq_eqword(ans, off, wlen, "there" as *u8) == 1 { return 1 } 102 if rsq_eqword(ans, off, wlen, "these" as *u8) == 1 { return 1 } 103 if rsq_eqword(ans, off, wlen, "those" as *u8) == 1 { return 1 } 104 if rsq_eqword(ans, off, wlen, "their" as *u8) == 1 { return 1 } 105 if rsq_eqword(ans, off, wlen, "would" as *u8) == 1 { return 1 } 106 if rsq_eqword(ans, off, wlen, "could" as *u8) == 1 { return 1 } 107 if rsq_eqword(ans, off, wlen, "should" as *u8) == 1 { return 1 } 108 if rsq_eqword(ans, off, wlen, "about" as *u8) == 1 { return 1 } 109 if rsq_eqword(ans, off, wlen, "after" as *u8) == 1 { return 1 } 110 if rsq_eqword(ans, off, wlen, "other" as *u8) == 1 { return 1 } 111 if rsq_eqword(ans, off, wlen, "being" as *u8) == 1 { return 1 } 112 if rsq_eqword(ans, off, wlen, "where" as *u8) == 1 { return 1 } 113 if rsq_eqword(ans, off, wlen, "while" as *u8) == 1 { return 1 } 114 if rsq_eqword(ans, off, wlen, "first" as *u8) == 1 { return 1 } 115 return 0 116} 117// is a content word (ptr at ans+off, wlen) present in ANY of the nsrc sources? 118func rsq_present_in_sources(ans: *u8, off: i64, wlen: i64, srcv: *i64, nsrc: i64) -> i64 { 119 var k: i64 = 0 120 while k < nsrc { 121 let sp: *u8 = srcv[k] as *u8 122 let sl: i64 = rsq_len(sp) 123 if rsq_ci_contains(sp, sl, (ans as i64 + off) as *u8, wlen) == 1 { return 1 } 124 k = k + 1 125 } 126 return 0 127} 128// THE grounding report: out[0]=content words, out[1]=hallucinated (present in NO source). returns halluc. 129func rsq_ground_report(ans: *u8, alen: i64, srcv: *i64, nsrc: i64, out: *i64) -> i64 { 130 var content: i64 = 0 131 var halluc: i64 = 0 132 var i: i64 = 0 133 while i < alen { 134 let c: i64 = ans[i] as i64 & 0xff 135 if rsq_is_alnum(c) == 1 { 136 let je: i64 = rsq_word_end(ans, i, alen) 137 let wlen: i64 = je - i 138 if wlen >= RSQ_MINWORD { 139 if rsq_is_stop(ans, i, wlen) == 0 { 140 content = content + 1 141 if rsq_present_in_sources(ans, i, wlen, srcv, nsrc) == 0 { halluc = halluc + 1 } 142 } 143 } 144 i = je 145 } else { 146 i = i + 1 147 } 148 } 149 out[0] = content 150 out[1] = halluc 151 return halluc 152} 153// parse [n] citations: out[0]=count out[1]=in-range out[2]=out-of-range. returns count. 154func rsq_parse_cites(ans: *u8, alen: i64, cites: *i64, maxc: i64, srcrange: i64, out: *i64) -> i64 { 155 var nc: i64 = 0; var inr: i64 = 0; var outr: i64 = 0 156 var i: i64 = 0 157 while i < alen { 158 if (ans[i] as i64 & 0xff) == 91 { // '[' 159 var j: i64 = i + 1 160 var val: i64 = 0 161 var got: i64 = 0 162 var go: i64 = 1 163 while go == 1 { 164 go = 0 165 if j < alen { 166 let d: i64 = ans[j] as i64 & 0xff 167 if d >= 48 { if d <= 57 { val = val*10 + (d-48); got = got + 1; j = j + 1; go = 1 } } 168 } 169 } 170 if got > 0 { if j < alen { if (ans[j] as i64 & 0xff) == 93 { // ']' 171 if nc < maxc { cites[nc] = val; nc = nc + 1 } 172 if val >= 1 { if val <= srcrange { inr = inr + 1 } else { outr = outr + 1 } } else { outr = outr + 1 } 173 i = j 174 } } } 175 } 176 i = i + 1 177 } 178 out[0] = nc; out[1] = inr; out[2] = outr 179 return nc 180} 181// did the model decline (grounded refusal, the DeepResearcher honesty-refusal behavior)? 182func rsq_is_refusal(ans: *u8, alen: i64) -> i64 { 183 if rsq_ci_contains(ans, alen, "not supported" as *u8, 13) == 1 { return 1 } 184 return 0 185} 186// COMBINED grounded verdict (the complete S1 check). out[0]=content out[1]=halluc out[2]=ncites 187// out[3]=inrange out[4]=outrange. Returns 1 GROUNDED iff halluc<=htol AND no out-of-range citation 188// AND (has content OR is an explicit refusal). Catches BOTH hallucinated claims and fabricated citations 189// (the real 0.5B over-cites -- Tier-2 emitted a [3] with 2 sources; this rejects it). Not a hot path. 190func rsq_verdict(ans: *u8, alen: i64, srcv: *i64, nsrc: i64, htol: i64, out: *i64) -> i64 { 191 let gr: *i64 = sys_mmap(64) as *i64 192 let cr: *i64 = sys_mmap(64) as *i64 193 let cbuf: *i64 = sys_mmap(256) as *i64 194 rsq_ground_report(ans, alen, srcv, nsrc, gr) 195 rsq_parse_cites(ans, alen, cbuf, 24, nsrc, cr) 196 out[0] = gr[0] 197 out[1] = gr[1] 198 out[2] = cr[0] 199 out[3] = cr[1] 200 out[4] = cr[2] 201 var grounded: i64 = 1 202 if gr[1] > htol { grounded = 0 } 203 if cr[2] > 0 { grounded = 0 } 204 if gr[0] == 0 { if rsq_is_refusal(ans, alen) == 0 { grounded = 0 } } 205 return grounded 206} 207 208// ---- per-claim attribution (the S1->S2 bridge: each sentence-claim independently checkable) ---- 209// first IN-RANGE [c] citation in sentence [s,e) (1..nsrc), or 0 if none; outp[0]=1 if any OUT-OF-RANGE cite. 210func rsq_sentence_cite(ans: *u8, s: i64, e: i64, nsrc: i64, outp: *i64) -> i64 { 211 if g_rsq_ctp_init == 0 { g_rsq_ctp = sys_mmap(32) as *i64; g_rsq_ctp_init = 1 } 212 let tp: *i64 = g_rsq_ctp 213 var c: i64 = 0 214 var oor: i64 = 0 215 var i: i64 = s 216 while i < e { 217 var adv: i64 = 1 218 if (ans[i] as i64 & 0xff) == 91 { // '[' 219 let endp: i64 = txt_parse_cite(ans, e, i, tp) // shared canonical parser (Consolidation STEP C) 220 if tp[1] == 1 { // complete [n] token 221 let val: i64 = tp[0] 222 if val >= 1 { if val <= nsrc { if c == 0 { c = val } } else { oor = 1 } } else { oor = 1 } 223 i = endp 224 adv = 0 225 } 226 } 227 if adv == 1 { i = i + 1 } 228 } 229 outp[0] = oor 230 return c 231} 232// does any content word of ans[s,e) appear in the SPECIFICALLY cited source srcv[c-1]? (mis-citation catcher) 233func rsq_span_overlaps_src(ans: *u8, s: i64, e: i64, srcv: *i64, c: i64) -> i64 { 234 if c < 1 { return 0 } 235 let sp: *u8 = srcv[c-1] as *u8 236 let sl: i64 = rsq_len(sp) 237 var i: i64 = s 238 while i < e { 239 if rsq_is_alnum(ans[i] as i64 & 0xff) == 1 { 240 let je: i64 = rsq_word_end(ans, i, e) 241 let wlen: i64 = je - i 242 if wlen >= RSQ_MINWORD { if rsq_is_stop(ans, i, wlen) == 0 { 243 if rsq_ci_contains(sp, sl, (ans as i64 + i) as *u8, wlen) == 1 { return 1 } 244 } } 245 i = je 246 } else { i = i + 1 } 247 } 248 return 0 249} 250// per-claim (sentence) verdict. out[0]=nclaims out[1]=grounded out[2]=ungrounded. A claim is grounded iff it 251// has an in-range citation AND >=1 content word present in THAT cited source. returns nclaims. 252func rsq_claim_verdict(ans: *u8, alen: i64, srcv: *i64, nsrc: i64, out: *i64) -> i64 { 253 var nclaims: i64 = 0 254 var ng: i64 = 0 255 var nu: i64 = 0 256 let op: *i64 = sys_mmap(32) as *i64 257 var s: i64 = 0 258 while s < alen { 259 let e: i64 = txt_sentence_end(ans, s, alen) 260 var content: i64 = 0 261 var i: i64 = s 262 while i < e { 263 if rsq_is_alnum(ans[i] as i64 & 0xff) == 1 { 264 let je: i64 = rsq_word_end(ans, i, e) 265 let wlen: i64 = je - i 266 if wlen >= RSQ_MINWORD { if rsq_is_stop(ans, i, wlen) == 0 { content = content + 1 } } 267 i = je 268 } else { i = i + 1 } 269 } 270 if content > 0 { 271 nclaims = nclaims + 1 272 let c: i64 = rsq_sentence_cite(ans, s, e, nsrc, op) 273 var grounded: i64 = 0 274 if c >= 1 { if op[0] == 0 { if rsq_span_overlaps_src(ans, s, e, srcv, c) == 1 { grounded = 1 } } } 275 if grounded == 1 { ng = ng + 1 } else { nu = nu + 1 } 276 } 277 s = e + 1 278 } 279 out[0] = nclaims 280 out[1] = ng 281 out[2] = nu 282 return nclaims 283} 284// build the synthesis prompt: instruction + numbered sources + question. returns byte length. 285func rsq_build_prompt(q: *u8, srcv: *i64, nsrc: i64, pr: *u8, cap: i64) -> i64 { 286 var po: i64 = 0 287 po = rsq_cats(pr, po, "Answer the question using ONLY the numbered sources. After each sentence cite the source in brackets like [1]. If the sources do not contain the answer, reply exactly: NOT SUPPORTED.\n\n" as *u8, cap) 288 var k: i64 = 0 289 while k < nsrc { 290 let sp: *u8 = srcv[k] as *u8 291 po = rsq_cat(pr, po, "[" as *u8, 1, cap) 292 po = rsq_catd(pr, po, k + 1, cap) 293 po = rsq_cats(pr, po, "] " as *u8, cap) 294 var sl: i64 = rsq_len(sp) 295 if sl > RSQ_SRCCAP { sl = RSQ_SRCCAP } 296 po = rsq_cat(pr, po, sp, sl, cap) 297 po = rsq_cats(pr, po, "\n" as *u8, cap) 298 k = k + 1 299 } 300 po = rsq_cats(pr, po, "\nQuestion: " as *u8, cap) 301 var qc: i64 = rsq_len(q) 302 if qc > 200 { qc = 200 } 303 po = rsq_cat(pr, po, q, qc, cap) 304 po = rsq_cats(pr, po, "\nAnswer:" as *u8, cap) 305 return po 306} 307 308// ---- model boot (idempotent; path override like nx_qwen_extract) ---- 309func rsq_load() -> i64 { 310 if g_rsq_ready == 1 { return 0 } 311 var mp: *u8 = RSQ_MODEL 312 let pfd: i64 = sys_openat_rd("knowledge/index/qwen_model_path.txt" as *u8) 313 if pfd >= 0 { 314 let pb: *u8 = sys_mmap(512) 315 let pn: i64 = sys_read(pfd, pb, 511) 316 sys_close(pfd) 317 var pe: i64 = pn 318 var trim: i64 = 1 319 while trim == 1 { 320 trim = 0 321 if pe > 0 { 322 let c: i64 = pb[pe-1] as i64 323 if c == 10 { pe = pe - 1; trim = 1 } else { if c == 13 { pe = pe - 1; trim = 1 } else { if c == 32 { pe = pe - 1; trim = 1 } } } 324 } 325 } 326 if pe > 0 { pb[pe] = 0 as u8; mp = pb } 327 } 328 let rc: i64 = nsv_init(mp) 329 if rc != 0 { return rc } 330 g_rsq_pr = sys_mmap(8192) 331 g_rsq_out = sys_mmap(4096) 332 g_rsq_meta = sys_mmap(8*8) as *i64 333 g_rsq_gp = sys_mmap(12*8) as *i64 334 g_rsq_ready = 1 335 return 0 336} 337func rsq_ready() -> i64 { return g_rsq_ready } 338 339// generate a grounded synthesis for q over nsrc sources; first-block answer into ans (NUL-term). 340// returns answer byte length, or <=0 on not-ready / too-long / empty. 341func rsq_synth(q: *u8, srcv: *i64, nsrc: i64, ans: *u8) -> i64 { 342 if g_rsq_ready == 0 { return 0 } 343 let pr: *u8 = g_rsq_pr 344 let po: i64 = rsq_build_prompt(q, srcv, nsrc, pr, 8192) 345 if po > RSQ_MAXPROMPT { return 0 } 346 let out: *u8 = g_rsq_out 347 let gp: *i64 = g_rsq_gp 348 gp[0] = pr as i64 349 gp[1] = po 350 gp[2] = RSQ_MAXNEW 351 gp[3] = RSQ_MODE 352 gp[4] = out as i64 353 gp[5] = 4096 354 gp[6] = g_rsq_meta as i64 355 gp[7] = 0 - 1 356 gp[8] = 0 357 gp[9] = 0 358 gp[10] = 0 359 gp[11] = 0 360 let tlen: i64 = nsv_generate(gp) 361 if tlen <= 0 { return 0 } 362 var st: i64 = 0 363 if (out[0] as i64) == 32 { st = 1 } // trim leading space 364 var w: i64 = 0 365 var k: i64 = st 366 while k < tlen { if w < 1000 { ans[w] = out[k]; w = w + 1 } k = k + 1 } 367 ans[w] = 0 as u8 368 return w 369}