mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-08 08:08:37 +00:00
Merge 8f310e37dc into 4786dd861b
This commit is contained in:
commit
649eddede1
3 changed files with 108 additions and 23 deletions
|
|
@ -2573,9 +2573,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:
|
||||
|
|
|
|||
|
|
@ -52,6 +52,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,
|
||||
|
|
@ -6852,6 +6853,13 @@ class StandardLoggingPayloadSetup:
|
|||
return _raw.model_dump()
|
||||
return _empty
|
||||
|
||||
@staticmethod
|
||||
def _get_model_info_or_none(model: str, custom_llm_provider: str | None, api_base: str | None) -> ModelInfo | None:
|
||||
try:
|
||||
return litellm.get_model_info(model=model, custom_llm_provider=custom_llm_provider, api_base=api_base)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_model_cost_information(
|
||||
base_model: str | None,
|
||||
|
|
@ -6879,27 +6887,29 @@ class StandardLoggingPayloadSetup:
|
|||
else model_cost_name
|
||||
)
|
||||
if model_cost_name is None:
|
||||
model_cost_information = StandardLoggingModelInformation(model_map_key="", model_map_value=None)
|
||||
else:
|
||||
try:
|
||||
_model_cost_information: Final = litellm.get_model_info(
|
||||
model=pricing_model_name or model_cost_name,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
api_base=api_base,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name,
|
||||
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
|
||||
)
|
||||
return model_cost_information
|
||||
return StandardLoggingModelInformation(model_map_key="", model_map_value=None)
|
||||
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
|
||||
)
|
||||
lookup_model: Final = pricing_model_name or model_cost_name
|
||||
provider_info: Final = StandardLoggingPayloadSetup._get_model_info_or_none(
|
||||
model=lookup_model, custom_llm_provider=provider_for_lookup, api_base=api_base
|
||||
)
|
||||
model_info: Final = (
|
||||
StandardLoggingPayloadSetup._get_model_info_or_none(
|
||||
model=lookup_model, custom_llm_provider=None, api_base=api_base
|
||||
)
|
||||
if provider_info is None and provider_for_lookup is not None and base_model is not None
|
||||
else provider_info
|
||||
)
|
||||
if model_info is None:
|
||||
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,
|
||||
)
|
||||
return StandardLoggingModelInformation(model_map_key=model_cost_name, model_map_value=model_info)
|
||||
|
||||
@staticmethod
|
||||
def get_final_response_obj(response_obj: dict, init_response_obj: object, kwargs: dict) -> dict | str | list | None:
|
||||
|
|
|
|||
|
|
@ -7481,3 +7481,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