Skip to content

Commit ab79b8d

Browse files
committed
fix: count tiered_pricing as a cost mapping when blocking unpriced models
1 parent 5301872 commit ab79b8d

2 files changed

Lines changed: 34 additions & 6 deletions

File tree

litellm/proxy/auth/auth_checks.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,8 @@ def _is_positive_cost(value: object) -> bool:
472472

473473

474474
def _entry_has_priced_metric(entry: Mapping[str, object]) -> bool:
475+
if entry.get("tiered_pricing") is not None:
476+
return True
475477
for key, value in entry.items():
476478
if "cost_per" not in key:
477479
continue
@@ -483,15 +485,15 @@ def _entry_has_priced_metric(entry: Mapping[str, object]) -> bool:
483485

484486

485487
def _entry_declares_price(entry: Mapping[str, object]) -> bool:
486-
return any("cost_per" in key for key in entry)
488+
return any("cost_per" in key or key == "tiered_pricing" for key in entry)
487489

488490

489491
def _model_group_has_pricing(model: str, llm_router: "Router") -> bool:
490492
"""
491-
A model group counts as priced when a deployment overrides any *cost_per* field in its
492-
litellm_params, even at zero, or when its resolved model info carries a positive price on
493-
any billed metric (tokens, characters, seconds, pages, images, queries, ...), so models
494-
billed by a non-token metric are not treated as unpriced.
493+
A model group counts as priced when a deployment overrides any *cost_per* field or
494+
tiered_pricing in its litellm_params, even at zero, or when its resolved model info carries
495+
tiered_pricing or a positive price on any billed metric (tokens, characters, seconds, pages,
496+
images, queries, ...), so models billed by a non-token metric are not treated as unpriced.
495497
"""
496498
for deployment in llm_router.get_model_list(model_name=model) or ():
497499
litellm_params = deployment.get("litellm_params") or _EMPTY_COST_ENTRY

tests/test_litellm/proxy/auth/test_auth_checks.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import os
44
import sys
55
from types import SimpleNamespace
6-
from typing import Optional
6+
from typing import TYPE_CHECKING, Optional
77
from unittest.mock import AsyncMock, MagicMock, patch
88

9+
if TYPE_CHECKING:
10+
from litellm.router import Router
11+
912
sys.path.insert(
1013
0, os.path.abspath("../../..")
1114
) # Adds the parent directory to the system path
@@ -6667,6 +6670,29 @@ def test_model_has_no_cost_mapping_explicit_zero_price_is_false(cost_field):
66676670
assert model_has_no_cost_mapping(model="free-group", llm_router=router) is False
66686671

66696672

6673+
def test_model_has_no_cost_mapping_tiered_pricing_only_is_false():
6674+
from litellm.proxy.auth.auth_checks import model_has_no_cost_mapping
6675+
from litellm.router import Router
6676+
6677+
router = Router(
6678+
model_list=[
6679+
{
6680+
"model_name": "tiered-group",
6681+
"litellm_params": {
6682+
"model": f"{UNPRICED_UNDERLYING_MODEL}-tiered",
6683+
"api_key": "sk-test",
6684+
"tiered_pricing": [
6685+
{"range": [0, 128000], "input_cost_per_token": 2e-7, "output_cost_per_token": 6e-7},
6686+
{"range": [128000, 256000], "input_cost_per_token": 4e-7, "output_cost_per_token": 12e-7},
6687+
],
6688+
},
6689+
}
6690+
]
6691+
)
6692+
6693+
assert model_has_no_cost_mapping(model="tiered-group", llm_router=router) is False
6694+
6695+
66706696
async def _run_common_checks(
66716697
model: Optional[str], llm_router: Optional["Router"], route: str = "/chat/completions"
66726698
) -> bool:

0 commit comments

Comments
 (0)