code wiki / _hdl_build / nx_book_search.nx

nx_book_search.nx source

↩ module page · 139 lines · 8369 B

1// nx_book_search.nx -- SC20: sovereign RANKED search over the NAS book library (idx_book.wsl, 5761 books). 2// 3// REUSE not reinvent: composes the team's production BM25 ranker (nx_bm25: bm_idf_micro / bm_sat_milli / 4// bm_token_count / bm_df) + nx_research_extract (re_count/re_has). The existing nx_library_search is wired for 5// the researcher's [doc]-index corpus and caps at 256 docs; this drives the SAME BM25 math over the 5761-book 6// library index. TWO fixes for scale + real-world data: 7// (1) case-insensitive: the index paths are mixed-case, so we rank over a LOWERCASED copy of the index. 8// (2) O(N*nq) not O(N^2): bm_best recomputes df per-doc (fine for 256 docs, not 5761); we PRECOMPUTE idf 9// once per query term, then score each doc -> a true library-scale ranker. 10// Self-gated by KATs over the REAL index (dragonlance/byers/tolkien/witcher must rank a doc that contains the 11// term; "sanderson" has 0 matches -> must return NO result = negative control; dragonlance != byers = discrim). 12// Standalone (no server/reader edit -> no collision with the ark-beat loop). license_tier: ORIGINAL 13import "nx_research_extract.nx" // re_count / re_has 14import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 15import "nx_bm25.nx" // bm_token_count / bm_idf_micro / bm_sat_milli / bm_df 16import "nx_syscalls.nx" 17const BS_MAGIC_2000000: i64 = 2000000 18 19const BS_IDX: *u8 = "knowledge/staging/media/idx_book.wsl" 20const BS_LOG: *u8 = "knowledge/status/book_search.log" 21const BS_CAPDOCS: i64 = 8192 // > 5761 22 23func bs_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 24// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 25// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 26// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 27// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 28func bs_n(v: i64) -> i64 { nxi_out(v); return 0 } 29func bs_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 30// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 31// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 32// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 33// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 34func bs_fn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 35func bs_lc(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c } 36 37func bs_read(path: *u8, buf: *u8, cap: i64) -> i64 { 38 let fd: i64 = sys_openat_rd(path) 39 if fd < 0 { return 0 - 1 } 40 var n: i64 = 0; var go: i64 = 1 41 while go == 1 { let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap - 1 { go = 0 } } 42 sys_close(fd) 43 return n 44} 45 46// ranked best doc for a single lowercased term, idf precomputed ONCE (library-scale O(N)). 47func bs_best1(ptrs: *i64, lens: *i64, dls: *i64, ndocs: i64, avgdl: i64, term: *u8) -> i64 { 48 let idf: i64 = bm_idf_micro(ndocs, bm_df(ptrs, lens, ndocs, term)) // x1e6, once 49 var best: i64 = 0 - 1; var bestscore: i64 = 0 50 var k: i64 = 0 51 while k < ndocs { 52 let tf: i64 = re_count(ptrs[k] as *u8, lens[k], term) 53 if tf > 0 { 54 let sc: i64 = (idf * bm_sat_milli(tf, dls[k], avgdl)) / 1000 55 if sc > bestscore { bestscore = sc; best = k } 56 } 57 k = k + 1 58 } 59 return best 60} 61 62func main() -> i64 { 63 bs_p("=== nx_book_search: SC20 ranked library search over idx_book.wsl (sovereign BM25) ===\n" as *u8) 64 65 let buf: *u8 = sys_mmap(BS_MAGIC_2000000) 66 let n: i64 = bs_read(BS_IDX, buf, BS_MAGIC_2000000) 67 if n <= 0 { bs_p("BOOK-SEARCH verdict=RED reason=idx-missing\n" as *u8); sys_exit(1); return 1 } 68 69 // lowercased mirror of the index (1:1 byte layout) for case-insensitive ranking 70 let lc: *u8 = sys_mmap(BS_MAGIC_2000000) 71 var i: i64 = 0 72 while i < n { lc[i] = bs_lc(buf[i] as i64) as u8; i = i + 1 } 73 74 // split into docs: one line = one book. ptrs into lc (matching), offs to recover original (display). 75 let ptrs: *i64 = sys_mmap(BS_CAPDOCS * 8) as *i64 76 let offs: *i64 = sys_mmap(BS_CAPDOCS * 8) as *i64 77 let lens: *i64 = sys_mmap(BS_CAPDOCS * 8) as *i64 78 let dls: *i64 = sys_mmap(BS_CAPDOCS * 8) as *i64 79 var ndocs: i64 = 0 80 var total: i64 = 0 81 var s: i64 = 0 82 while s < n { 83 var e: i64 = s 84 var found: i64 = 0 85 while found == 0 { if e >= n { found = 1 } else { if lc[e] == (10 as u8) { found = 1 } else { e = e + 1 } } } 86 let llen: i64 = e - s 87 if llen > 0 { if ndocs < BS_CAPDOCS { 88 offs[ndocs] = s 89 ptrs[ndocs] = (lc as i64) + s 90 lens[ndocs] = llen 91 dls[ndocs] = bm_token_count((lc as i64 + s) as *u8, llen) 92 total = total + dls[ndocs] 93 ndocs = ndocs + 1 94 } } 95 s = e + 1 96 } 97 var avgdl: i64 = 1 98 if ndocs > 0 { avgdl = total / ndocs } 99 if avgdl <= 0 { avgdl = 1 } 100 bs_p(" indexed docs=" as *u8); bs_n(ndocs); bs_p(" avgdl=" as *u8); bs_n(avgdl); bs_p("\n" as *u8) 101 102 // ---- KAT queries over the REAL corpus ---- 103 let bd: i64 = bs_best1(ptrs, lens, dls, ndocs, avgdl, "dragonlance" as *u8) 104 let bb: i64 = bs_best1(ptrs, lens, dls, ndocs, avgdl, "byers" as *u8) 105 let bt: i64 = bs_best1(ptrs, lens, dls, ndocs, avgdl, "tolkien" as *u8) 106 let bw: i64 = bs_best1(ptrs, lens, dls, ndocs, avgdl, "witcher" as *u8) 107 let bs: i64 = bs_best1(ptrs, lens, dls, ndocs, avgdl, "sanderson" as *u8) // 0 matches -> expect -1 108 109 // show top hit for each positive query (original-case path) 110 bs_p(" q=dragonlance -> " as *u8); if bd >= 0 { sys_write(1, (buf as i64 + offs[bd]) as *u8, lens[bd]) } else { bs_p("(none)" as *u8) } bs_p("\n" as *u8) 111 bs_p(" q=byers -> " as *u8); if bb >= 0 { sys_write(1, (buf as i64 + offs[bb]) as *u8, lens[bb]) } else { bs_p("(none)" as *u8) } bs_p("\n" as *u8) 112 bs_p(" q=tolkien -> " as *u8); if bt >= 0 { sys_write(1, (buf as i64 + offs[bt]) as *u8, lens[bt]) } else { bs_p("(none)" as *u8) } bs_p("\n" as *u8) 113 bs_p(" q=witcher -> " as *u8); if bw >= 0 { sys_write(1, (buf as i64 + offs[bw]) as *u8, lens[bw]) } else { bs_p("(none)" as *u8) } bs_p("\n" as *u8) 114 bs_p(" q=sanderson -> " as *u8); if bs >= 0 { sys_write(1, (buf as i64 + offs[bs]) as *u8, lens[bs]) } else { bs_p("(none = correct, 0 in corpus)" as *u8) } bs_p("\n" as *u8) 115 116 // ---- gate: each positive must rank a doc that CONTAINS the term; negative must be -1; discrim ---- 117 var pass: i64 = 0 118 if bd >= 0 { if re_has((lc as i64 + offs[bd]) as *u8, lens[bd], "dragonlance" as *u8) == 1 { pass = pass + 1 } } 119 if bb >= 0 { if re_has((lc as i64 + offs[bb]) as *u8, lens[bb], "byers" as *u8) == 1 { pass = pass + 1 } } 120 if bt >= 0 { if re_has((lc as i64 + offs[bt]) as *u8, lens[bt], "tolkien" as *u8) == 1 { pass = pass + 1 } } 121 if bw >= 0 { if re_has((lc as i64 + offs[bw]) as *u8, lens[bw], "witcher" as *u8) == 1 { pass = pass + 1 } } 122 var neg_ok: i64 = 0 123 if bs < 0 { neg_ok = 1; pass = pass + 1 } 124 var discrim: i64 = 0 125 if bd >= 0 { if bb >= 0 { if bd != bb { discrim = 1; pass = pass + 1 } } } 126 127 bs_p(" gate: pass=" as *u8); bs_n(pass); bs_p("/6 (4 positive-rank + 1 negative-control + 1 discrimination)\n" as *u8) 128 129 let lf: i64 = sys_openat_append(BS_LOG, 0x1a4) 130 if pass == 6 { 131 if lf >= 0 { bs_fp(lf, "BOOK-SEARCH verdict=GREEN docs=" as *u8); bs_fn(lf, ndocs); bs_fp(lf, " avgdl=" as *u8); bs_fn(lf, avgdl); bs_fp(lf, " pass=6/6 neg_ok=" as *u8); bs_fn(lf, neg_ok); bs_fp(lf, " discrim=" as *u8); bs_fn(lf, discrim); bs_fp(lf, " epoch=" as *u8); bs_fn(lf, sys_now_realtime_sec()); bs_fp(lf, "\n" as *u8); sys_close(lf) } 132 bs_p("BOOK-SEARCH verdict=GREEN (sovereign BM25 ranked search works over the real 5761-book library; SC20 engine)\n" as *u8) 133 sys_exit(0); return 0 134 } 135 if lf >= 0 { bs_fp(lf, "BOOK-SEARCH verdict=RED pass=" as *u8); bs_fn(lf, pass); bs_fp(lf, "/6\n" as *u8); sys_close(lf) } 136 bs_p("BOOK-SEARCH verdict=RED (a KAT failed)\n" as *u8) 137 sys_exit(1) 138 return 1 139}