mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(proxy): honor key-level disable_fallbacks after first pre-call pass
Some checks failed
ai-gateway image / ai-gateway release image (push) Has been cancelled
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
Some checks failed
ai-gateway image / ai-gateway release image (push) Has been cancelled
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
Key metadata disable_fallbacks only lands on data during add_key_level_controls, so the local rate-limit fallback retry now rechecks it post pre-call. Also use a real UserAPIKeyAuth in the skip pre-call test since the path reads router_settings Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
391da46e2c
commit
9974cf4bf8
3 changed files with 35 additions and 4 deletions
|
|
@ -2093,7 +2093,12 @@ class ProxyBaseLLMRequestProcessing:
|
|||
except ProxyRateLimitError as original_exc:
|
||||
rate_limited_data: Final = self.data
|
||||
original_model: Final = rate_limited_data.get("model")
|
||||
if pristine is None or not configured_fallbacks or not isinstance(original_model, str):
|
||||
if (
|
||||
pristine is None
|
||||
or not configured_fallbacks
|
||||
or rate_limited_data.get("disable_fallbacks")
|
||||
or not isinstance(original_model, str)
|
||||
):
|
||||
raise
|
||||
|
||||
fallback_models: Final = self._resolve_fallback_models(
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class TestSkipPreCallLogic:
|
|||
await processor.base_process_llm_request(
|
||||
request=MagicMock(spec=Request),
|
||||
fastapi_response=MagicMock(spec=Response),
|
||||
user_api_key_dict=MagicMock(spec=UserAPIKeyAuth),
|
||||
user_api_key_dict=UserAPIKeyAuth(),
|
||||
route_type="aresponses",
|
||||
proxy_logging_obj=mock_proxy_logging,
|
||||
llm_router=MagicMock(),
|
||||
|
|
|
|||
|
|
@ -6410,7 +6410,9 @@ class TestPreCallWithFallbacksOnLocalRateLimit:
|
|||
|
||||
@staticmethod
|
||||
def _otel_key(
|
||||
rpm_limit: int | None = None, model_rpm_limit: dict[str, int] | None = None
|
||||
rpm_limit: int | None = None,
|
||||
model_rpm_limit: dict[str, int] | None = None,
|
||||
disable_fallbacks: bool = False,
|
||||
) -> ProxyUserAPIKeyAuth:
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
|
||||
|
|
@ -6419,7 +6421,10 @@ class TestPreCallWithFallbacksOnLocalRateLimit:
|
|||
api_key="hashed-key",
|
||||
parent_otel_span=span,
|
||||
rpm_limit=rpm_limit,
|
||||
metadata={"model_rpm_limit": model_rpm_limit} if model_rpm_limit else {},
|
||||
metadata={
|
||||
**({"model_rpm_limit": model_rpm_limit} if model_rpm_limit else {}),
|
||||
**({"disable_fallbacks": True} if disable_fallbacks else {}),
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -6540,6 +6545,27 @@ class TestPreCallWithFallbacksOnLocalRateLimit:
|
|||
assert data["model"] == fallback_model
|
||||
assert rig[3] == [primary_model, primary_model, fallback_model]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_metadata_disable_fallbacks_returns_429_instead_of_retrying(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
"""``disable_fallbacks`` set in key metadata only lands on ``data`` during the first
|
||||
pre-call pass (``add_key_level_controls``), so it must be honored after that pass."""
|
||||
from litellm.proxy.common_utils.proxy_rate_limit_error import ProxyRateLimitError
|
||||
|
||||
primary_model = "gpt-4.1"
|
||||
fallback_model = "gpt-4.1-mini"
|
||||
key = self._otel_key(model_rpm_limit={primary_model: 1}, disable_fallbacks=True)
|
||||
rig = self._v3_limiter_rig(monkeypatch, key, [{primary_model: [fallback_model]}])
|
||||
request = {"model": primary_model, "messages": [{"role": "user", "content": "hi"}]}
|
||||
|
||||
await self._pre_call(dict(request), key, rig)
|
||||
with pytest.raises(ProxyRateLimitError) as exc_info:
|
||||
await self._pre_call(dict(request), key, rig)
|
||||
|
||||
assert exc_info.value.status_code == 429
|
||||
assert rig[3] == [primary_model, primary_model]
|
||||
|
||||
|
||||
class _RecordingSuccessLogger(CustomLogger):
|
||||
def __init__(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue