Merge pull request #37966 from BerriAI/litellm_1787426863_strategy_router_health_check

fix(proxy): skip health checks for strategy routers
This commit is contained in:
Mateo Wang 2026-08-24 10:26:09 -07:00 committed by GitHub
commit 28b433a007
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 35 deletions

View file

@ -18,6 +18,7 @@ from litellm.constants import (
DEFAULT_HEALTH_CHECK_PROMPT,
HEALTH_CHECK_TIMEOUT_SECONDS,
)
from litellm.router_utils.auto_router_model_naming import classify_strategy_router_model
ILLEGAL_DISPLAY_PARAMS: Final = [
"messages",
@ -182,30 +183,17 @@ async def run_with_timeout(task, timeout):
return {"error": "Timeout exceeded", "exception": timeout_exception}
def _is_semantic_auto_router_deployment(litellm_params: dict) -> bool:
"""
True for semantic auto_router deployments (auto_router/<name>) that are not
sub-strategies (complexity_router, adaptive_router, quality_router).
These are meta-routers that select among real LLM deployments at request time;
they have no LLM endpoint to health-check.
"""
def _is_strategy_router_deployment(litellm_params: dict) -> bool:
"""True for strategy-router deployments."""
model: Final[object] = litellm_params.get("model", "")
if not isinstance(model, str):
return False
if not model.startswith("auto_router/"):
return False
for sub_strategy in ("complexity_router", "adaptive_router", "quality_router"):
if model.startswith(f"auto_router/{sub_strategy}"):
return False
return True
return isinstance(model, str) and classify_strategy_router_model(model) is not None
async def _run_model_health_check(model: dict):
litellm_params = model["litellm_params"]
model_info: Final = model.get("model_info", {})
if _is_semantic_auto_router_deployment(litellm_params):
if _is_strategy_router_deployment(litellm_params):
return {}
mode: Final = _resolve_health_check_mode(

View file

@ -5,7 +5,7 @@ import pytest
from litellm.litellm_core_utils.health_check_helpers import HealthCheckHelpers
from litellm.proxy import health_check as hc_module
from litellm.proxy.health_check import (
_is_semantic_auto_router_deployment,
_is_strategy_router_deployment,
_resolve_health_check_max_tokens,
_resolve_health_check_mode,
_update_litellm_params_for_health_check,
@ -495,33 +495,22 @@ def test_autodetected_embedding_skips_reasoning_effort():
assert "max_tokens" not in updated
# ---------------------------------------------------------------------------
# auto_router (semantic router) deployments must be skipped by health checks.
#
# These are meta-routers that select among real LLM deployments at request
# time. They have no LLM endpoint to probe. Before this fix, the health check
# passed model="auto_router/router_1" to get_llm_provider(), which raised
# BadRequestError: "Unmapped LLM provider for this endpoint" because
# auto_router is not a real LLM provider.
# ---------------------------------------------------------------------------
@pytest.mark.parametrize(
"model, expected",
[
("auto_router/router_1", True),
("auto_router/my_router", True),
("auto_router/complexity_router", False),
("auto_router/adaptive_router", False),
("auto_router/quality_router", False),
("auto_router/adaptive_router/subpath", False),
("auto_router/complexity_router", True),
("auto_router/adaptive_router", True),
("auto_router/quality_router", True),
("auto_router/adaptive_router/subpath", True),
("gpt-4", False),
("openai/gpt-4", False),
("bedrock/claude", False),
],
)
def test_is_semantic_auto_router_deployment(model, expected):
assert _is_semantic_auto_router_deployment({"model": model}) == expected
def test_is_strategy_router_deployment(model, expected):
assert _is_strategy_router_deployment({"model": model}) == expected
@pytest.mark.asyncio
@ -543,3 +532,22 @@ async def test_run_model_health_check_skips_auto_router_deployment():
fake_ahealth_check.assert_not_called()
assert result == {}
@pytest.mark.asyncio
async def test_run_model_health_check_skips_complexity_router_deployment():
fake_ahealth_check = AsyncMock(return_value={})
model = {
"litellm_params": {
"model": "auto_router/complexity_router",
"complexity_router_config": {"tiers": {"simple": "gpt-4o-mini"}},
"complexity_router_default_model": "gpt-4o-mini",
},
"model_info": {},
}
with patch.object(hc_module.litellm, "ahealth_check", fake_ahealth_check):
result = await hc_module._run_model_health_check(model)
fake_ahealth_check.assert_not_called()
assert result == {}