mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-28 01:32:17 +00:00
Merge 01a8e6ccee into 2dccc0dc79
This commit is contained in:
commit
7c47aa75db
2 changed files with 135 additions and 5 deletions
|
|
@ -3124,6 +3124,15 @@ _CACHE_PRICING_FIELDS: Final = (
|
|||
"cache_read_input_token_cost_above_200k_tokens",
|
||||
)
|
||||
|
||||
_PROVIDERS_WITH_RESPONSE_REPORTED_COST: Final = frozenset({"openrouter", "perplexity"})
|
||||
|
||||
|
||||
def _has_response_reported_cost(key: str, provider: object) -> bool:
|
||||
provider_name: Final = provider.lower() if isinstance(provider, str) else ""
|
||||
if provider_name in _PROVIDERS_WITH_RESPONSE_REPORTED_COST:
|
||||
return True
|
||||
return key.partition("/")[0].lower() in _PROVIDERS_WITH_RESPONSE_REPORTED_COST
|
||||
|
||||
|
||||
def _resolve_builtin_model_cost_entry(key: str, provider: str) -> dict[str, object] | None:
|
||||
"""Best-effort lookup of a built-in ``model_cost`` entry for a custom key
|
||||
|
|
@ -3296,11 +3305,13 @@ def register_model(
|
|||
_runtime_registered_model_cost[_registered_key] = dict(_registered_value) # mutable-ok: caller-owned
|
||||
|
||||
_skip_get_model_info_providers: Final = PROVIDERS_THAT_AUTHENTICATE_ON_PROVIDER_INFO
|
||||
warned_model_names: set[str] = set()
|
||||
|
||||
for key, value in loaded_model_cost.items():
|
||||
## get model info ##
|
||||
provider = value.get("litellm_provider", "")
|
||||
_key_str = str(key)
|
||||
warning_model_name: Final = str(warning_display_name or key)
|
||||
if provider in _skip_get_model_info_providers or any(
|
||||
_key_str.startswith(f"{p}/") for p in _skip_get_model_info_providers
|
||||
):
|
||||
|
|
@ -3329,11 +3340,17 @@ def register_model(
|
|||
and (
|
||||
value.get("input_cost_per_token") is not None or value.get("output_cost_per_token") is not None
|
||||
)
|
||||
and "*" not in _key_str
|
||||
and "*" not in warning_model_name
|
||||
and not _has_response_reported_cost(key=_key_str, provider=provider)
|
||||
and not _has_response_reported_cost(key=warning_model_name, provider=provider)
|
||||
):
|
||||
verbose_logger.warning(
|
||||
"register_model: model=%s has custom pricing but not in built-in cost map and no prefix/region variant matched; cache_creation_input_token_cost and cache_read_input_token_cost will default to 0 for this model (input/output cost tracking is unaffected). To track cache cost, add them to model_info",
|
||||
warning_display_name or key,
|
||||
)
|
||||
if warning_model_name not in warned_model_names:
|
||||
verbose_logger.warning(
|
||||
"register_model: model=%s has custom pricing but not in built-in cost map and no prefix/region variant matched; cache_creation_input_token_cost and cache_read_input_token_cost will default to 0 for this model (input/output cost tracking is unaffected). To track cache cost, add them to model_info",
|
||||
warning_model_name,
|
||||
)
|
||||
warned_model_names.add(warning_model_name)
|
||||
# ``get_model_info`` returns ``litellm_provider: None`` when the
|
||||
# provider is unknown (e.g. custom deployments registered via
|
||||
# ``Router.add_deployment``). Persisting that None into
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import os
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
import litellm
|
||||
from litellm.main import _build_custom_pricing_entry
|
||||
from litellm.utils import _invalidate_model_cost_lowercase_map
|
||||
|
|
@ -435,6 +434,120 @@ def test_register_model_warns_when_no_builtin_match_for_cache_pricing(caplog):
|
|||
litellm.model_cost.pop(registered_key, None)
|
||||
|
||||
|
||||
def test_register_model_does_not_warn_for_wildcard_models(caplog):
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
registered_key = "lit39169-wildcard/*"
|
||||
litellm.model_cost.pop(registered_key, None)
|
||||
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING, logger=verbose_logger.name):
|
||||
litellm.register_model(
|
||||
{
|
||||
registered_key: {
|
||||
"input_cost_per_token": 0.001,
|
||||
"output_cost_per_token": 0.002,
|
||||
"litellm_provider": "custom",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert not any("register_model" in record.message for record in caplog.records)
|
||||
finally:
|
||||
litellm.model_cost.pop(registered_key, None)
|
||||
|
||||
|
||||
def test_router_openrouter_wildcard_does_not_warn(caplog):
|
||||
import logging
|
||||
|
||||
from litellm import Router
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
deployment_model = "openrouter/*"
|
||||
deployment_id = "lit39169-openrouter-wildcard"
|
||||
snapshot = _snapshot_model_cost_entries([deployment_model, deployment_id])
|
||||
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING, logger=verbose_logger.name):
|
||||
router = Router(
|
||||
model_list=[
|
||||
{
|
||||
"model_name": "all-openrouter",
|
||||
"litellm_params": {
|
||||
"model": deployment_model,
|
||||
"api_key": "fake-key",
|
||||
"input_cost_per_token": 0.0,
|
||||
"output_cost_per_token": 0.0,
|
||||
},
|
||||
"model_info": {"id": deployment_id},
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
assert not any("register_model" in record.message for record in caplog.records)
|
||||
finally:
|
||||
_restore_model_cost_entries(snapshot)
|
||||
del router
|
||||
|
||||
|
||||
def test_register_model_does_not_warn_for_response_priced_providers(caplog):
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
registered_key = "openrouter/lit39169-unmapped-model"
|
||||
litellm.model_cost.pop(registered_key, None)
|
||||
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING, logger=verbose_logger.name):
|
||||
litellm.register_model(
|
||||
{
|
||||
registered_key: {
|
||||
"input_cost_per_token": 0.001,
|
||||
"output_cost_per_token": 0.002,
|
||||
"litellm_provider": "openrouter",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert not any("register_model" in record.message for record in caplog.records)
|
||||
finally:
|
||||
litellm.model_cost.pop(registered_key, None)
|
||||
|
||||
|
||||
def test_register_model_warns_once_for_duplicate_model_aliases(caplog):
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
registered_keys = ["lit39169-deployment-id", "bedrock/lit39169-unmapped-model"]
|
||||
for key in registered_keys:
|
||||
litellm.model_cost.pop(key, None)
|
||||
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING, logger=verbose_logger.name):
|
||||
litellm.register_model(
|
||||
{
|
||||
key: {
|
||||
"input_cost_per_token": 0.001,
|
||||
"output_cost_per_token": 0.002,
|
||||
"litellm_provider": "bedrock",
|
||||
}
|
||||
for key in registered_keys
|
||||
},
|
||||
warning_display_name=registered_keys[1],
|
||||
)
|
||||
|
||||
warnings = [record.message for record in caplog.records if "register_model" in record.message]
|
||||
assert len(warnings) == 1
|
||||
assert registered_keys[1] in warnings[0]
|
||||
finally:
|
||||
for key in registered_keys:
|
||||
litellm.model_cost.pop(key, None)
|
||||
|
||||
|
||||
def test_register_model_no_warning_without_custom_pricing(caplog):
|
||||
"""LIT-6318: an entry with no custom pricing (e.g. router deployment
|
||||
metadata) never drives cost calculation, so registering it under an
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue