Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/auth/budget_throttle.py: 23%
21 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1"""
2Throttle a key after it exceeds its own ``max_budget`` instead of blocking it.
4When a key opts in via ``throttle_on_budget_exceeded`` and a global
5``budget_exceeded_throttle_percentage`` is configured, an over-budget key keeps
6serving requests but at a reduced TPM/RPM (the configured percentage of its
7configured limits). The decision (over budget + opted in) is made once during
8auth; the scaling is recomputed from the key's original limits on every request
9so it never compounds across requests.
10"""
12import math
13from typing import Final
15import litellm
16from litellm.proxy._types import UserAPIKeyAuth
19def budget_throttle_percentage() -> float | None:
20 """
21 The global throttle percentage, or None when throttling is disabled /
22 misconfigured (in which case an over-budget key is hard-blocked, the safe
23 default).
24 """
25 pct: Final = litellm.budget_exceeded_throttle_percentage
26 if not isinstance(pct, (int, float)) or isinstance(pct, bool):
27 return None
28 if not 0 < pct <= 1:
29 return None
30 return float(pct)
33def should_throttle_budget_exceeded(valid_token: UserAPIKeyAuth) -> bool:
34 """
35 True when a key that exceeded its own ``max_budget`` should be throttled
36 rather than blocked: it opted in, a valid global percentage is set, and the
37 key has a TPM or RPM limit to scale down. A key with neither limit has
38 nothing to throttle, so it stays hard-blocked (the safe default) rather than
39 serving unlimited requests past its budget.
40 """
41 if (valid_token.metadata or {}).get("throttle_on_budget_exceeded") is not True:
42 return False
43 if valid_token.tpm_limit is None and valid_token.rpm_limit is None:
44 return False
45 return budget_throttle_percentage() is not None
48def throttled_limit(limit: int | None, pct: float | None) -> int | None:
49 """
50 Scale a TPM/RPM limit to ``pct`` of its value, keeping a trickle of at least
51 1 so a throttled key is slowed rather than fully locked out. An unset limit
52 or unset percentage leaves the limit unchanged.
53 """
54 if limit is None or pct is None:
55 return limit
56 return max(1, math.floor(limit * pct))