nx_rank_fused.nx source
↩ module page · 75 lines · 2779 B
1// nx_rank_fused.nx -- the additive, SEO-resistant ranker (tier + BM25 via RRF).
2//
3// module: nishi-core.search.rank_fused
4// depends: fx.nx, nx_source_tier.nx, nx_bm25.nx, nx_rrf.nx
5// capability: CORE_COMPUTE
6// wired_status: FULLY_WIRED
7//
8// The capstone of the ranking layer: fuse the source-tier PRIOR rank with the
9// BM25 CONTENT rank via Reciprocal Rank Fusion. Because RRF rewards items that
10// rank well in BOTH signals, a high-tier page with no relevant content cannot
11// win on authority alone, and a UNIQUE low-tier page with strong content rises
12// -- the operator cardinal (deliver information, additive, no prejudging) made
13// operational. Novelty (nx_simhash) and provenance join as further RRF inputs
14// once the crawler supplies page content. Deterministic Q16.16 throughout.
15
16import "fx.nx"
17import "syscalls.nx"
18import "nx_source_tier.nx"
19import "nx_bm25.nx"
20import "nx_rrf.nx"
21
22// item-ids sorted by score descending (ties -> lower id first).
23func nx_rank_order_desc(scores: *i64, n: i64, order_out: *i64) -> i64 {
24 let used: *i64 = sys_mmap(n * 8) as *i64
25 var i: i64 = 0
26 while i < n { used[i] = 0; i = i + 1 }
27 var k: i64 = 0
28 while k < n {
29 var best: i64 = 0 - 1
30 var bestsc: i64 = 0
31 var j: i64 = 0
32 while j < n {
33 if used[j] == 0 {
34 if best < 0 { best = j; bestsc = scores[j] }
35 else { if scores[j] > bestsc { best = j; bestsc = scores[j] } }
36 }
37 j = j + 1
38 }
39 used[best] = 1
40 order_out[k] = best
41 k = k + 1
42 }
43 return 0
44}
45
46// Fused ranking of a corpus for a query. urls/titles drive the tier prior;
47// texts drive BM25 content relevance. Writes the fused item order (best first)
48// into order_out.
49func nx_rank_fused(urls: **u8, titles: **u8, texts: **u8, text_lens: *i64, n: i64,
50 q_terms: **u8, q_term_lens: *i64, nterms: i64,
51 order_out: *i64) -> i64 {
52 let tier_sc: *i64 = sys_mmap(n * 8) as *i64
53 let v: *NxTierVerdict = sys_mmap(NX_TIER_VERDICT_BYTES) as *NxTierVerdict
54 var i: i64 = 0
55 while i < n {
56 nx_tier_classify(urls[i], titles[i], v)
57 tier_sc[i] = nx_tier_gain(v)
58 i = i + 1
59 }
60 let bm: *i64 = sys_mmap(n * 8) as *i64
61 nx_bm25_score(texts, text_lens, n, q_terms, q_term_lens, nterms, bm)
62
63 let tier_order: *i64 = sys_mmap(n * 8) as *i64
64 let bm_order: *i64 = sys_mmap(n * 8) as *i64
65 nx_rank_order_desc(tier_sc, n, tier_order)
66 nx_rank_order_desc(bm, n, bm_order)
67
68 let fused: *i64 = sys_mmap(n * 8) as *i64
69 var j: i64 = 0
70 while j < n { fused[j] = 0; j = j + 1 }
71 nx_rrf_add(tier_order, n, fused)
72 nx_rrf_add(bm_order, n, fused)
73 nx_rank_order_desc(fused, n, order_out)
74 return 0
75}