nx_bright_prep.nx source
↩ module page · 346 lines · 15543 B
1// nx_bright_prep.nx -- BRIGHT (huggingface xlangai/BRIGHT, cc-by-4.0) reshaped into the BEIR layout nx_beir_eval reads
2// (search R0d be_bright).
3//
4// usage: nx_bright_prep <split> <examples.parquet> <documents.parquet> <outdir>
5// Writes, through the sovereign parquet reader (nx_parquet_lib):
6// <outdir>/corpus.tsv doc id TAB content (the documents file, id and content, via pq_tsv)
7// <outdir>/queries.tsv query id TAB query (the examples file)
8// <outdir>/qrels/test.tsv the BEIR header line, then query id TAB doc id TAB 1 for every gold_ids element
9// <outdir>/excluded.tsv query id TAB doc id for every excluded_ids element: BRIGHT lists the query's own
10// source documents there, so a retriever must not be credited for finding them
11// <outdir>/../LICENSE the dataset, its source and its licence beside the bytes (a data asset carries its
12// licence in the same directory, the estate's rule for foreign data)
13// Every file is staged as .tmp and renamed into place. Tabs, newlines and carriage returns inside a cell become
14// spaces. A row with a null id or query is COUNTED and skipped; a gold or excluded element whose row has no id is
15// COUNTED as an orphan. The known-answer test is the dataset card's num_examples per split (search.refs brightds26):
16// queries must equal it and corpus rows must equal the documents count. The work lives in bp_run so the gate drives
17// it in-process; main prints the receipt. Exit 0 OK, 1 REFUSED, 2 usage.
18// Measured 2026-09-14 on eleven splits: every count agrees with the card, orphans 0 (search.plan 1789433620).
19// license_tier: ORIGINAL No hw writes (Rule 26).
20import "nx_syscalls.nx"
21import "nx_parquet_lib.nx"
22
23const BP_OK: i64 = 0
24const BP_REFUSED: i64 = 1
25const BP_USAGE: i64 = 2
26const BP_STDOUT: i64 = 1
27const BP_MODE_DIR: i64 = 0x1ed
28const BP_PATH_CAP: i64 = 1024
29const BP_SLASH: i64 = 47
30const BP_TMP: *u8 = ".tmp"
31const BP_F_CORPUS: *u8 = "/corpus.tsv"
32const BP_F_QUERIES: *u8 = "/queries.tsv"
33const BP_D_QRELS: *u8 = "/qrels"
34const BP_F_QRELS: *u8 = "/qrels/test.tsv"
35const BP_F_EXCLUDED: *u8 = "/excluded.tsv"
36const BP_F_LICENSE: *u8 = "/LICENSE"
37const BP_COL_ID: *u8 = "id"
38const BP_COL_CONTENT: *u8 = "content"
39const BP_COL_QUERY: *u8 = "query"
40const BP_COL_GOLD: *u8 = "gold_ids"
41const BP_COL_EXCL: *u8 = "excluded_ids"
42const BP_H1: *u8 = "query-id"
43const BP_H2: *u8 = "corpus-id"
44const BP_H3: *u8 = "score"
45const BP_SCORE: *u8 = "1"
46const BP_LICENSE_TEXT: *u8 = "BRIGHT: A Realistic and Challenging Benchmark for Reasoning-Intensive Retrieval. Source: huggingface.co/datasets/xlangai/BRIGHT (the dataset card is pinned as search.refs brightds26, read 2026-09-14). Licence: Creative Commons Attribution 4.0 (cc-by-4.0), as declared on that card. The files under this directory are derived from the documents and examples parquet files of that dataset by the estate's own reader (nx_parquet_lib) and prep organ (nx_bright_prep), reshaped into the BEIR layout nx_beir_eval reads (corpus.tsv, queries.tsv, qrels/test.tsv, excluded.tsv per split); content is unchanged apart from tabs, newlines and carriage returns inside a cell becoming spaces. This file is written by nx_bright_prep on every run."
47// the receipt slots bp_run fills
48const BR_QUERIES: i64 = 0
49const BR_NULLQ: i64 = 1
50const BR_QDECL: i64 = 2
51const BR_QRELS: i64 = 3
52const BR_EXCL: i64 = 4
53const BR_ORPHANS: i64 = 5
54const BR_CORPUS_DECL: i64 = 6
55const BR_CORPUS_ROWS: i64 = 7
56const BR_CORPUS_WRITTEN: i64 = 8
57const BR_CORPUS_NULL: i64 = 9
58const BR_CORPUS_BYTES: i64 = 10
59const BR_STAGE: i64 = 11 // which stage refused (BR_ST_*), 0 when none
60const BR_WHAT: i64 = 12 // the reader's pq[PQ_WHAT] at the refusal
61const BR_SLOTS: i64 = 13
62// stages, named so a refusal says where
63const BR_ST_NONE: i64 = 0
64const BR_ST_LICENSE: i64 = 1
65const BR_ST_DOCS_OPEN: i64 = 2
66const BR_ST_DOCS_COLUMNS: i64 = 3
67const BR_ST_CORPUS: i64 = 4
68const BR_ST_EX_OPEN: i64 = 5
69const BR_ST_EX_COLUMNS: i64 = 6
70const BR_ST_OUTPUTS: i64 = 7
71const BR_ST_EX_READ: i64 = 8
72const BR_ST_ROWS: i64 = 9
73const BR_ST_FINISH: i64 = 10
74
75func bp_slen(s: *u8) -> i64 {
76 var n: i64 = 0
77 while (s[n] & PQ_BYTE) as i64 != 0 { n = n + 1 }
78 return n
79}
80// dst = base + tail, NUL-terminated; returns the length or PQ_E_CAPACITY
81func bp_path(dst: *u8, base: *u8, tail: *u8) -> i64 {
82 let bl: i64 = bp_slen(base)
83 let tl: i64 = bp_slen(tail)
84 if bl + tl + 1 > BP_PATH_CAP { return PQ_E_CAPACITY }
85 var i: i64 = 0
86 while i < bl { dst[i] = base[i]; i = i + 1 }
87 var j: i64 = 0
88 while j < tl { dst[bl + j] = tail[j]; j = j + 1 }
89 dst[bl + tl] = 0 as u8
90 return bl + tl
91}
92// the parent directory of a path (cut at the last slash) into dst; 0 when there is none
93func bp_parent(dst: *u8, path: *u8) -> i64 {
94 let n: i64 = bp_slen(path)
95 var cut: i64 = PQ_NONE
96 var i: i64 = 0
97 while i < n { if (path[i] & PQ_BYTE) as i64 == BP_SLASH { cut = i } i = i + 1 }
98 if cut <= 0 { return 0 }
99 var k: i64 = 0
100 while k < cut { dst[k] = path[k]; k = k + 1 }
101 dst[cut] = 0 as u8
102 return cut
103}
104// open <path>.tmp for writing; tmp receives the staged name; returns the fd or a refusal
105func bp_open_tmp(path: *u8, tmp: *u8) -> i64 {
106 if bp_path(tmp, path, BP_TMP) < 0 { return PQ_E_CAPACITY }
107 let fd: i64 = sys_openat_wr(tmp, MODE_0644)
108 if fd < 0 { return PQ_E_OPEN }
109 return fd
110}
111func bp_finish(w: *i64, fd: i64, tmp: *u8, path: *u8) -> i64 {
112 wb_flush(w)
113 sys_close(fd)
114 if w[WB_ERR] != 0 { return PQ_E_CAPACITY }
115 if sys_renameat(tmp, path) != 0 { return PQ_E_OPEN }
116 return 0
117}
118func bp_stage_name(st: i64) -> *u8 {
119 if st == BR_ST_LICENSE { return "LICENSE" as *u8 }
120 if st == BR_ST_DOCS_OPEN { return "documents-open" as *u8 }
121 if st == BR_ST_DOCS_COLUMNS { return "documents-columns (id, content)" as *u8 }
122 if st == BR_ST_CORPUS { return "corpus.tsv" as *u8 }
123 if st == BR_ST_EX_OPEN { return "examples-open" as *u8 }
124 if st == BR_ST_EX_COLUMNS { return "examples-columns (id, query, gold_ids, excluded_ids)" as *u8 }
125 if st == BR_ST_OUTPUTS { return "output-files" as *u8 }
126 if st == BR_ST_EX_READ { return "examples-read" as *u8 }
127 if st == BR_ST_ROWS { return "examples-id-and-query-row-counts" as *u8 }
128 if st == BR_ST_FINISH { return "finish (rename into place)" as *u8 }
129 return "none" as *u8
130}
131// the whole job: fills st[BR_*]; returns 0 or a refusal code with st[BR_STAGE] naming the stage
132func bp_run(exf: *u8, docf: *u8, outdir: *u8, st: *i64) -> i64 {
133 var s0: i64 = 0
134 while s0 < BR_SLOTS { st[s0] = 0; s0 = s0 + 1 }
135 st[BR_WHAT] = PQ_NONE
136 let p1: *u8 = sys_mmap(BP_PATH_CAP)
137 let p2: *u8 = sys_mmap(BP_PATH_CAP)
138 let p3: *u8 = sys_mmap(BP_PATH_CAP)
139 let t1: *u8 = sys_mmap(BP_PATH_CAP)
140 let t2: *u8 = sys_mmap(BP_PATH_CAP)
141 let t3: *u8 = sys_mmap(BP_PATH_CAP)
142 let parent: *u8 = sys_mmap(BP_PATH_CAP)
143 let pq: *i64 = sys_mmap(PQ_SLOTS * PQ_I64) as *i64
144 // directories (an existing one answers EEXIST, which is the state wanted)
145 if bp_parent(parent, outdir) > 0 { sys_mkdir(parent, BP_MODE_DIR) }
146 sys_mkdir(outdir, BP_MODE_DIR)
147 bp_path(p1, outdir, BP_D_QRELS)
148 sys_mkdir(p1, BP_MODE_DIR)
149 // the licence beside the bytes
150 if bp_parent(parent, outdir) > 0 {
151 bp_path(p1, parent, BP_F_LICENSE)
152 let lfd: i64 = bp_open_tmp(p1, t1)
153 if lfd < 0 { st[BR_STAGE] = BR_ST_LICENSE; return lfd }
154 let lw: *i64 = wb_new(lfd)
155 wb_puts(lw, BP_LICENSE_TEXT)
156 wb_byte(lw, PQ_NL)
157 let lrc: i64 = bp_finish(lw, lfd, t1, p1)
158 if lrc < 0 { st[BR_STAGE] = BR_ST_LICENSE; return lrc }
159 }
160 // corpus.tsv from the documents file
161 let rcd: i64 = pq_open(pq, docf)
162 if rcd < 0 { st[BR_STAGE] = BR_ST_DOCS_OPEN; st[BR_WHAT] = pq[PQ_WHAT]; return rcd }
163 let lid: i64 = pq_leaf_named(pq, BP_COL_ID)
164 let lct: i64 = pq_leaf_named(pq, BP_COL_CONTENT)
165 if lid < 0 || lct < 0 { st[BR_STAGE] = BR_ST_DOCS_COLUMNS; st[BR_WHAT] = lid; return PQ_E_ARG }
166 let stats: *i64 = sys_mmap(PT_SLOTS * PQ_I64) as *i64
167 bp_path(p1, outdir, BP_F_CORPUS)
168 let rct: i64 = pq_tsv(pq, lid, lct, p1, stats)
169 st[BR_CORPUS_ROWS] = stats[PT_ROWS]
170 st[BR_CORPUS_WRITTEN] = stats[PT_WRITTEN]
171 st[BR_CORPUS_NULL] = stats[PT_NULLROWS]
172 st[BR_CORPUS_BYTES] = stats[PT_BYTES]
173 st[BR_CORPUS_DECL] = pq[PQ_NROWS]
174 if rct < 0 { st[BR_STAGE] = BR_ST_CORPUS; st[BR_WHAT] = pq[PQ_WHAT]; return rct }
175 // the examples file
176 let pqe: *i64 = sys_mmap(PQ_SLOTS * PQ_I64) as *i64
177 let rce: i64 = pq_open(pqe, exf)
178 if rce < 0 { st[BR_STAGE] = BR_ST_EX_OPEN; st[BR_WHAT] = pqe[PQ_WHAT]; return rce }
179 st[BR_QDECL] = pqe[PQ_NROWS]
180 let eid: i64 = pq_leaf_named(pqe, BP_COL_ID)
181 let eq: i64 = pq_leaf_named(pqe, BP_COL_QUERY)
182 let eg: i64 = pq_leaf_named(pqe, BP_COL_GOLD)
183 let ex: i64 = pq_leaf_named(pqe, BP_COL_EXCL)
184 if eid < 0 || eq < 0 || eg < 0 || ex < 0 { st[BR_STAGE] = BR_ST_EX_COLUMNS; st[BR_WHAT] = eid; return PQ_E_ARG }
185 bp_path(p1, outdir, BP_F_QUERIES)
186 bp_path(p2, outdir, BP_F_QRELS)
187 bp_path(p3, outdir, BP_F_EXCLUDED)
188 let fq: i64 = bp_open_tmp(p1, t1)
189 if fq < 0 { st[BR_STAGE] = BR_ST_OUTPUTS; return fq }
190 let fr: i64 = bp_open_tmp(p2, t2)
191 if fr < 0 { st[BR_STAGE] = BR_ST_OUTPUTS; return fr }
192 let fx: i64 = bp_open_tmp(p3, t3)
193 if fx < 0 { st[BR_STAGE] = BR_ST_OUTPUTS; return fx }
194 let wq: *i64 = wb_new(fq)
195 let wr: *i64 = wb_new(fr)
196 let wx: *i64 = wb_new(fx)
197 wb_puts(wr, BP_H1)
198 wb_byte(wr, PQ_TAB)
199 wb_puts(wr, BP_H2)
200 wb_byte(wr, PQ_TAB)
201 wb_puts(wr, BP_H3)
202 wb_byte(wr, PQ_NL)
203 var r: i64 = 0
204 while r < pqe[PQ_NRG] {
205 let pid: *i64 = pr_alloc(pqe, r, eid)
206 let pqy: *i64 = pr_alloc(pqe, r, eq)
207 let pg: *i64 = pr_alloc(pqe, r, eg)
208 let px: *i64 = pr_alloc(pqe, r, ex)
209 let r1: i64 = pq_read_column(pqe, r, eid, pid)
210 if r1 < 0 { st[BR_STAGE] = BR_ST_EX_READ; st[BR_WHAT] = pqe[PQ_WHAT]; return r1 }
211 let r2: i64 = pq_read_column(pqe, r, eq, pqy)
212 if r2 < 0 { st[BR_STAGE] = BR_ST_EX_READ; st[BR_WHAT] = pqe[PQ_WHAT]; return r2 }
213 let r3: i64 = pq_read_column(pqe, r, eg, pg)
214 if r3 < 0 { st[BR_STAGE] = BR_ST_EX_READ; st[BR_WHAT] = pqe[PQ_WHAT]; return r3 }
215 let r4: i64 = pq_read_column(pqe, r, ex, px)
216 if r4 < 0 { st[BR_STAGE] = BR_ST_EX_READ; st[BR_WHAT] = pqe[PQ_WHAT]; return r4 }
217 if pid[PR_N] != pqy[PR_N] { st[BR_STAGE] = BR_ST_ROWS; return PQ_E_LEVELS }
218 let ida: *u8 = pid[PR_ARENA] as *u8
219 let ioff: *i64 = pid[PR_OFF] as *i64
220 let ilen: *i64 = pid[PR_LEN] as *i64
221 let qa: *u8 = pqy[PR_ARENA] as *u8
222 let qoff: *i64 = pqy[PR_OFF] as *i64
223 let qlen: *i64 = pqy[PR_LEN] as *i64
224 var i: i64 = 0
225 while i < pid[PR_N] {
226 if ioff[i] >= 0 && qoff[i] >= 0 {
227 wb_cell(wq, ida, ioff[i], ilen[i])
228 wb_byte(wq, PQ_TAB)
229 wb_cell(wq, qa, qoff[i], qlen[i])
230 wb_byte(wq, PQ_NL)
231 st[BR_QUERIES] = st[BR_QUERIES] + 1
232 } else { st[BR_NULLQ] = st[BR_NULLQ] + 1 }
233 i = i + 1
234 }
235 let ga: *u8 = pg[PR_ARENA] as *u8
236 let goff: *i64 = pg[PR_OFF] as *i64
237 let glen: *i64 = pg[PR_LEN] as *i64
238 let grow: *i64 = pg[PR_ROW] as *i64
239 var e: i64 = 0
240 while e < pg[PR_N] {
241 if goff[e] >= 0 {
242 let row: i64 = grow[e]
243 if row >= 0 && row < pid[PR_N] && ioff[row] >= 0 {
244 wb_cell(wr, ida, ioff[row], ilen[row])
245 wb_byte(wr, PQ_TAB)
246 wb_cell(wr, ga, goff[e], glen[e])
247 wb_byte(wr, PQ_TAB)
248 wb_puts(wr, BP_SCORE)
249 wb_byte(wr, PQ_NL)
250 st[BR_QRELS] = st[BR_QRELS] + 1
251 } else { st[BR_ORPHANS] = st[BR_ORPHANS] + 1 }
252 }
253 e = e + 1
254 }
255 let xa: *u8 = px[PR_ARENA] as *u8
256 let xoff: *i64 = px[PR_OFF] as *i64
257 let xlen: *i64 = px[PR_LEN] as *i64
258 let xrow: *i64 = px[PR_ROW] as *i64
259 var e2: i64 = 0
260 while e2 < px[PR_N] {
261 if xoff[e2] >= 0 {
262 let row2: i64 = xrow[e2]
263 if row2 >= 0 && row2 < pid[PR_N] && ioff[row2] >= 0 {
264 wb_cell(wx, ida, ioff[row2], ilen[row2])
265 wb_byte(wx, PQ_TAB)
266 wb_cell(wx, xa, xoff[e2], xlen[e2])
267 wb_byte(wx, PQ_NL)
268 st[BR_EXCL] = st[BR_EXCL] + 1
269 } else { st[BR_ORPHANS] = st[BR_ORPHANS] + 1 }
270 }
271 e2 = e2 + 1
272 }
273 pr_free(pid)
274 pr_free(pqy)
275 pr_free(pg)
276 pr_free(px)
277 r = r + 1
278 }
279 let f1: i64 = bp_finish(wq, fq, t1, p1)
280 if f1 < 0 { st[BR_STAGE] = BR_ST_FINISH; return f1 }
281 let f2: i64 = bp_finish(wr, fr, t2, p2)
282 if f2 < 0 { st[BR_STAGE] = BR_ST_FINISH; return f2 }
283 let f3: i64 = bp_finish(wx, fx, t3, p3)
284 if f3 < 0 { st[BR_STAGE] = BR_ST_FINISH; return f3 }
285 return 0
286}
287// the receipt's verdict: queries equal the file's declared rows, corpus written equals the documents file's rows,
288// no orphan
289func bp_verdict(st: *i64) -> i64 {
290 if st[BR_QUERIES] != st[BR_QDECL] { return 0 }
291 if st[BR_CORPUS_WRITTEN] != st[BR_CORPUS_DECL] { return 0 }
292 if st[BR_ORPHANS] != 0 { return 0 }
293 return 1
294}
295
296func main(argc: i64, argv: *i64) -> i64 {
297 let w: *i64 = wb_new(BP_STDOUT)
298 if argc < 5 {
299 wb_puts(w, "usage: nx_bright_prep <split> <examples.parquet> <documents.parquet> <outdir>" as *u8)
300 wb_byte(w, PQ_NL)
301 wb_flush(w)
302 sys_exit(BP_USAGE)
303 return BP_USAGE
304 }
305 let split: *u8 = argv[1] as *u8
306 let st: *i64 = sys_mmap(BR_SLOTS * PQ_I64) as *i64
307 let rc: i64 = bp_run(argv[2] as *u8, argv[3] as *u8, argv[4] as *u8, st)
308 wb_puts(w, "NX-BRIGHT-PREP split=" as *u8)
309 wb_puts(w, split)
310 wb_byte(w, PQ_SPACE)
311 wb_kv(w, "queries" as *u8, st[BR_QUERIES])
312 wb_kv(w, "null_queries" as *u8, st[BR_NULLQ])
313 wb_kv(w, "queries_declared" as *u8, st[BR_QDECL])
314 wb_kv(w, "qrels" as *u8, st[BR_QRELS])
315 wb_kv(w, "excluded" as *u8, st[BR_EXCL])
316 wb_kv(w, "orphans" as *u8, st[BR_ORPHANS])
317 wb_kv(w, "corpus_declared" as *u8, st[BR_CORPUS_DECL])
318 wb_kv(w, "corpus_rows" as *u8, st[BR_CORPUS_ROWS])
319 wb_kv(w, "corpus_written" as *u8, st[BR_CORPUS_WRITTEN])
320 wb_kv(w, "corpus_null_rows" as *u8, st[BR_CORPUS_NULL])
321 wb_kv(w, "corpus_bytes" as *u8, st[BR_CORPUS_BYTES])
322 wb_puts(w, "outdir=" as *u8)
323 wb_puts(w, argv[4] as *u8)
324 wb_byte(w, PQ_SPACE)
325 if rc < 0 {
326 wb_puts(w, "REFUSED " as *u8)
327 wb_puts(w, bp_stage_name(st[BR_STAGE]))
328 wb_byte(w, PQ_SPACE)
329 wb_puts(w, pq_errname(rc))
330 wb_byte(w, PQ_SPACE)
331 wb_kv(w, "code" as *u8, rc)
332 wb_kv(w, "what" as *u8, st[BR_WHAT])
333 wb_puts(w, "verdict=REFUSED" as *u8)
334 wb_byte(w, PQ_NL)
335 wb_flush(w)
336 sys_exit(BP_REFUSED)
337 return BP_REFUSED
338 }
339 let ok: i64 = bp_verdict(st)
340 if ok == 1 { wb_puts(w, "verdict=OK" as *u8) } else { wb_puts(w, "verdict=REFUSED (counts disagree with the files' own declarations)" as *u8) }
341 wb_byte(w, PQ_NL)
342 wb_flush(w)
343 if ok == 1 { sys_exit(BP_OK); return BP_OK }
344 sys_exit(BP_REFUSED)
345 return BP_REFUSED
346}