code wiki / _hdl_build / nx_research_relations.nx
nx_research_relations.nx source
↩ module page · 110 lines · 4215 B
1// nx_research_relations.nx -- Researcher EXTRACT, rung 2: DOCUMENT-level claim
2// extraction. Splits a document into sentences and runs the rung-1 relation
3// organ on each, collecting a CLAIM SET (subject -> relation -> object). This is
4// what turns per-sentence extraction into research depth: ~one qualitative claim
5// per relational sentence across a whole page, vs the number-only extractor's
6// handful of digit-facts. Inspectable, sovereign, gated. license_tier: ORIGINAL.
7
8import "nx_syscalls.nx"
9import "nx_research_extract.nx"
10import "nx_research_relation.nx"
11import "nx_research_relation_clean.nx"
12const K_MAGIC_2048: i64 = 2048
13
14// sentence terminators ('.' '!' '?' newline)
15func rel_is_sent_end(c: u8) -> i64 {
16 if c == (46 as u8) { return 1 }
17 if c == (33 as u8) { return 1 }
18 if c == (63 as u8) { return 1 }
19 if c == (10 as u8) { return 1 }
20 return 0
21}
22
23// append NUL-terminated s into out at *off (bounded by out_cap)
24func rel_app(out: *u8, off: *i64, out_cap: i64, s: *u8) -> i64 {
25 var i: i64 = 0
26 while s[i] != (0 as u8) {
27 if off[0] >= out_cap - 1 { return 0 }
28 out[off[0]] = s[i]; off[0] = off[0] + 1; i = i + 1
29 }
30 return 0
31}
32
33// Extract all (subject,relation,object) claims from text[0..n); writes a
34// human-readable claim per line into out; returns the TOTAL claim count
35// (true count even if the report buffer fills -- never silently under-reports).
36func nx_rel_extract_doc(text: *u8, n: i64, out: *u8, out_cap: i64) -> i64 {
37 let subj: *u8 = sys_mmap(K_MAGIC_2048)
38 let obj: *u8 = sys_mmap(K_MAGIC_2048)
39 let off: *i64 = (sys_mmap(8)) as *i64
40 off[0] = 0
41 var count: i64 = 0
42 var s: i64 = 0
43 var i: i64 = 0
44 while i <= n {
45 var atend: i64 = 0
46 if i == n { atend = 1 } else { if rel_is_sent_end(text[i]) == 1 { atend = 1 } }
47 if atend == 1 {
48 let slen: i64 = i - s
49 if slen > 0 {
50 let ri: i64 = nx_rel_extract(text + s, slen, subj, obj)
51 if ri >= 0 {
52 if off[0] < out_cap - 512 {
53 rel_app(out, off, out_cap, subj)
54 rel_app(out, off, out_cap, " -> " as *u8)
55 rel_app(out, off, out_cap, rel_name(ri))
56 rel_app(out, off, out_cap, " -> " as *u8)
57 rel_app(out, off, out_cap, obj)
58 rel_app(out, off, out_cap, "\n" as *u8)
59 }
60 count = count + 1
61 }
62 }
63 s = i + 1
64 }
65 i = i + 1
66 }
67 out[off[0]] = 0 as u8
68 return count
69}
70
71// document-level extraction WITH rung-3 cleanup: emits only clean, non-junk
72// claims (NP-trimmed subjects, pronouns/boilerplate rejected). Returns count.
73func nx_rel_extract_doc_clean(text: *u8, n: i64, out: *u8, out_cap: i64) -> i64 {
74 let subj: *u8 = sys_mmap(K_MAGIC_2048)
75 let obj: *u8 = sys_mmap(K_MAGIC_2048)
76 let cs: *u8 = sys_mmap(K_MAGIC_2048)
77 let co: *u8 = sys_mmap(K_MAGIC_2048)
78 let off: *i64 = (sys_mmap(8)) as *i64
79 off[0] = 0
80 var count: i64 = 0
81 var s: i64 = 0
82 var i: i64 = 0
83 while i <= n {
84 var atend: i64 = 0
85 if i == n { atend = 1 } else { if rel_is_sent_end(text[i]) == 1 { atend = 1 } }
86 if atend == 1 {
87 let slen: i64 = i - s
88 if slen > 0 {
89 let ri: i64 = nx_rel_extract(text + s, slen, subj, obj)
90 if ri >= 0 {
91 if nx_claim_clean(subj, obj, cs, co) == 1 {
92 if off[0] < out_cap - 512 {
93 rel_app(out, off, out_cap, cs)
94 rel_app(out, off, out_cap, " -> " as *u8)
95 rel_app(out, off, out_cap, rel_name(ri))
96 rel_app(out, off, out_cap, " -> " as *u8)
97 rel_app(out, off, out_cap, co)
98 rel_app(out, off, out_cap, "\n" as *u8)
99 }
100 count = count + 1
101 }
102 }
103 }
104 s = i + 1
105 }
106 i = i + 1
107 }
108 out[off[0]] = 0 as u8
109 return count
110}