Cion-lab commited on
Commit
1f22abe
·
verified ·
1 Parent(s): bc34e7d

phase4_prep: pins at a813e5c7 + bounded-readback rehearsal stage / tee-prefix fix

Browse files
Files changed (1) hide show
  1. kernels/phase4_prep.py +86 -5
kernels/phase4_prep.py CHANGED
@@ -13,18 +13,18 @@ import hashlib, json, os, subprocess, sys, time
13
 
14
  os.chdir("/kaggle/working")
15
  sys.path.insert(0, "/kaggle/working")
16
- REV = os.environ.get("OUNCE100M_REV") or "7570b7b264f82a536a7a0f8f3e45241dca10d883"
17
  WANT = {
18
  "ounce100m_credentials.py": ("ounce100m_credentials.py",
19
  "6525f62f03f2d73650a1eb4f70fcb52d1194caad4ca88b2d8bd8fd54f88339b6"),
20
  "shard_dataset.py": ("train/shard_dataset.py",
21
  "f35653bf4c8f2cfe7bb0c2c7835e308505fb5a84b4eb002d0f82f2cada768ca6"),
22
  "hubckpt.py": ("train/hubckpt.py",
23
- "568c31b300906cb8d78a59ef890baa9731b18e064e3d69b0eaea4b45c546f23e"),
24
  "train_ounce100m.py": ("train/train_ounce100m.py",
25
  "744259c7519e5a12c2d2bf4dca534fa39f7ddb7e6689e1a5a9e0925bfaa640aa"),
26
  "phase4_session.py": ("kernels/phase4_session.py",
27
- "28fb3bb477f956b5dab804d8d335acf85193900116ee8d0c520139dad495e112"),
28
  }
29
  BASE = "https://huggingface.co/Cion-lab/ounce100m-code/resolve/" + REV
30
  for p, (rp, want) in sorted(WANT.items()):
@@ -219,6 +219,87 @@ rc3, _ = run([sys.executable, "-c",
219
  "print('TRAINER_HELP_RC', p.returncode, 'lines', len((p.stdout or '').splitlines()))\n"
220
  "assert p.returncode == 0, (p.stdout or '')[-1500:] + (p.stderr or '')[-1500:]\n"],
221
  "CURSOR_AND_IMPORT", 900)
222
- print("VERDICT PHASE4_PREP rc_launcher", rc1, "rc_check", rc2, "rc_cursor", rc3,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  "seconds", round(time.time() - T0, 1), flush=True)
224
- raise SystemExit(0 if (rc1 == rc2 == rc3 == 0) else 4)
 
13
 
14
  os.chdir("/kaggle/working")
15
  sys.path.insert(0, "/kaggle/working")
16
+ REV = os.environ.get("OUNCE100M_REV") or "a813e5c7fb7539a0586756c76b95f7520934f7a0"
17
  WANT = {
18
  "ounce100m_credentials.py": ("ounce100m_credentials.py",
19
  "6525f62f03f2d73650a1eb4f70fcb52d1194caad4ca88b2d8bd8fd54f88339b6"),
20
  "shard_dataset.py": ("train/shard_dataset.py",
21
  "f35653bf4c8f2cfe7bb0c2c7835e308505fb5a84b4eb002d0f82f2cada768ca6"),
22
  "hubckpt.py": ("train/hubckpt.py",
23
+ "a21de427b9c7586d3cc104e80d230a085d00907829fe1148d0b1ddbec9f4d20a"),
24
  "train_ounce100m.py": ("train/train_ounce100m.py",
25
  "744259c7519e5a12c2d2bf4dca534fa39f7ddb7e6689e1a5a9e0925bfaa640aa"),
26
  "phase4_session.py": ("kernels/phase4_session.py",
27
+ "925ef1f160dcd7ae52090d10fbb7e8abca1f52f3b087d36a6fc35fad8a5de6e1"),
28
  }
29
  BASE = "https://huggingface.co/Cion-lab/ounce100m-code/resolve/" + REV
30
  for p, (rp, want) in sorted(WANT.items()):
 
219
  "print('TRAINER_HELP_RC', p.returncode, 'lines', len((p.stdout or '').splitlines()))\n"
220
  "assert p.returncode == 0, (p.stdout or '')[-1500:] + (p.stderr or '')[-1500:]\n"],
221
  "CURSOR_AND_IMPORT", 900)
222
+
223
+ # Stage 4 -- checkpoint verification against real Hub bytes, on the theory that a gate which authorises
224
+ # deleting the only local copy of a checkpoint should be tested where failing is free. Probe v5 measured
225
+ # the old whole-object read-back at `push+verify=797.7s` for an 850 MB optimizer.pt (and 26 s for the same
226
+ # cycle once the CDN was warm), so the read-back is now two bounded Range requests; this proves the
227
+ # replacement still says yes to the 1.27 GB the probe really pushed and still says no three different ways.
228
+ # PREP_VERIFY_REPO exists because the probe repos are scratch: point it at `Cion-lab/ounce100m-ckpt` plus a
229
+ # `ckpt/checkpoint-N` once the run has one and this stage outlives them.
230
+ VERIFY = """
231
+ import json, os, sys, time
232
+ sys.path.insert(0, "/kaggle/working")
233
+ import hubckpt
234
+ from huggingface_hub import snapshot_download
235
+ REPO = os.environ.get("PREP_VERIFY_REPO") or "Cion-lab/ounce100m-ckpt-probe-0920-0747"
236
+ SUB = os.environ.get("PREP_VERIFY_SUB") or "ckpt/checkpoint-10"
237
+ d = "/kaggle/working/verify_subject"
238
+ t0 = time.time()
239
+ snapshot_download(repo_id=REPO, repo_type="dataset", allow_patterns=SUB + "/*", local_dir=d,
240
+ max_workers=4)
241
+ local = os.path.join(d, SUB)
242
+ print("GOT", len(os.listdir(local)), "files from", REPO, SUB, "in", round(time.time() - t0, 1), "s",
243
+ flush=True)
244
+ assert os.path.exists(os.path.join(local, "model.safetensors")), sorted(os.listdir(local))
245
+
246
+ t0 = time.time()
247
+ v = hubckpt.verify_checkpoint(REPO, local, SUB, repo_type="dataset")
248
+ secs = round(time.time() - t0, 1)
249
+ print("VERIFY_CLEAN ok", v["ok"], "readback_ok", v["readback_ok"], "seconds", secs,
250
+ json.dumps({k: v[k] for k in ("n_local", "n_hub", "missing", "mismatch", "extra", "readback")},
251
+ default=str)[:600], flush=True)
252
+ assert v["ok"] and v["readback_ok"], v
253
+ assert secs < 180, f"verification took {secs}s -- the bounded read-back was supposed to make this cheap"
254
+ rb = v["readback"]
255
+ assert rb["path"] == "optimizer.pt" and rb["bytes"] < (10 << 20) and len(rb["ranges"]) == 2, rb
256
+
257
+ # 1. A byte the Hub does not have: the local sha256 stops matching the stored lfs.oid.
258
+ p = os.path.join(local, "optimizer.pt")
259
+ with open(p, "r+b") as fh:
260
+ fh.seek(500_000_001)
261
+ b = fh.read(1)
262
+ fh.seek(500_000_001)
263
+ fh.write(bytes([b[0] ^ 0xFF]))
264
+ v2 = hubckpt.verify_checkpoint(REPO, local, SUB, repo_type="dataset")
265
+ print("VERIFY_TAMPERED ok", v2["ok"], "mismatch", json.dumps(v2["mismatch"])[:260], flush=True)
266
+ assert not v2["ok"] and v2["mismatch"], "a flipped byte at 500 MB verified clean"
267
+ with open(p, "r+b") as fh:
268
+ fh.seek(500_000_001)
269
+ fh.write(b)
270
+ assert hubckpt.verify_checkpoint(REPO, local, SUB, repo_type="dataset")["ok"], "restoring did not help"
271
+
272
+ # 2. A path that is not on the Hub at all: nothing listed means nothing verified.
273
+ v3 = hubckpt.verify_checkpoint(REPO, local, "ckpt/checkpoint-99999999", repo_type="dataset")
274
+ print("VERIFY_ABSENT ok", v3["ok"], "missing", len(v3["missing"]), "of", v3["n_local"], flush=True)
275
+ assert not v3["ok"] and len(v3["missing"]) == v3["n_local"], v3["missing"][:3]
276
+
277
+ # 3. A server that ignores Range and streams the whole object: the read-back must fail rather than pay
278
+ # for 850 MB, because a silent full download is the thing this change exists to prevent.
279
+ real = hubckpt.urllib.request.urlopen
280
+ class _Whole:
281
+ status = 200
282
+ def __enter__(self): return self
283
+ def __exit__(self, *a): return False
284
+ def read(self, n=-1): return b"x" * (len(self) if n is None or n < 0 else min(n, len(self)))
285
+ def __len__(self): return 1 << 20
286
+ def _fake(req, *a, **k):
287
+ # Only the download path is faked: hub_listing uses the same urlopen, and breaking it here would
288
+ # report a "server ignored Range" test as a listing crash.
289
+ if "/resolve/" in getattr(req, "full_url", str(req)):
290
+ return _Whole()
291
+ return real(req, *a, **k)
292
+ hubckpt.urllib.request.urlopen = _fake
293
+ try:
294
+ v4 = hubckpt.verify_checkpoint(REPO, local, SUB, repo_type="dataset")
295
+ finally:
296
+ hubckpt.urllib.request.urlopen = real
297
+ print("VERIFY_NO_206 ok", v4["ok"], "readback", json.dumps(v4["readback"])[:260], flush=True)
298
+ assert not v4["ok"] and "206" in str(v4["readback"]), v4["readback"]
299
+ print("VERIFY_STAGE_OK all four paths behave", flush=True)
300
+ """
301
+ open("prepverify.py", "w").write(VERIFY)
302
+ rc4, _ = run([sys.executable, "prepverify.py"], "CHECK_VERIFY", 1800, env=dict(PLANENV))
303
+ print("VERDICT PHASE4_PREP rc_launcher", rc1, "rc_check", rc2, "rc_cursor", rc3, "rc_verify", rc4,
304
  "seconds", round(time.time() - T0, 1), flush=True)
305
+ raise SystemExit(0 if (rc1 == rc2 == rc3 == rc4 == 0) else 4)