mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
fix(logging): report the cost-map entry billing used in model_map_information (#47182)
Backport of #47182 to stable/1.106.x.
Cherry-picked from 1212260ab1 (main).
Test conflict resolved by keeping the line's file plus this PR's own tests.
This commit is contained in:
parent
c0009b0e8b
commit
568ccb1830
2 changed files with 98 additions and 1 deletions
|
|
@ -6023,6 +6023,7 @@ class StandardLoggingPayloadSetup:
|
|||
custom_llm_provider: str | None,
|
||||
init_response_obj: object,
|
||||
api_base: str | None = None,
|
||||
router_model_id: str | None = None,
|
||||
) -> StandardLoggingModelInformation:
|
||||
model_cost_name: Final = select_model_name_for_cost_calc(
|
||||
model=base_model if custom_pricing else None,
|
||||
|
|
@ -6030,12 +6031,23 @@ class StandardLoggingPayloadSetup:
|
|||
base_model=base_model,
|
||||
custom_pricing=custom_pricing,
|
||||
)
|
||||
pricing_model_name: Final = (
|
||||
select_model_name_for_cost_calc(
|
||||
model=base_model if custom_pricing else None,
|
||||
completion_response=init_response_obj,
|
||||
base_model=base_model,
|
||||
custom_pricing=custom_pricing,
|
||||
router_model_id=router_model_id,
|
||||
)
|
||||
if router_model_id is not None
|
||||
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=model_cost_name,
|
||||
model=pricing_model_name or model_cost_name,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
api_base=api_base,
|
||||
)
|
||||
|
|
@ -6714,6 +6726,7 @@ def get_standard_logging_object_payload(
|
|||
custom_llm_provider=kwargs.get("custom_llm_provider"),
|
||||
init_response_obj=init_response_obj,
|
||||
api_base=litellm_params.get("api_base"),
|
||||
router_model_id=logging_obj.get_router_model_id(),
|
||||
)
|
||||
|
||||
error_information, error_str = StandardLoggingPayloadSetup.get_error_information_for_logging_payload(
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ from litellm.litellm_core_utils.litellm_logging import (
|
|||
StandardLoggingPayloadSetup,
|
||||
_extract_response_obj_and_hidden_params,
|
||||
_get_status_fields,
|
||||
get_standard_logging_object_payload,
|
||||
set_callbacks,
|
||||
)
|
||||
from litellm.litellm_core_utils.logging_worker import GLOBAL_LOGGING_WORKER
|
||||
|
|
@ -11563,3 +11564,86 @@ class CompletionCustomHandler(
|
|||
except Exception:
|
||||
print(f"Assertion Error: {traceback.format_exc()}")
|
||||
self.errors.append(traceback.format_exc())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("input_cost_per_token", "output_cost_per_token"),
|
||||
[(1e-06, 2e-06), (0.0, 0.0)],
|
||||
ids=["custom_price", "explicit_zero_price"],
|
||||
)
|
||||
def test_standard_logging_payload_reports_the_deployment_entry_the_request_was_billed_from(
|
||||
input_cost_per_token: float, output_cost_per_token: float
|
||||
):
|
||||
"""A deployment with its own price keeps the catalog model as model_map_key but is logged at its own rates."""
|
||||
deployment_id: Final = "lit9660-priced-deployment"
|
||||
deployment_model_info: Final = {
|
||||
"id": deployment_id,
|
||||
"input_cost_per_token": input_cost_per_token,
|
||||
"output_cost_per_token": output_cost_per_token,
|
||||
}
|
||||
litellm.register_model(
|
||||
model_cost={
|
||||
deployment_id: {
|
||||
"litellm_provider": "openai",
|
||||
"mode": "chat",
|
||||
"input_cost_per_token": input_cost_per_token,
|
||||
"output_cost_per_token": output_cost_per_token,
|
||||
}
|
||||
},
|
||||
persist_across_reloads=False,
|
||||
)
|
||||
try:
|
||||
logging_obj: Final = LitellmLogging(
|
||||
model="gpt-5.4-nano",
|
||||
messages=[{"role": "user", "content": "Hi"}],
|
||||
stream=False,
|
||||
call_type="completion",
|
||||
start_time=time.time(),
|
||||
litellm_call_id="lit9660",
|
||||
function_id="fn",
|
||||
)
|
||||
litellm_params: Final = {
|
||||
"metadata": {
|
||||
"model_group": "lit9660-group",
|
||||
"deployment": "openai/gpt-5.4-nano",
|
||||
"model_info": deployment_model_info,
|
||||
}
|
||||
}
|
||||
logging_obj.update_environment_variables(
|
||||
model="gpt-5.4-nano", user="", optional_params={}, litellm_params=litellm_params, custom_llm_provider="openai"
|
||||
)
|
||||
response: Final = ModelResponse(
|
||||
model="gpt-5.4-nano",
|
||||
choices=[litellm.Choices(message=litellm.Message(role="assistant", content="hi"))],
|
||||
usage=litellm.Usage(prompt_tokens=10, completion_tokens=6, total_tokens=16),
|
||||
)
|
||||
|
||||
response_cost: Final = logging_obj.response_cost_calculator(result=response)
|
||||
payload: Final = get_standard_logging_object_payload(
|
||||
kwargs={
|
||||
"model": "gpt-5.4-nano",
|
||||
"custom_llm_provider": "openai",
|
||||
"litellm_params": litellm_params,
|
||||
"response_cost": response_cost,
|
||||
},
|
||||
init_response_obj=response,
|
||||
start_time=datetime.datetime.now(),
|
||||
end_time=datetime.datetime.now(),
|
||||
logging_obj=logging_obj,
|
||||
status="success",
|
||||
)
|
||||
|
||||
assert response_cost == 10 * input_cost_per_token + 6 * output_cost_per_token
|
||||
assert payload is not None
|
||||
assert payload["model_map_information"] == {
|
||||
"model_map_key": "openai/gpt-5.4-nano",
|
||||
"model_map_value": litellm.get_model_info(model=f"openai/{deployment_id}", custom_llm_provider="openai"),
|
||||
}
|
||||
model_map_value: Final = payload["model_map_information"]["model_map_value"]
|
||||
assert model_map_value is not None
|
||||
assert (model_map_value["input_cost_per_token"], model_map_value["output_cost_per_token"]) == (
|
||||
input_cost_per_token,
|
||||
output_cost_per_token,
|
||||
)
|
||||
finally:
|
||||
litellm.model_cost.pop(deployment_id, None)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue