nx_recall_rerank.nx source
↩ module page · 56 lines · 2392 B
1// nx_recall_rerank.nx -- the SOVEREIGN semantic reranker: score (query, doc) by dense
2// cosine over PPMI-SVD / concept embeddings (nx_cosine_similarity).
3//
4// module: nishi-core.search.recall_rerank
5// depends: nx_tier.nx, nx_cosine_similarity.nx, syscalls.nx
6// capability: CORE_COMPUTE
7// wired_status: LIBRARY (daemon wiring = R2b; embedding source = nx_ppmi_svd / nx_semppmi_build)
8// genealogy_id: salton_1971_smart (vector space) + two_stage_retrieve_then_rerank
9//
10// WHY (3rd-party debt-eating, good form): nx_rag_rerank PUNTS the semantic judgment to
11// an EXTERNAL LLM (Claude now, "Nishi-LLM the destination") -- a non-sovereign crutch.
12// This organ replaces that punt with a sovereign, integer-deterministic, gate-
13// MEASURABLE reranker: the two-stage pattern's stage 2 (retrieve+fuse in R1 -> rerank
14// the shortlist here by joint query-doc semantic similarity). No external dependency,
15// bit-exact reproducible. The fast tier of the reranker; the no-float LLM-reranker
16// (nx_nofloat_llm) is the latency-tolerant escalation tier (R5).
17
18import "nx_tier.nx"
19import "nx_cosine_similarity.nx"
20import "syscalls.nx"
21
22// Semantic score per candidate: signed Q10 cosine(query_emb, doc_emb[c]) over `dim`.
23// doc_embs is a flat ncand*dim matrix (row c = candidate c's embedding). out_cos[c].
24func rr_semantic_scores(query_emb: *nx_int, dim: nx_int, doc_embs: *nx_int, ncand: nx_int, out_cos: *nx_int) -> nx_int {
25 var c: nx_int = 0
26 while c < ncand {
27 let row: *nx_int = ((doc_embs as i64) + c * dim * 8) as *nx_int
28 out_cos[c] = nx_cosine_similarity(query_emb, dim, row, dim)
29 c = c + 1
30 }
31 return 0
32}
33
34// Order candidate ids by semantic score DESC (ties -> lower id). out_order[ncand].
35// Selection sort -- the reranked shortlist is small (post-fusion top-N).
36func rr_order_by_cos(cos: *nx_int, ncand: nx_int, out_order: *i64) -> i64 {
37 let used: *u8 = sys_mmap(ncand)
38 var i: i64 = 0
39 while i < ncand { used[i] = 0 as u8; i = i + 1 }
40 var r: i64 = 0
41 while r < ncand {
42 var best: i64 = 0 - 1
43 var j: i64 = 0
44 while j < ncand {
45 if used[j] == (0 as u8) {
46 if best < 0 { best = j }
47 else { if cos[j] > cos[best] { best = j } }
48 }
49 j = j + 1
50 }
51 out_order[r] = best
52 used[best] = 1 as u8
53 r = r + 1
54 }
55 return 0
56}