From b3df9b012b488e679ad9c6b3553029b6cdbf7ab7 Mon Sep 17 00:00:00 2001 From: n24q02m Date: Mon, 12 Oct 2026 15:36:53 +0700 Subject: [PATCH] fix: adapt Jev confidence gate to the renamed classifier API and move its test to tests/unit Upstream replaced _with_signal with the failure_reason and signal arguments of _classifier_failure_outcome and renamed the config to OpenSourceClassifierConfig. The test now lives under tests/unit, which is the sharded root that CI assigns to a shard. --- .../complexity_router/complexity_router.py | 26 ++++++++++--------- .../test_jev_confidence_gate.py | 0 2 files changed, 14 insertions(+), 12 deletions(-) rename tests/{test_litellm => unit}/router_strategy/complexity_router/test_jev_confidence_gate.py (100%) diff --git a/litellm/router_strategy/complexity_router/complexity_router.py b/litellm/router_strategy/complexity_router/complexity_router.py index ea37bbf26ca..0eea6c7147c 100644 --- a/litellm/router_strategy/complexity_router/complexity_router.py +++ b/litellm/router_strategy/complexity_router/complexity_router.py @@ -2351,19 +2351,21 @@ class ComplexityRouter(CustomLogger): # policy decision about the verdict, not a health failure, so the breaker closes. if breaker is not None and permit is not None: breaker.record_success(permit) - refused: Final = _with_signal( - self._classifier_failure_outcome( - f"jev classifier route-down refused ({refusal_reason}, verdict {tier_name}, " - f"confidence {answer.confidence:.4f})", - prompt, - system_prompt, - signal=f"jev-refused:{refusal_reason}", - ), - f"jev-classifier:{tier_name}", + refused: Final = self._classifier_failure_outcome( + f"{config.provider} classifier route-down refused ({refusal_reason}, verdict {tier_name}, " + f"confidence {answer.confidence:.4f})", + prompt, + system_prompt, + failure_reason="declined", + signal=f"{config.provider}-refused:{refusal_reason}", ) # Keep the verdict and its cost on the refusal for provenance: the request paid - # for the Jev call, and the routing decision still logs what it answered. - return refused._replace(classifier_cost=verdict.cost, jev_verdict=verdict) + # for the classifier call, and the routing decision still logs what it answered. + return refused._replace( + signals=(*refused.signals, f"{config.provider}-classifier:{tier_name}"), + classifier_cost=verdict.cost, + jev_verdict=verdict, + ) if breaker is not None and permit is not None: breaker.record_success(permit) return ClassificationOutcome( @@ -2398,7 +2400,7 @@ class ComplexityRouter(CustomLogger): @staticmethod def _jev_route_down_refusal_reason( - config: JevClassifierConfig, + config: OpenSourceClassifierConfig, chosen_tier: str, strongest_tier: str, confidence: float, diff --git a/tests/test_litellm/router_strategy/complexity_router/test_jev_confidence_gate.py b/tests/unit/router_strategy/complexity_router/test_jev_confidence_gate.py similarity index 100% rename from tests/test_litellm/router_strategy/complexity_router/test_jev_confidence_gate.py rename to tests/unit/router_strategy/complexity_router/test_jev_confidence_gate.py