fix(cost_calculator): resolve pricing when base_model provider differs from transport (#47908)

This commit is contained in:
VeeraBabu Jakkula 2026-10-22 15:16:57 +05:30
parent f2118fc767
commit 70fe418f19
3 changed files with 108 additions and 10 deletions

View file

@ -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:

View file

@ -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

View file

@ -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)