fix(proxy): treat explicit zero non-token prices as priced

A deployment that overrides any cost_per field, including at zero, now counts as priced so it is not blocked as unpriced

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
mateo 2026-08-20 20:59:38 +00:00
parent 074b37b4f9
commit c551a5c44a
2 changed files with 31 additions and 5 deletions

View file

@ -300,15 +300,20 @@ def _entry_has_priced_metric(entry: Mapping[str, object]) -> bool:
return False
def _entry_declares_price(entry: Mapping[str, object]) -> bool:
return any("cost_per" in key for key in entry)
def _model_group_has_pricing(model: str, llm_router: "Router") -> bool:
"""
Check every deployment behind a model group for a positive price on any billed
metric (tokens, characters, seconds, pages, images, queries, ...), so models that
are billed by a non-token metric are not treated as unpriced.
A model group counts as priced when a deployment overrides any *cost_per* field in its
litellm_params, even at zero, or when its resolved model info carries a positive price on
any billed metric (tokens, characters, seconds, pages, images, queries, ...), so models
billed by a non-token metric are not treated as unpriced.
"""
for deployment in llm_router.get_model_list(model_name=model) or []:
litellm_params = deployment.get("litellm_params") or {}
if _entry_has_priced_metric(litellm_params):
if _entry_declares_price(litellm_params):
return True
model_id = (deployment.get("model_info") or {}).get("id")

View file

@ -5246,7 +5246,7 @@ def test_model_has_no_cost_mapping_non_token_price_from_litellm_params_is_false(
{
"model_name": "custom-tts",
"litellm_params": {
"model": UNPRICED_UNDERLYING_MODEL,
"model": f"{UNPRICED_UNDERLYING_MODEL}-per-second",
"api_key": "sk-test",
"input_cost_per_second": 0.0001,
},
@ -5257,6 +5257,27 @@ def test_model_has_no_cost_mapping_non_token_price_from_litellm_params_is_false(
assert model_has_no_cost_mapping(model="custom-tts", llm_router=router) is False
@pytest.mark.parametrize("cost_field", ["input_cost_per_second", "input_cost_per_token"])
def test_model_has_no_cost_mapping_explicit_zero_price_is_false(cost_field):
from litellm.proxy.auth.auth_checks import model_has_no_cost_mapping
from litellm.router import Router
router = Router(
model_list=[
{
"model_name": "free-group",
"litellm_params": {
"model": f"{UNPRICED_UNDERLYING_MODEL}-{cost_field}",
"api_key": "sk-test",
cost_field: 0,
},
}
]
)
assert model_has_no_cost_mapping(model="free-group", llm_router=router) is False
async def _run_common_checks(
model: Optional[str], llm_router: Optional["Router"], route: str = "/chat/completions"
) -> bool: