Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions templates/consumer-repo/tools/llm_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ def load_model_registry() -> list[ModelRegistryEntry]:
model=model,
blocked=bool(raw_entry.get("blocked", False)),
lifecycle=str(raw_entry.get("lifecycle", "unknown")).strip().lower(),
quality={},
)
)
return entries
Expand Down Expand Up @@ -370,7 +369,7 @@ def load_slot_config(*, github_default_model: str = "") -> list[SlotDefinition]:
)
continue
logger.debug(
"Ignoring advisory bundled slot model pin %s/%s; reviewed %s selection is %s",
"Ignoring advisory bundled slot model pin %s/%s; reviewed %s selection before fallback is %s",
provider,
explicit_model,
profile,
Expand Down Expand Up @@ -435,7 +434,12 @@ def resolve_slots(
# Preserve an explicit runtime override as an emergency bootstrap when the
# registry file is unavailable. Empty models are never invoked directly;
# langchain_client skips them when the override cannot serve that provider.
if not slots and not os.environ.get(ENV_SLOT_CONFIG) and os.environ.get(env_model_name):
if (
not slots
and not os.environ.get(ENV_SLOT_CONFIG)
and not _slot_path().exists()
and os.environ.get(env_model_name)
):
slots = [
SlotDefinition(name=f"slot{index}", provider=provider, model="")
for index, provider in enumerate(
Expand Down
4 changes: 2 additions & 2 deletions tests/tools/test_langchain_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def test_load_model_registry_ignores_malformed_nested_values(
entries = llm_registry.load_model_registry()

assert len(entries) == 1
assert entries[0].quality == {}
assert entries[0].quality is None


def test_load_model_registry_rejects_non_list_models(
Expand Down Expand Up @@ -372,7 +372,7 @@ def test_load_model_registry_ignores_v1_quality_scores(

[entry] = llm_registry.load_model_registry()

assert entry.quality == {}
assert entry.quality is None


def test_load_slot_config_ignores_tier_slot_when_registry_invalid(
Expand Down
25 changes: 25 additions & 0 deletions tests/tools/test_llm_registry_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ def test_profile_selection_uses_explicit_decision_not_model_position(
assert registry.select_model_for_profile(provider="openai") == "model-balanced"


def test_loaded_registry_entries_keep_compatibility_quality_immutable(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
registry_path = tmp_path / "registry.json"
_write_registry(registry_path)
monkeypatch.setenv(registry.ENV_MODEL_REGISTRY_CONFIG, str(registry_path))

assert registry.load_model_registry()[0].quality is None


def test_new_catalog_model_does_not_auto_promote(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
Expand Down Expand Up @@ -197,6 +207,21 @@ def test_missing_explicit_slot_config_fails_closed(
assert registry.configured_model_for_provider("openai") == ""


def test_unusable_bundled_slot_config_does_not_bootstrap_env_model(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
registry_path = tmp_path / "registry.json"
slots_path = tmp_path / "slots.json"
_write_registry(registry_path)
slots_path.write_text(json.dumps({"slots": [{"provider": "unknown"}]}), encoding="utf-8")
monkeypatch.setenv(registry.ENV_MODEL_REGISTRY_CONFIG, str(registry_path))
monkeypatch.delenv(registry.ENV_SLOT_CONFIG, raising=False)
monkeypatch.setattr(registry, "DEFAULT_SLOT_CONFIG_PATH", slots_path)
monkeypatch.setenv("LANGCHAIN_MODEL", "emergency-model")

assert registry.resolve_slots() == []


def test_invalid_registry_with_explicit_profile_slot_fails_closed(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
Expand Down
10 changes: 7 additions & 3 deletions tools/llm_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ def load_model_registry() -> list[ModelRegistryEntry]:
model=model,
blocked=bool(raw_entry.get("blocked", False)),
lifecycle=str(raw_entry.get("lifecycle", "unknown")).strip().lower(),
quality={},
)
)
return entries
Expand Down Expand Up @@ -370,7 +369,7 @@ def load_slot_config(*, github_default_model: str = "") -> list[SlotDefinition]:
)
continue
logger.debug(
"Ignoring advisory bundled slot model pin %s/%s; reviewed %s selection is %s",
"Ignoring advisory bundled slot model pin %s/%s; reviewed %s selection before fallback is %s",
provider,
explicit_model,
profile,
Expand Down Expand Up @@ -435,7 +434,12 @@ def resolve_slots(
# Preserve an explicit runtime override as an emergency bootstrap when the
# registry file is unavailable. Empty models are never invoked directly;
# langchain_client skips them when the override cannot serve that provider.
if not slots and not os.environ.get(ENV_SLOT_CONFIG) and os.environ.get(env_model_name):
if (
not slots
and not os.environ.get(ENV_SLOT_CONFIG)
and not _slot_path().exists()
and os.environ.get(env_model_name)
):
slots = [
SlotDefinition(name=f"slot{index}", provider=provider, model="")
for index, provider in enumerate(
Expand Down
Loading