Skip to content

Commit 6bf1ffc

Browse files
committed
fix: cache-first local-dir shortcut requires safetensors (hub 1.x has no bin fallback)
1 parent 01c7313 commit 6bf1ffc

2 files changed

Lines changed: 9 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on Keep a Changelog, and the project follows Semantic Versio
1111
### Fixed
1212

1313
- **Warm-cache model loading no longer touches the Hugging Face Hub.** Every checkpoint download (`hf_hub_download`/`snapshot_download` across all embedders, plus the rshf `from_pretrained` loaders for satmae/scalemae/satmaepp) now resolves against the local HF cache first and only goes online on a cache miss. Previously each fresh process issued a HEAD request to huggingface.co even when weights were fully cached, so Hub outages, 429 rate limits, or blocked networks froze `get_embedding` indefinitely — hit hardest by agent integrations that spawn a new process per call. Consequence of cache-first: cached weights are never re-checked against the Hub; delete the cached file to force a re-download. Shared helpers: `hf_hub_download_cache_first` / `snapshot_download_cache_first` / `resolve_pretrained_source_cache_first` in `embedders/shared.py`.
14+
- **`resolve_pretrained_source_cache_first` no longer hands bin-only snapshots to `from_pretrained`.** huggingface_hub >= 1.0 loads a local directory exclusively from `model.safetensors` (no `pytorch_model.bin` fallback, unlike its Hub code path), so the cache-first shortcut crashed with FileNotFoundError for repos that publish only bin weights (e.g. MVRL/satmaepp_ViT-L_pretrain_fmow_rgb). The local-dir shortcut now requires `model.safetensors`; bin-only repos fall back to the repo-id path, whose EntryNotFoundError fallback still loads the cached bin.
1415
- **Clay batch prefetched-input path no longer acquires a provider.** `ClayEmbedder.get_embeddings_batch_from_inputs` unconditionally initialized the provider even though prefetched inputs never fetch — invisible in exports (the provider was already live) but it forced Earth Engine auth on machines without GEE when embedding user-provided data. The single-embedding path already followed the lazy-provider convention; the batch path now matches it, with a regression test.
1516

1617
### Added

src/rs_embed/embedders/shared.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,13 @@ def resolve_pretrained_source_cache_first(model_id: str, *, weight_names: tuple
159159
160160
``Mixin.from_pretrained(repo_id)`` re-resolves config and weights against the
161161
Hub on every fresh process even when cached. If a cached snapshot exists and
162-
holds ``config.json`` plus one of ``weight_names`` (default: the standard
163-
safetensors/bin names), return its path — ``from_pretrained`` accepts a local
164-
dir and skips the network entirely. On any miss return ``model_id`` unchanged
165-
so the caller keeps the exact previous online behavior.
162+
holds ``config.json`` plus one of ``weight_names`` (default:
163+
``model.safetensors`` only — huggingface_hub >= 1.0 loads a local directory
164+
exclusively from safetensors with no ``pytorch_model.bin`` fallback, so
165+
handing it a bin-only snapshot raises FileNotFoundError), return its path —
166+
``from_pretrained`` accepts a local dir and skips the network entirely. On
167+
any miss return ``model_id`` unchanged so the caller keeps the exact
168+
previous online behavior, where the Hub code path does fall back to bin.
166169
"""
167170
if os.path.exists(model_id):
168171
return model_id
@@ -171,7 +174,7 @@ def resolve_pretrained_source_cache_first(model_id: str, *, weight_names: tuple
171174
snap = str(hub.snapshot_download(repo_id=model_id, local_files_only=True))
172175
except Exception:
173176
return model_id
174-
names = weight_names or ("model.safetensors", "pytorch_model.bin")
177+
names = weight_names or ("model.safetensors",)
175178
if os.path.isfile(os.path.join(snap, "config.json")) and any(
176179
os.path.isfile(os.path.join(snap, n)) for n in names
177180
):

0 commit comments

Comments
 (0)