diff --git a/strix/config/models.py b/strix/config/models.py index 4ce6dc86..b2d6f9d0 100644 --- a/strix/config/models.py +++ b/strix/config/models.py @@ -905,6 +905,12 @@ def model_supports_reasoning(model_name: str) -> bool: return bool(entry and entry.get("supports_reasoning")) +def model_supports_images(model_name: str) -> bool: + """Return whether the model accepts image input. Assume yes until proven otherwise.""" + entry = _catalog_entry(model_name) + return entry is None or bool(entry.get("supports_vision")) + + def _bare_openai_name(model_name: str) -> str: name = model_name.strip().lower() for prefix in ("litellm/", "any-llm/", "openai/"): diff --git a/tests/test_models.py b/tests/test_models.py index 82cf8ac4..aafbaf40 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -16,6 +16,7 @@ from strix.config.models import ( _NonStreamingModel, _TurnGuardModel, configure_sdk_model_defaults, + model_supports_images, request_timeout_extra_args, resolve_api_type, routes_through_litellm, @@ -202,3 +203,11 @@ def test_configure_sdk_api_route_follows_the_given_model( models.configure_sdk_api_route("my-private-model", settings) assert routes == ["responses", "chat_completions"] + + +def test_image_support_follows_the_catalog(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setitem(litellm.model_cost, "acme-text", {}) + monkeypatch.setitem(litellm.model_cost, "acme-vision", {"supports_vision": True}) + assert model_supports_images("acme-text") is False + assert model_supports_images("litellm/openai/acme-vision") is True + assert model_supports_images("acme-unknown-model") is True