timestral-mlx / scripts /download.py
jbilcke's picture
Publish all four Timestral MLX FP32 models, pipeline, original licences and validation
d35e174 verified
Raw History Blame Contribute Delete
2.45 kB
"""Explicit, resumable, revision-pinned upstream download with hash verification."""
import argparse
import os
import hashlib
import json
from pathlib import Path
os.environ.setdefault("HF_HUB_DISABLE_XET", "1")
from huggingface_hub import HfApi, hf_hub_download
ROOT = Path(__file__).resolve().parents[1]
VARIANTS = ("5M", "28M", "123M", "209M")
def sha256(path):
h = hashlib.sha256()
with Path(path).open("rb") as f:
for chunk in iter(lambda: f.read(8 * 1024 * 1024), b""):
h.update(chunk)
return h.hexdigest()
def download(variant):
repo = f"mistralai/Timestral-{variant}"
api = HfApi()
pins_path = ROOT / "pins.json"
pins = json.loads(pins_path.read_text()) if pins_path.exists() else {}
revision = pins.get(variant, {}).get("revision")
info = api.model_info(repo, revision=revision, files_metadata=True)
path = ROOT / "models" / "source" / variant
path.mkdir(parents=True, exist_ok=True)
print(f"Downloading {repo}@{info.sha} to {path}", flush=True)
inventory = {}
for name in ("config.json", "model.safetensors", "LICENSE", "README.md"):
dest = Path(hf_hub_download(repo, name, revision=info.sha, local_dir=path))
meta = next(s for s in info.siblings if s.rfilename == name)
if meta.lfs:
expected = meta.lfs.sha256
actual = sha256(dest)
else:
expected = meta.blob_id
data = dest.read_bytes()
actual = hashlib.sha1(f"blob {len(data)}\0".encode() + data).hexdigest()
if actual != expected:
raise ValueError(f"Hub blob hash mismatch for {repo}/{name}")
inventory[name] = {"sha256": sha256(dest), "bytes": dest.stat().st_size, "hub_blob": expected}
pinned = pins.get(variant, {}).get("files", {}).get(name)
if pinned is not None and pinned != inventory[name]:
raise ValueError(f"pinned source hash mismatch: {repo}/{name}")
print(f" {name}: {dest.stat().st_size:,} bytes, verified", flush=True)
record = {"repo_id": repo, "revision": info.sha, "files": inventory}
(path / "source.json").write_text(json.dumps(record, indent=2) + "\n")
return path
if __name__ == "__main__":
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("variants", nargs="*", choices=VARIANTS, default=list(VARIANTS))
args = p.parse_args()
for size in args.variants:
download(size)