File size: 4,525 Bytes
2ea2835 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #!/usr/bin/env python3
"""Stage an existing local VideoMAE-v2 Large snapshot; no network access."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path
import tempfile
import shutil
MODEL_ID = "VideoMAEv2-Large"
REVISION = "9981a9c8f77118c421e5228e1b219468a4b0238d"
def file_sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
while block := handle.read(8 * 1024 * 1024):
digest.update(block)
return digest.hexdigest()
def canonical_sha256(value) -> str:
payload = json.dumps(
value, sort_keys=True, separators=(",", ":"), allow_nan=False
).encode("utf-8")
return hashlib.sha256(payload).hexdigest()
def atomic_json(path: Path, value) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
descriptor, name = tempfile.mkstemp(
dir=path.parent, prefix=f".{path.name}.", suffix=".tmp")
try:
with os.fdopen(descriptor, "w", encoding="utf-8") as handle:
json.dump(value, handle, sort_keys=True, indent=2)
handle.write("\n")
handle.flush()
os.fsync(handle.fileno())
os.replace(name, path)
finally:
Path(name).unlink(missing_ok=True)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"--output-dir",
default=(
"assets/models/"
"VideoMAEv2-Large"),
)
parser.add_argument("--source-dir", required=True, type=Path,
help="Existing local snapshot; not a hosted repository ID")
args = parser.parse_args()
output = Path(args.output_dir).expanduser().resolve()
source = args.source_dir.expanduser().resolve()
if not source.is_dir():
parser.error("--source-dir must be an existing local directory")
if source == output or source in output.parents or output in source.parents:
parser.error("Source and output directories must be separate and non-nested")
if output.exists() and (not output.is_dir() or any(output.iterdir())):
parser.error("--output-dir must be absent or empty")
if not (source / "config.json").is_file():
parser.error("The local snapshot must include config.json")
if not any(source.glob("*.safetensors")) and not any(source.glob("*.bin")):
parser.error("The local snapshot must include model weights")
shutil.copytree(source, output, dirs_exist_ok=True,
ignore=shutil.ignore_patterns(".git", ".cache", "__pycache__", ".DS_Store"))
# Existing frozen banks depend on the original manifest digest. Copy that
# manifest unchanged when supplied, rather than rewriting its identity.
existing_manifest = output / "download_manifest.json"
if existing_manifest.is_file():
manifest = json.loads(existing_manifest.read_text())
payload = dict(manifest)
saved = payload.pop("content_hash", None)
if manifest.get("revision") != REVISION or canonical_sha256(payload) != saved:
raise ValueError("Invalid pinned local snapshot manifest")
for item in manifest["files"]:
path = (output / item["path"]).resolve()
if (output not in path.parents or path.stat().st_size != item["size_bytes"]
or file_sha256(path) != item["sha256"]):
raise ValueError(f"Local snapshot file identity mismatch: {path}")
print(json.dumps({"output_dir": str(output), "file_count": len(manifest["files"]),
"content_hash": saved, "preserved_manifest": True}, sort_keys=True))
return
files = []
for path in sorted(output.rglob("*")):
if (
not path.is_file()
or path.name == "download_manifest.json"
or ".cache" in path.parts
):
continue
files.append({
"path": path.relative_to(output).as_posix(),
"size_bytes": path.stat().st_size,
"sha256": file_sha256(path),
})
payload = {
"schema_version": 1,
"model_id": MODEL_ID,
"revision": REVISION,
"files": files,
}
payload["content_hash"] = canonical_sha256(payload)
atomic_json(output / "download_manifest.json", payload)
print(json.dumps({
"output_dir": str(output),
"file_count": len(files),
"content_hash": payload["content_hash"],
}, sort_keys=True))
if __name__ == "__main__":
main()
|