code wiki / _hdl_build / nx_dr_semjudge.nx
nx_dr_semjudge.nx source
↩ module page · 47 lines · 2701 B
1// nx_dr_semjudge.nx -- SEMANTIC judge tier for the deep-research engine (DR-10).
2// The engine's judge was the LEXICAL tier: token containment, so an insight saying "won"
3// scored ZERO against a source saying "defeated". This escalates that socket to SEMANTIC
4// matching over a real PPMI count model: coverage(insight,doc) = mean over insight terms of
5// MAX PPMI cosine against any doc term -- ColBERT-class integer late-interaction, zero float.
6//
7// ★seq283 EATEN (this half): the loader/cosine numerics are NO LONGER duplicated here. They
8// live once in nx_ppmi_lib.nx and this file is a thin ADAPTER preserving the sj_* API its gate
9// and CLI already use. Two hand-rolled copies of the same numeric code could silently diverge
10// and change similarity scores with no gate noticing -- that risk is gone for this organ.
11// (nx_recall_dense still holds its own pb_* copy; it is a LIVE organ owned by the recall lane
12// and migrates on its owner's next touch, per the D001 migrate-on-touch law.)
13//
14// ⚠INTEGRATION LAW: the PPMI vocab is keyed by db_semhash (nx_qabench_engine), NOT the djb2
15// lexical hash -- the wrong hash silently returns -1 for every word and zeroes every
16// similarity. nx_ppmi_lib owns the lowercase-then-db_semhash resolution.
17// ⚠HONEST CEILING: a count model is bounded by its corpus vocabulary; out-of-vocabulary terms
18// score 0. Use nx_dr_semjudge_x to A/B an alternative model against that ceiling.
19//
20// module: nishi-core.research.dr_semjudge
21// depends: nx_ppmi_lib.nx
22// genealogy_id: levy_goldberg_2014_ppmi + colbert_late_interaction
23import "nx_ppmi_lib.nx"
24
25func sj_isqrt(v: i64) -> i64 { return ppl_isqrt(v) }
26
27// Load the default shipped PPMI model. Returns 1 on success, 0 on failure (fail-closed).
28func sj_load(g: *i64) -> i64 { return ppl_load(g, "knowledge/index/semppmi_v1.bin" as *u8) }
29
30// PPMI cosine between two vocab rows, permille.
31func sj_cos(g: *i64, a: i64, b: i64) -> i64 { return ppl_cos(g, a, b) }
32
33// cosine with identity + out-of-vocabulary guard (id -1 contributes nothing).
34func sj_dcos(g: *i64, a: i64, b: i64) -> i64 { return ppl_dcos(g, a, b) }
35
36// Resolve buf[start,end) to a PPMI vocab id, or -1 if OOV.
37func sj_wid_range(g: *i64, buf: *u8, start: i64, end: i64) -> i64 { return ppl_wid_range(g, buf, start, end) }
38
39// Tokenize text into PPMI vocab ids (-1 = OOV). Returns the token count.
40func sj_tokenize_ids(g: *i64, buf: *u8, len: i64, out: *i64, maxn: i64) -> i64 {
41 return ppl_tokenize_ids(g, buf, len, out, maxn)
42}
43
44// SEMANTIC coverage of an insight in a document, permille (late interaction).
45func sj_maxsim(g: *i64, ins: *i64, ni: i64, doc: *i64, nd: i64) -> i64 {
46 return ppl_maxsim(g, ins, ni, doc, nd)
47}