Skip to content

feat: honor HF_HUB_CACHE and propagate HF_HUB_OFFLINE into the container - #310

Open
thebroadercollective wants to merge 1 commit into
eugr:mainfrom
thebroadercollective:feat/hf-hub-cache-support
Open

feat: honor HF_HUB_CACHE and propagate HF_HUB_OFFLINE into the container#310
thebroadercollective wants to merge 1 commit into
eugr:mainfrom
thebroadercollective:feat/hf-hub-cache-support

Conversation

@thebroadercollective

Copy link
Copy Markdown

Summary

Extends the HF_HOME support added for #68 to the rest of the HuggingFace cache environment variables, so the tooling resolves the model cache exactly the way huggingface_hub itself does: HF_HUB_CACHE if set, otherwise $HF_HOME/hub, with HF_HOME defaulting to $XDG_CACHE_HOME/huggingface (i.e. ~/.cache/huggingface).

Motivating use case: models stored on a NAS and exposed via an NFS mount that contains a standard HF hub cache hierarchy. Pointing HF_HUB_CACHE at that mount (while HF_HOME — tokens and other HF state — stays local) plus HF_HUB_OFFLINE=1 now works end to end. This should also help with the workflows discussed in #153 / #247 for models that are already in an HF cache layout.

Changes:

  • hf-download.sh: HUB_PATH honors HF_HUB_CACHE (and XDG_CACHE_HOME in the fallback) instead of assuming $HF_HOME/hub.
  • run-recipe.py: check_model_exists() resolves the hub cache from the environment instead of hardcoding ~/.cache/huggingface/hub, so --setup no longer re-downloads models that are already present in a relocated cache.
  • launch-cluster.sh:
    • When HF_HUB_CACHE is set, it is bind-mounted over the container's default hub location and HF_HUB_CACHE is set inside the container. The cache dir and the mount point are pre-created first so Docker doesn't create them root-owned.
    • HF_HUB_OFFLINE is propagated from the host into the container when set — the HF cache is a host mount, so the container should follow the host's offline intent without needing manual CONTAINER_HF_HUB_OFFLINE configuration.

Behavior is unchanged when none of these variables are set (DOCKER_ARGS and all resolved paths are identical to current main).

Notes / known limitations (both match the existing HF_HOME mount semantics): HF_HUB_CACHE must be present at the same path on all cluster nodes, and like all DOCKER_ARGS it takes effect at container creation, so an already-running cluster needs a restart to pick it up. When the cache is a shared mount, hf-download.sh --copy-to is unnecessary (it would rsync the cache onto itself).

Test plan

  • tests/test_recipes.sh passes (56/56) on the branch
  • bash -n / py_compile clean on all three scripts
  • Verified HUB_PATH / check_model_exists() resolution matrix: HF_HUB_CACHE set, HF_HOME set, XDG_CACHE_HOME set, and all unset (default unchanged)
  • Verified generated docker run args: with HF_HUB_CACHE + HF_HUB_OFFLINE=1 set, the hub mount and both env vars are added; with nothing set, DOCKER_ARGS is byte-identical to main
  • Verified pre-creation leaves user-owned (not root-owned) cache/mount-point dirs
  • Real-world on DGX Spark: NFS-mounted read-only hub cache with HF_HUB_OFFLINE=1 (new path), and a run with no HF variables set against the local cache (no regression)

Resolve the HuggingFace hub cache the same way huggingface_hub does:
HF_HUB_CACHE if set, else $HF_HOME/hub, with HF_HOME defaulting to
$XDG_CACHE_HOME/huggingface (~/.cache/huggingface). HF_HOME and
HF_HUB_CACHE are independent: HF_HOME holds tokens and other HF state,
while HF_HUB_CACHE is specifically the model cache and may live
elsewhere (e.g. a shared NFS mount).

- hf-download.sh: HUB_PATH now honors HF_HUB_CACHE and XDG_CACHE_HOME.
- run-recipe.py: check_model_exists() resolves the hub cache from the
  environment instead of hardcoding ~/.cache/huggingface/hub.
- launch-cluster.sh: when HF_HUB_CACHE is set, bind-mount it over the
  container's hub location and set HF_HUB_CACHE in the container; both
  the cache dir and mount point are pre-created to avoid root-owned
  dirs. HF_HUB_OFFLINE is propagated from the host when set, since the
  cache is a host mount and the container should follow the host's
  offline intent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant