|
|
@@ -183,6 +183,33 @@ def copy_range(src_f, dst_f, off: int, length: int, started: float, tag: str) ->
|
|
|
flush=True)
|
|
|
|
|
|
|
|
|
+def headers_ok(src: Path, dst: Path) -> bool:
|
|
|
+ """The safetensors header (8-byte length + JSON) must be byte-identical —
|
|
|
+ the overlay loaders parse it before touching rows; holes read as len 0."""
|
|
|
+ try:
|
|
|
+ n = struct.unpack("<Q", _head_read(src, 0, 8))[0]
|
|
|
+ return _head_read(src, 0, 8 + n) == _head_read(dst, 0, 8 + n)
|
|
|
+ except Exception: # noqa: BLE001
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+def _head_read(path: Path, off: int, n: int) -> bytes:
|
|
|
+ with open(path, "rb", buffering=0) as f:
|
|
|
+ f.seek(off)
|
|
|
+ b = f.read(n)
|
|
|
+ if len(b) != n:
|
|
|
+ raise OSError(f"{path}: short read {len(b)} < {n}")
|
|
|
+ return b
|
|
|
+
|
|
|
+
|
|
|
+def copy_header(src: Path, dst: Path) -> None:
|
|
|
+ n = struct.unpack("<Q", _head_read(src, 0, 8))[0]
|
|
|
+ head = _head_read(src, 0, 8 + n)
|
|
|
+ with open(dst, "r+b", buffering=0) as f:
|
|
|
+ f.seek(0)
|
|
|
+ f.write(head)
|
|
|
+
|
|
|
+
|
|
|
def stage_sparse_layer(out: Path, layer: int, recs, lo: int, hi: int, ledger: Ledger,
|
|
|
samples_n: int, force: bool, verify: str) -> None:
|
|
|
"""One rank slice into node-local sparse shard copies at the ORIGINAL
|
|
|
@@ -214,6 +241,11 @@ def stage_sparse_layer(out: Path, layer: int, recs, lo: int, hi: int, ledger: Le
|
|
|
t0 = time.monotonic()
|
|
|
verified_only = False
|
|
|
if not force and files_ok():
|
|
|
+ # header repair fast path: builds before 2026-09-27 left the header
|
|
|
+ # region hole-zeroed, which the loaders read as "not JSON"
|
|
|
+ for srcp, dstp in ((wpath, dst_w), (spath, dst_s)):
|
|
|
+ if not headers_ok(srcp, dstp):
|
|
|
+ copy_header(srcp, dstp)
|
|
|
if rec is not None and rec.get("lo") == lo and rec.get("hi") == hi:
|
|
|
if verify == "presence" or check([(int(k), v) for k, v in rec["sample"].items()]):
|
|
|
verified_only = True
|
|
|
@@ -239,6 +271,9 @@ def stage_sparse_layer(out: Path, layer: int, recs, lo: int, hi: int, ledger: Le
|
|
|
os.truncate(dst, size)
|
|
|
elif dst.stat().st_size != size:
|
|
|
os.truncate(dst, size)
|
|
|
+ for srcp, dstp in ((wpath, dst_w), (spath, dst_s)):
|
|
|
+ if not headers_ok(srcp, dstp):
|
|
|
+ copy_header(srcp, dstp)
|
|
|
with open(wpath, "rb", buffering=0) as sf, open(dst_w, "r+b", buffering=0) as df:
|
|
|
copy_range(sf, df, woff + lo * WEIGHT_BYTES, (hi - lo) * WEIGHT_BYTES,
|
|
|
t0, f"l{layer}-weight")
|