unparallelled commited on
Commit
411a8a3
·
verified ·
1 Parent(s): e9bd690

Upload source/files/in2_gate.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. source/files/in2_gate.py +141 -0
source/files/in2_gate.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ in2_gate.py -- the EXACT layout gate for in2_gen.py output. No GPU, no CUDA.
4
+
5
+ This is the only exact pre-flight check in the IN2 pilot. The step-0 loss check
6
+ was demoted to a diagnostic because its two hypotheses sit only ~0.22 nats apart
7
+ (no-induction 4.147 vs strong-induction 3.925, against a 3.901 plain baseline),
8
+ which cannot validate a layout. These assertions can.
9
+
10
+ Checks, per arm dir:
11
+ 1 file size is exactly examples*T*2 bytes (headerless uint16)
12
+ 2 every token in [0, VOCAB)
13
+ 3 no answer span intrudes into the last PAD_TAIL offsets of its example
14
+ 4 planted spans (needle / probe+answer / decoy) never overlap
15
+ 5 RETRIEVAL IS ACTUALLY POSSIBLE: the tokens at the probe equal the needle's
16
+ key, and the tokens at the answer equal the needle's value. If this fails
17
+ the task is unsolvable and the whole experiment is void.
18
+ 6 batch alignment: re-derive x/y exactly as DataLoaderLite::next_batch does
19
+ (x=buf[i], y=buf[i+1], stride B*T*dp) and assert every example boundary
20
+ lands on a row boundary
21
+ 7 arm-specific distance invariants (b: all == span, c: all >= d_min)
22
+
23
+ Cross-arm:
24
+ 8 arms B and C have BIT-IDENTICAL answer_start histograms -- the discipline
25
+ the whole B-vs-C contrast rests on
26
+
27
+ Usage
28
+ python3 in2_gate.py --dirs /tmp/in2b /tmp/in2c --B 2 --dp 2
29
+ """
30
+ import argparse, array, json, os, sys
31
+
32
+ VOCAB = 50304
33
+ fails = []
34
+
35
+
36
+ def check(cond, msg):
37
+ print((" ok " if cond else " FAIL ") + msg)
38
+ if not cond:
39
+ fails.append(msg)
40
+
41
+
42
+ def load(d, split="train"):
43
+ js = [f for f in os.listdir(d) if f.endswith(".json") and f"_{split}_" in f]
44
+ if len(js) != 1:
45
+ raise SystemExit(f"{d}: expected exactly one {split} manifest, found {js}")
46
+ man = json.load(open(os.path.join(d, js[0])))
47
+ toks = array.array("H")
48
+ for sp in man.get("shards", [man["bin"]]):
49
+ with open(sp, "rb") as f:
50
+ toks.fromfile(f, os.path.getsize(sp) // 2)
51
+ return man, toks
52
+
53
+
54
+ def gate_one(d, B, dp, split="train"):
55
+ man, toks = load(d, split)
56
+ T, n_ex, arm, span = man["T"], man["examples"], man["arm"], man["span"]
57
+ kl, vl, pad = man["key_len"], man["val_len"], man["pad_tail"]
58
+ print(f"\n=== arm {arm} T={T} examples={n_ex} K={man['K']} ===")
59
+
60
+ tot = sum(os.path.getsize(sp) for sp in man.get("shards", [man["bin"]]))
61
+ check(tot == n_ex * T * 2,
62
+ f"1 total size across {len(man.get('shards',[1]))} shard(s) == examples*T*2 "
63
+ f"({n_ex*T*2} bytes, got {tot})")
64
+ lo, hi = min(toks), max(toks)
65
+ check(lo >= 0 and hi < VOCAB, f"2 tokens in [0,{VOCAB}) (min {lo}, max {hi})")
66
+
67
+ bad_pad = bad_ovl = bad_ret = bad_dist = 0
68
+ for ei, recs in enumerate(man["records"]):
69
+ base = ei * T
70
+ spans = []
71
+ for r in recs:
72
+ a0, a1 = r["answer_start"], r["answer_start"] + vl
73
+ if a1 > T - pad:
74
+ bad_pad += 1
75
+ spans.append((r["needle_start"], r["needle_start"] + span))
76
+ spans.append((r["probe_start"], r["probe_start"] + span))
77
+ # 5: the probe must reproduce the needle's key, the answer its value
78
+ nk = toks[base + r["needle_start"]: base + r["needle_start"] + kl]
79
+ nv = toks[base + r["needle_start"] + kl: base + r["needle_start"] + span]
80
+ pk = toks[base + r["probe_start"]: base + r["probe_start"] + kl]
81
+ av = toks[base + a0: base + a1]
82
+ if nk != pk or nv != av:
83
+ bad_ret += 1
84
+ if arm == "b" and r["distance"] != span:
85
+ bad_dist += 1
86
+ if arm == "c" and r["distance"] < man["d_min"]:
87
+ bad_dist += 1
88
+ spans.sort()
89
+ for (s0, e0), (s1, _) in zip(spans, spans[1:]):
90
+ if s1 < e0:
91
+ bad_ovl += 1
92
+ check(bad_pad == 0, f"3 no answer within the last {pad} offsets ({bad_pad} bad)")
93
+ check(bad_ovl == 0, f"4 planted spans never overlap ({bad_ovl} bad)")
94
+ check(bad_ret == 0, f"5 RETRIEVAL POSSIBLE: probe==key and answer==value ({bad_ret} bad)")
95
+ check(bad_dist == 0, f"7 arm-{arm} distance invariant ({bad_dist} bad)")
96
+
97
+ # 6: DataLoaderLite windowing. next_batch reads B*T+1 tokens and sets
98
+ # y[i]=buf[i+1]; pos_ advances by B*T*world. Example boundaries must land on
99
+ # row boundaries or an example would straddle two rows.
100
+ stride = B * T * dp
101
+ check(stride % T == 0, f"6a batch stride {stride} is a multiple of T={T}")
102
+ check((n_ex * T) % stride == 0,
103
+ f"6b total {n_ex*T} tokens is a whole number of batches (stride {stride})")
104
+ if len(toks) >= B * T + 1:
105
+ x0 = toks[0:B * T]
106
+ y0 = toks[1:B * T + 1]
107
+ rows_ok = all(x0[r * T] == toks[r * T] for r in range(B))
108
+ check(rows_ok, f"6c row r starts at token r*T for all B={B} rows")
109
+ check(y0[T - 1] == toks[T], "6d y[T-1] targets the next example's first token "
110
+ "(why PAD_TAIL exists)")
111
+ return man
112
+
113
+
114
+ def main():
115
+ ap = argparse.ArgumentParser()
116
+ ap.add_argument("--dirs", nargs="+", required=True)
117
+ ap.add_argument("--B", type=int, default=2)
118
+ ap.add_argument("--dp", type=int, default=2)
119
+ ap.add_argument("--split", default="train", choices=["train", "val"])
120
+ args = ap.parse_args()
121
+
122
+ mans = {}
123
+ for d in args.dirs:
124
+ m = gate_one(d, args.B, args.dp, args.split)
125
+ mans[m["arm"]] = m
126
+
127
+ if "b" in mans and "c" in mans:
128
+ print("\n=== cross-arm ===")
129
+ hb, hc = mans["b"]["answer_start_hist"], mans["c"]["answer_start_hist"]
130
+ check(hb == hc, "8 arms B and C have BIT-IDENTICAL answer_start histograms "
131
+ f"({len(hb)} vs {len(hc)} distinct offsets)")
132
+ check(mans["b"]["seed"] == mans["c"]["seed"], "8b same seed")
133
+ check(mans["b"]["answer_tokens"] == mans["c"]["answer_tokens"],
134
+ "8c same answer-token count")
135
+
136
+ print(f"\n{'ALL PASS' if not fails else str(len(fails)) + ' FAILURE(S)'}")
137
+ return 1 if fails else 0
138
+
139
+
140
+ if __name__ == "__main__":
141
+ sys.exit(main())