mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-10 08:28:25 +00:00
fix(cost_calculator): resolve pricing when base_model provider differs from transport (#47908)
This commit is contained in:
parent
f2118fc767
commit
70fe418f19
3 changed files with 108 additions and 10 deletions
|
|
@ -2457,9 +2457,26 @@ def pricing_entry_for_cost_calc(
|
|||
)
|
||||
if bedrock_model_info is not None:
|
||||
return bedrock_model_info["key"], bedrock_model_info
|
||||
candidates: Final = (selected_model, _get_response_model(completion_response), model)
|
||||
base_model_provider: Final = (
|
||||
_base_model_pricing_provider(
|
||||
base_model,
|
||||
_get_provider_for_cost_calc(
|
||||
model=model,
|
||||
custom_llm_provider=custom_llm_provider if isinstance(custom_llm_provider, str) else None,
|
||||
),
|
||||
)
|
||||
if base_model is not None and custom_pricing is not True
|
||||
else None
|
||||
)
|
||||
pricing_provider: Final = base_model_provider or custom_llm_provider
|
||||
candidates: Final = (
|
||||
(selected_model, pricing_provider),
|
||||
(_get_response_model(completion_response), custom_llm_provider),
|
||||
(model, custom_llm_provider),
|
||||
*(((selected_model, None),) if base_model is not None else ()),
|
||||
)
|
||||
resolved: Final = next(
|
||||
(info for info in (_cost_map_model_info(name, custom_llm_provider) for name in candidates if name) if info),
|
||||
(info for info in (_cost_map_model_info(name, provider) for name, provider in candidates if name) if info),
|
||||
None,
|
||||
)
|
||||
if resolved is None:
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ from litellm.constants import (
|
|||
from litellm.cost_calculator import (
|
||||
RealtimeAPITokenUsageProcessor,
|
||||
ResponsesWebSocketTokenUsageProcessor,
|
||||
_base_model_pricing_provider,
|
||||
get_usage_object,
|
||||
pricing_entry_for_cost_calc,
|
||||
select_model_name_for_cost_calc,
|
||||
|
|
@ -6690,13 +6691,19 @@ class StandardLoggingPayloadSetup:
|
|||
if router_model_id is not None
|
||||
else model_cost_name
|
||||
)
|
||||
model_cost_information: StandardLoggingModelInformation
|
||||
if model_cost_name is None:
|
||||
model_cost_information = StandardLoggingModelInformation(model_map_key="", model_map_value=None)
|
||||
else:
|
||||
provider_for_lookup: Final[str | None] = (
|
||||
_base_model_pricing_provider(base_model, custom_llm_provider)
|
||||
if base_model is not None and not custom_pricing
|
||||
else custom_llm_provider
|
||||
)
|
||||
try:
|
||||
_model_cost_information: Final = litellm.get_model_info(
|
||||
model=pricing_model_name or model_cost_name,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
custom_llm_provider=provider_for_lookup,
|
||||
api_base=api_base,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
|
|
@ -6704,13 +6711,29 @@ class StandardLoggingPayloadSetup:
|
|||
model_map_value=_model_cost_information,
|
||||
)
|
||||
except Exception:
|
||||
verbose_logger.debug( # keep in debug otherwise it will trigger on every call
|
||||
"Model=%s is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload",
|
||||
model_cost_name,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name, model_map_value=None
|
||||
)
|
||||
if provider_for_lookup is not None and base_model is not None:
|
||||
try:
|
||||
_fallback_info: Final = litellm.get_model_info(
|
||||
model=pricing_model_name or model_cost_name,
|
||||
custom_llm_provider=None,
|
||||
api_base=api_base,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name,
|
||||
model_map_value=_fallback_info,
|
||||
)
|
||||
except Exception:
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name, model_map_value=None
|
||||
)
|
||||
else:
|
||||
verbose_logger.debug( # keep in debug otherwise it will trigger on every call
|
||||
"Model=%s is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload",
|
||||
model_cost_name,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name, model_map_value=None
|
||||
)
|
||||
return model_cost_information
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -7400,3 +7400,61 @@ def test_get_logging_payload_stores_end_user_only_while_end_user_cost_tracking_i
|
|||
end_time=datetime.datetime.now(timezone.utc),
|
||||
)
|
||||
assert payload["end_user"] == expected_end_user
|
||||
|
||||
|
||||
|
||||
def test_base_model_different_custom_llm_provider_resolves_pricing() -> None:
|
||||
"""
|
||||
Verify pricing_entry_for_cost_calc and get_model_cost_information resolve
|
||||
when base_model names a priced model whose provider differs from the transport provider (#47908).
|
||||
"""
|
||||
from litellm.cost_calculator import completion_cost, pricing_entry_for_cost_calc
|
||||
|
||||
model: Final = "glm-5.3-flash"
|
||||
base_model: Final = "zai/glm-5.3-flash"
|
||||
custom_llm_provider: Final = "openai"
|
||||
|
||||
response = {
|
||||
"model": model,
|
||||
"usage": {
|
||||
"prompt_tokens": 1000,
|
||||
"completion_tokens": 100,
|
||||
"total_tokens": 1100,
|
||||
},
|
||||
}
|
||||
|
||||
# 1. pricing_entry_for_cost_calc resolves to the base_model key
|
||||
entry: Final = pricing_entry_for_cost_calc(
|
||||
model=model,
|
||||
completion_response=response,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
custom_pricing=False,
|
||||
base_model=base_model,
|
||||
router_model_id=None,
|
||||
region_name=None,
|
||||
litellm_logging_obj=None,
|
||||
)
|
||||
assert entry is not None
|
||||
assert entry[0] == base_model
|
||||
assert entry[1]["input_cost_per_token"] == 1.5e-07
|
||||
|
||||
# 2. StandardLoggingPayloadSetup.get_model_cost_information populates model_map_value
|
||||
info: Final = StandardLoggingPayloadSetup.get_model_cost_information(
|
||||
base_model=base_model,
|
||||
custom_pricing=False,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
init_response_obj=response,
|
||||
)
|
||||
assert info.get("model_map_key") == base_model
|
||||
assert info.get("model_map_value") is not None
|
||||
assert info["model_map_value"]["key"] == base_model
|
||||
|
||||
# 3. completion_cost computes correct USD cost using base_model pricing
|
||||
cost: Final = completion_cost(
|
||||
completion_response=response,
|
||||
model=model,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
base_model=base_model,
|
||||
)
|
||||
expected_cost: Final = 1000 * 1.5e-07 + 100 * 5e-07
|
||||
assert cost == pytest.approx(expected_cost)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue