Download prepare_model_dir.py from episod/clef-p300: direct link, hf CLI and curl.
- Browser
- Download file 3.86 kB
-
https://huggingface.co/episod/clef-p300/resolve/main/prepare_model_dir.py
- Command line
-
hf download hf://episod/clef-p300/prepare_model_dir.py
-
curl -L -o prepare_model_dir.py https://huggingface.co/episod/clef-p300/resolve/main/prepare_model_dir.py
3.86 kB
| #!/usr/bin/env python3 | |
| """Build model-dir/ for this bundle before vLLM starts. run.sh runs it with the bundle's python. | |
| Written by tt-orchard (stage 7) for a model whose weights are a fine-tune of a supported model. | |
| The model code in this bundle is registered for the base model's architecture, so vLLM must see | |
| the base model's config files. The tokenizer and weights must be the fine-tune's. This script | |
| builds model-dir/ next to itself from both: | |
| - COPIED from base_config/ (shipped in the bundle): every file there, for example config.json. | |
| - LINKED from the fine-tune's Hugging Face snapshot (absolute links to the resolved files): | |
| tokenizer.json, tokenizer_config.json, chat_template.jinja, generation_config.json, | |
| model.safetensors.index.json and every *.safetensors file. tokenizer.json and at least one | |
| *.safetensors file are required. | |
| The snapshot is the manifest's `weights.repo_id` at `weights.revision` (which must be a pinned | |
| 40-character commit) under $HF_HUB_CACHE or $HF_HOME/hub (run.sh sets HF_HOME). When it is missing | |
| and HF_HUB_OFFLINE is not set, it is downloaded with huggingface_hub from the bundle's venv. When it | |
| is missing and HF_HUB_OFFLINE is set, the script exits 2 and names it. | |
| model-dir/.weights records "<repo>@<revision>". A model-dir without that file was not built here, | |
| and the script exits 2 without touching it. Exit 0 means model-dir is ready. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| import re | |
| import shutil | |
| import sys | |
| from pathlib import Path | |
| HERE = Path(__file__).resolve().parent | |
| LINKED = ("tokenizer.json", "tokenizer_config.json", "chat_template.jinja", "generation_config.json", | |
| "model.safetensors.index.json") | |
| MARKER = ".weights" | |
| def fail(message: str) -> None: | |
| print(f"prepare_model_dir: {message}", file=sys.stderr) | |
| sys.exit(2) | |
| def snapshot(repo: str, rev: str) -> Path: | |
| hub = os.environ.get("HF_HUB_CACHE") or os.path.join( | |
| os.environ.get("HF_HOME") or os.path.expanduser("~/.cache/huggingface"), "hub") | |
| org, name = repo.split("/", 1) | |
| snap = Path(hub) / f"models--{org}--{name}" / "snapshots" / rev | |
| if snap.is_dir(): | |
| return snap | |
| if os.environ.get("HF_HUB_OFFLINE", "").lower() in ("1", "true", "yes", "on"): | |
| fail(f"the weights snapshot {repo}@{rev} is not in {hub} and HF_HUB_OFFLINE is set. " | |
| f"Download it first: hf download {repo} --revision {rev}") | |
| from huggingface_hub import snapshot_download # in the bundle's venv | |
| return Path(snapshot_download(repo_id=repo, revision=rev)) | |
| def main() -> int: | |
| weights = json.loads((HERE / "tt_kernel_manifest.json").read_text(encoding="utf-8"))["weights"] | |
| repo, rev = weights["repo_id"], weights.get("revision") or "" | |
| if not re.fullmatch(r"[0-9a-f]{40}", rev): | |
| fail(f"the manifest's weights revision {rev!r} is not a 40-character commit") | |
| md = HERE / "model-dir" | |
| if md.is_symlink() or (md.exists() and not (md / MARKER).is_file()): | |
| fail(f"{md} exists and was not built by this script; move it aside") | |
| snap = snapshot(repo, rev) | |
| names = list(LINKED) + sorted(p.name for p in snap.glob("*.safetensors")) | |
| present = [n for n in names if (snap / n).exists()] | |
| if "tokenizer.json" not in present or not any(n.endswith(".safetensors") for n in present): | |
| fail(f"{snap} needs tokenizer.json and at least one *.safetensors file") | |
| if md.exists(): | |
| shutil.rmtree(md) | |
| md.mkdir() | |
| for f in sorted((HERE / "base_config").iterdir()): | |
| shutil.copyfile(f, md / f.name) | |
| for n in present: | |
| os.symlink(os.path.realpath(snap / n), md / n) | |
| (md / MARKER).write_text(f"{repo}@{rev}", encoding="utf-8") | |
| print(f"prepare_model_dir: {md} holds the base config and {len(present)} files of {repo}@{rev}") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |