Skip to content

Commit 367a77a

Browse files
committed
name the rejected path in the require_ml error
1 parent 8b18c80 commit 367a77a

2 files changed

Lines changed: 59 additions & 3 deletions

File tree

‎sdk/src/unplug/core/runtime/model_runtime.py‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,21 @@ def load_active_model_provider(
132132
if not path or not Path(path).is_dir():
133133
if config.require_ml:
134134
tier = config.active_model or "unknown"
135-
msg = (
136-
f"Model tier {tier!r} is not available locally. Run: unplug-models download {tier}"
137-
)
135+
if path:
136+
# Naming the path matters more than naming the tier here. Now that
137+
# a bad path is refused rather than answered from the cache, this
138+
# is the error an operator gets when they mistype one, and "tier
139+
# 'tiny' is not available locally" sends them to re-download a
140+
# model they already have.
141+
msg = (
142+
f"Model tier {tier!r} was configured with path {path!r}, which is not "
143+
"a usable checkpoint. Fix the path or unset it to use the model cache."
144+
)
145+
else:
146+
msg = (
147+
f"Model tier {tier!r} is not available locally. "
148+
f"Run: unplug-models download {tier}"
149+
)
138150
raise ModelError(msg)
139151
return None
140152
registry = build_model_registry()

‎sdk/tests/unit/ml/test_model_store.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,47 @@ def test_auto_download_still_uses_the_cache_when_no_path_was_named(
508508

509509
assert resolved is not None
510510
assert resolved.path == str(cached)
511+
512+
513+
def test_require_ml_error_names_the_offending_path(
514+
tmp_path: Path,
515+
monkeypatch: pytest.MonkeyPatch,
516+
) -> None:
517+
"""The operator needs to see which path was rejected, not just the tier.
518+
519+
Now that a bad path fails instead of being answered from the cache, this is
520+
the error a mistyped path produces, and "tier 'tiny' is not available
521+
locally, run unplug-models download tiny" sends them to re-download a model
522+
they already have.
523+
"""
524+
from unplug.core.runtime.model_runtime import load_active_model_provider
525+
526+
monkeypatch.delenv("UNPLUG_MODEL_PATH", raising=False)
527+
monkeypatch.setenv("UNPLUG_MODEL_CACHE", str(tmp_path / "empty"))
528+
bad = tmp_path / "typo_in_this_path"
529+
530+
cfg = merge_catalog_models(
531+
GuardConfig(active_model="tiny", require_ml=True, auto_download_model=False)
532+
)
533+
models = dict(cfg.models)
534+
models["tiny"] = models["tiny"].model_copy(update={"path": str(bad)})
535+
cfg = cfg.model_copy(update={"models": models})
536+
537+
with pytest.raises(ModelError) as excinfo:
538+
load_active_model_provider(cfg)
539+
assert str(bad) in str(excinfo.value)
540+
541+
542+
def test_require_ml_error_still_says_download_when_no_path_was_named(
543+
tmp_path: Path,
544+
monkeypatch: pytest.MonkeyPatch,
545+
) -> None:
546+
monkeypatch.delenv("UNPLUG_MODEL_PATH", raising=False)
547+
monkeypatch.setenv("UNPLUG_MODEL_CACHE", str(tmp_path / "empty"))
548+
from unplug.core.runtime.model_runtime import load_active_model_provider
549+
550+
cfg = merge_catalog_models(
551+
GuardConfig(active_model="tiny", require_ml=True, auto_download_model=False)
552+
)
553+
with pytest.raises(ModelError, match="download"):
554+
load_active_model_provider(cfg)

0 commit comments

Comments
 (0)