nx_slopmeter_lib.nx source
↩ module page · 150 lines · 7235 B
1// nx_slopmeter_lib.nx -- MEASURE THE OUTPUT, NOT THE REGISTRY.
2//
3// u2605u2605u2605u2605u2605u2605A BOARD THAT SCORES YOUR TAXONOMY MEASURES YOUR INTENTIONS. nx_writebench reads 625 permil,
4// and every one of its 28 axes asks whether we HAVE a registry, a gate or a lexicon for something.
5// Not one of them looks at a single byte the generator actually produced. The board could reach 1000
6// while the product emits garbage, and nothing in the estate would notice -- because nothing in the
7// estate reads the output.
8//
9// So this organ measures the artifact. It starts with the ONE axis that decides whether small-model
10// prose is usable at all: DEGENERATE SELF-REPETITION. A 4B model asked for 1200 tokens loops -- it
11// re-emits the same phrase with the same rhythm until the budget runs out. Humans call it slop; it
12// is mechanically detectable and needs no judge, no model and no network to see.
13//
14// WHAT THIS IS NOT: a quality score. It cannot tell good prose from bad. It detects a specific,
15// well-defined failure -- the text repeating itself -- and reports how much. Naming it honestly is
16// the difference between an instrument and an advertisement.
17// u2605A METRIC THAT CLAIMS MORE THAN IT MEASURES CORRUPTS EVERY DECISION MADE FROM IT.
18//
19// NO THRESHOLD LIVES HERE, DELIBERATELY. A verdict needs a cutoff, and a cutoff invented at the
20// keyboard is exactly the magic number this estate keeps paying for. The organ REPORTS permil; the
21// cutoff is a policy that belongs to a caller with measurements behind it. What the gate proves
22// instead is MONOTONICITY -- degenerate text must score strictly above varied text -- which is
23// threshold-free and cannot be satisfied by a broken meter.
24//
25// PURE: no syscalls, no allocation of its own, caller owns every buffer.
26// license_tier: ORIGINAL
27// module: nishi-core.write.slopmeter
28// capability: WRITE_OUTPUT_REPETITION_MEASURE
29import "nx_txtscan_lib.nx"
30
31const SM_PERMIL: i64 = 1000
32
33// N-gram width. 3 is not a taste call: a repeated 1-gram is ordinary English ("the", "and"), a
34// repeated 2-gram is common and often correct ("she said"), and a repeated 3-gram is where
35// deliberate phrasing ends and looping begins. Reported width is part of the measurement, so a
36// caller can never mistake one width's number for another's.
37const SM_NGRAM: i64 = 3
38
39func sm_is_wordch(c: i64) -> i64 {
40 if c >= 97 { if c <= 122 { return 1 } }
41 if c >= 65 { if c <= 90 { return 1 } }
42 if c >= 48 { if c <= 57 { return 1 } }
43 if c == 39 { return 1 } // apostrophe: "don't" is one token
44 return 0
45}
46
47// Split buf[0..n) into word tokens, writing start offsets and lengths into caller arrays.
48// Returns the token count, never exceeding cap. Tokens are the unit because BYTE repetition would
49// fire on ordinary whitespace and punctuation and measure nothing.
50func sm_tokenize(buf: *u8, n: i64, starts: *i64, lens: *i64, cap: i64) -> i64 {
51 var cnt: i64 = 0
52 var i: i64 = 0
53 while i < n {
54 if sm_is_wordch(buf[i] as i64) == 1 {
55 let s: i64 = i
56 // u26a0u26a0THIS LOOP TERMINATES WITH A FLAG, AND THE FIRST VERSION DID NOT -- IT SET `i = n + 1`
57 // TO BREAK, WHICH IS THE END-OF-TOKEN POSITION BEING OVERWRITTEN BY THE STOP SIGNAL.
58 // Every token then ran from its first character to the end of the buffer, so the whole
59 // text collapsed into ONE token: the gate read 2/10 with the tokenizer test failing and,
60 // worse, the all-unique-vocabulary test PASSING at a perfect 1000 permil because one
61 // token is trivially distinct from itself. u2605u2605u2605u2605u2605u2605A LOOP THAT SIGNALS TERMINATION BY
62 // OVERWRITING ITS CURSOR DESTROYS THE POSITION IT EXISTS TO REPORT -- and this estate has
63 // now written that bug three times (nx_cwdguard's `q = rn + 1`, rp_name_shaped, here).
64 // u2605A VACUOUS GREEN APPEARS EXACTLY WHERE THE DEFECT MAKES THE QUESTION TRIVIAL.
65 var e: i64 = i
66 var go: i64 = 1
67 while go == 1 {
68 if e >= n { go = 0 } else {
69 if sm_is_wordch(buf[e] as i64) == 0 { go = 0 } else { e = e + 1 }
70 }
71 }
72 if cnt < cap { starts[cnt] = s; lens[cnt] = e - s; cnt = cnt + 1 }
73 i = e
74 } else { i = i + 1 }
75 }
76 return cnt
77}
78
79// case-insensitive equality of two tokens
80func sm_tok_eq(buf: *u8, sa: i64, la: i64, sb: i64, lb: i64) -> i64 {
81 if la != lb { return 0 }
82 var k: i64 = 0
83 while k < la {
84 if tx_lower(buf[sa + k] as i64) != tx_lower(buf[sb + k] as i64) { return 0 }
85 k = k + 1
86 }
87 return 1
88}
89
90// do the SM_NGRAM-token windows at token indices a and b match?
91func sm_gram_eq(buf: *u8, starts: *i64, lens: *i64, a: i64, b: i64) -> i64 {
92 var k: i64 = 0
93 while k < SM_NGRAM {
94 if sm_tok_eq(buf, starts[a + k], lens[a + k], starts[b + k], lens[b + k]) == 0 { return 0 }
95 k = k + 1
96 }
97 return 1
98}
99
100// How many n-gram windows are a REPEAT of an earlier window. Counting "has an earlier twin" rather
101// than "appears more than once" makes the first occurrence innocent and every echo guilty, so a
102// phrase used twice costs 1 and a phrase looped ten times costs 9 -- which is the shape of the
103// failure being measured.
104func sm_repeat_count(buf: *u8, starts: *i64, lens: *i64, ntok: i64) -> i64 {
105 let w: i64 = ntok - SM_NGRAM + 1
106 if w <= 0 { return 0 }
107 var reps: i64 = 0
108 var i: i64 = 1
109 while i < w {
110 var j: i64 = 0
111 var dup: i64 = 0
112 while j < i {
113 if sm_gram_eq(buf, starts, lens, i, j) == 1 { dup = 1; j = i } else { j = j + 1 }
114 }
115 if dup == 1 { reps = reps + 1 }
116 i = i + 1
117 }
118 return reps
119}
120
121// Repetition in exact integer permil of the n-gram windows present.
122// u26a0SHORT TEXT CANNOT BE MEASURED, AND SAYING 0 WOULD BE A LIE. Fewer than SM_NGRAM tokens yields no
123// windows at all; returning 0 would read as "clean" when the truth is "no measurement was possible".
124// SM_UNMEASURABLE is a distinct value so a caller can never average it in as if it were a score.
125const SM_UNMEASURABLE: i64 = 0 - 1
126func sm_repeat_permil(buf: *u8, starts: *i64, lens: *i64, ntok: i64) -> i64 {
127 let w: i64 = ntok - SM_NGRAM + 1
128 if w <= 1 { return SM_UNMEASURABLE }
129 let reps: i64 = sm_repeat_count(buf, starts, lens, ntok)
130 return (reps * SM_PERMIL) / (w - 1)
131}
132
133// Vocabulary breadth: distinct tokens per 1000 tokens. A looping generator collapses this even when
134// it varies word ORDER enough to dodge the n-gram check, so the two axes fail independently --
135// which is the whole reason to carry both rather than trusting one number.
136func sm_distinct_permil(buf: *u8, starts: *i64, lens: *i64, ntok: i64) -> i64 {
137 if ntok <= 0 { return SM_UNMEASURABLE }
138 var distinct: i64 = 0
139 var i: i64 = 0
140 while i < ntok {
141 var j: i64 = 0
142 var seen: i64 = 0
143 while j < i {
144 if sm_tok_eq(buf, starts[i], lens[i], starts[j], lens[j]) == 1 { seen = 1; j = i } else { j = j + 1 }
145 }
146 if seen == 0 { distinct = distinct + 1 }
147 i = i + 1
148 }
149 return (distinct * SM_PERMIL) / ntok
150}