nx_research_verify_synth.nx source
↩ module page · 136 lines · 6491 B
1// nx_research_verify_synth.nx -- S1 <-> S2 INTEGRATION: the self-verifying researcher. It runs S1 (grounded
2// synthesis, nx_research_synth_qwen) and then, for every NUMERIC sentence-claim, checks that the model's number
3// is actually PRESENT (within a tight tolerance) in the source that claim cites -- CONFIRMED if present,
4// DISCREDITED if the source has numbers but not that one (the model fabricated/altered it), UNVERIFIABLE if the
5// claim is uncited or the source has no numbers. A synthesized answer thus grades ITS OWN numeric claims against
6// the evidence, at $0. Composes S1 (rsq_synth / rsq_sentence_cite) + S2 (cvc_iabs, the verdict discipline).
7// HONEST SCOPE: this catches numeric FABRICATION/ALTERATION (the common hallucination). Metric MISATTRIBUTION
8// (right number, wrong metric) needs S2's explicit-pattern path (nx_claim_verify_core cvc_verify_text with a
9// caller-supplied pattern, as in nx_research_refute). license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_research_synth_qwen.nx"
12import "nx_claim_verify_core.nx"
13import "nx_text_sentences.nx"
14
15// parse the number at buf[off] as TENTHS and report its end offset in endp[0]. off must point at a digit.
16func rvs_num_at(buf: *u8, blen: i64, off: i64, endp: *i64) -> i64 {
17 var i: i64 = off
18 var whole: i64 = 0
19 var any: i64 = 0
20 var go: i64 = 1
21 while go == 1 {
22 go = 0
23 if i < blen {
24 let c: i64 = buf[i] as i64 & 0xff
25 if c >= 48 { if c <= 57 { whole = whole*10 + (c-48); any = 1; i = i + 1; go = 1 } }
26 else { if c == 44 { if any == 1 { if i+1 < blen { let nd: i64 = buf[i+1] as i64 & 0xff; if nd >= 48 { if nd <= 57 { i = i + 1; go = 1 } } } } } } // thousands separator BETWEEN digits (bench H1): 107,785 -> 107785
27 }
28 }
29 if any == 0 { endp[0] = off + 1; return 0-1 }
30 var tenths: i64 = whole * 10
31 if i < blen { if (buf[i] as i64 & 0xff) == 46 { if i+1 < blen { let d: i64 = buf[i+1] as i64 & 0xff; if d >= 48 { if d <= 57 { tenths = tenths + (d-48); i = i + 2 } } } } }
32 endp[0] = i
33 return tenths
34}
35// first number (tenths) in span [s,e), or -1 if none.
36func rvs_first_number(buf: *u8, s: i64, e: i64) -> i64 {
37 let ep: *i64 = sys_mmap(16) as *i64
38 var i: i64 = s
39 while i < e {
40 let c: i64 = buf[i] as i64 & 0xff
41 if c == 91 { // '[' -- skip the whole citation token so [1] is NOT read as a number
42 var j: i64 = i + 1
43 var go: i64 = 1
44 while go == 1 { go = 0; if j < e { if (buf[j] as i64 & 0xff) != 93 { j = j + 1; go = 1 } } }
45 if j < e { i = j + 1 } else { i = e }
46 } else {
47 if c >= 48 { if c <= 57 { return rvs_num_at(buf, e, i, ep) } }
48 i = i + 1
49 }
50 }
51 return 0-1
52}
53// walk EVERY number in span [s,e) (skipping [n] citation tokens); each must be near-present in the cited source.
54// outp[0]=numbers found, outp[1]=all-near (1 when every number is present; the SECOND-NUMBER LAUNDERING kill --
55// judgment bench N6: a true first number must not launder a fabricated second one). hp = rvs_src_has_near scratch.
56func rvs_span_numbers_near(ans: *u8, s: i64, e: i64, src: *u8, sl: i64, tol: i64, hp: *i64, outp: *i64) -> i64 {
57 let ep: *i64 = sys_mmap(16) as *i64
58 var found: i64 = 0
59 var allnear: i64 = 1
60 var i: i64 = s
61 while i < e {
62 let c: i64 = ans[i] as i64 & 0xff
63 if c == 91 { // '[' -- skip the citation token
64 var j: i64 = i + 1
65 var go: i64 = 1
66 while go == 1 { go = 0; if j < e { if (ans[j] as i64 & 0xff) != 93 { j = j + 1; go = 1 } } }
67 if j < e { i = j + 1 } else { i = e }
68 } else {
69 if c >= 48 { if c <= 57 {
70 let num: i64 = rvs_num_at(ans, e, i, ep)
71 if num >= 0 { found = found + 1; if rvs_src_has_near(src, sl, num, tol, hp) == 0 { allnear = 0 } }
72 i = ep[0]
73 } else { i = i + 1 } } else { i = i + 1 }
74 }
75 }
76 outp[0] = found
77 outp[1] = allnear
78 return found
79}
80// does the claimed value appear (within tol) among the numbers in src? has[0]=1 if src has ANY number.
81func rvs_src_has_near(src: *u8, slen: i64, claimed: i64, tol: i64, has: *i64) -> i64 {
82 has[0] = 0
83 var near: i64 = 0
84 let ep: *i64 = sys_mmap(16) as *i64
85 var i: i64 = 0
86 while i < slen {
87 let c: i64 = src[i] as i64 & 0xff
88 if c >= 48 { if c <= 57 {
89 let num: i64 = rvs_num_at(src, slen, i, ep)
90 if num >= 0 { has[0] = 1; if cvc_iabs(num - claimed) <= tol { near = 1 } }
91 i = ep[0]
92 } else { i = i + 1 } } else { i = i + 1 }
93 }
94 return near
95}
96// grade each numeric claim against its cited source. out[0]=numeric out[1]=confirmed out[2]=discredited
97// out[3]=unverifiable. tol in tenths. returns numeric-claim count.
98func rvs_verify_answer(ans: *u8, alen: i64, srcv: *i64, nsrc: i64, tol: i64, out: *i64) -> i64 {
99 var numeric: i64 = 0
100 var cf: i64 = 0
101 var ds: i64 = 0
102 var uv: i64 = 0
103 let op: *i64 = sys_mmap(32) as *i64
104 let hp: *i64 = sys_mmap(32) as *i64
105 let np: *i64 = sys_mmap(32) as *i64
106 var s: i64 = 0
107 while s < alen {
108 let e: i64 = txt_sentence_end(ans, s, alen)
109 let claimed: i64 = rvs_first_number(ans, s, e)
110 if claimed >= 0 {
111 numeric = numeric + 1
112 let c: i64 = rsq_sentence_cite(ans, s, e, nsrc, op)
113 if c >= 1 {
114 let src: *u8 = srcv[c-1] as *u8
115 let sl: i64 = rsq_len(src)
116 rvs_span_numbers_near(ans, s, e, src, sl, tol, hp, np) // EVERY number must be near (bench N6 laundering kill)
117 if np[1] == 1 { cf = cf + 1 } else { if hp[0] == 1 { ds = ds + 1 } else { uv = uv + 1 } }
118 } else { uv = uv + 1 }
119 }
120 s = e + 1
121 }
122 out[0] = numeric
123 out[1] = cf
124 out[2] = ds
125 out[3] = uv
126 return numeric
127}
128// the full self-verifying researcher: synthesize (S1) then grade its numeric claims (S2). model-gated.
129// returns the answer byte-length (answer in ans, report in out), or -1 if the model isn't ready.
130func rvs_answer(q: *u8, srcv: *i64, nsrc: i64, tol: i64, ans: *u8, out: *i64) -> i64 {
131 if rsq_ready() == 0 { if rsq_load() != 0 { return 0-1 } }
132 let al: i64 = rsq_synth(q, srcv, nsrc, ans)
133 if al <= 0 { return 0-1 }
134 rvs_verify_answer(ans, al, srcv, nsrc, tol, out)
135 return al
136}