fix(logging): fall through to cost calculator on None hidden response_cost

This commit is contained in:
onatozmenn 2026-09-19 23:22:14 +03:00
parent bc3b5b1d5b
commit 0c116d9122
No known key found for this signature in database
2 changed files with 36 additions and 1 deletions

View file

@ -2396,7 +2396,7 @@ class Logging(LiteLLMLoggingBaseClass):
if self.model_call_details.get("cache_hit") is True:
self.model_call_details["response_cost"] = 0.0
elif "response_cost" in hidden_params:
elif hidden_params.get("response_cost") is not None:
self.model_call_details["response_cost"] = hidden_params["response_cost"]
self._record_zero_cost_diagnostic(logging_result, hidden_params["response_cost"])
elif (existing_cost := self.model_call_details.get("response_cost")) is not None and existing_cost != 0:

View file

@ -4170,6 +4170,41 @@ def test_process_hidden_params_uses_hidden_params_cost_after_failure_handler_zer
assert slo.get("response_cost") == passthrough_cost
def test_process_hidden_params_falls_through_on_none_response_cost():
"""A present-but-None response_cost in _hidden_params must not be copied
as the cost; it falls through to the calculator (issue #41976)."""
from datetime import datetime
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.types.utils import ModelResponse, Usage
logging_obj = LiteLLMLoggingObj(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "hi"}],
stream=False,
call_type="responses",
start_time=datetime.now(),
litellm_call_id="test-none-hidden-cost",
function_id="test-none-hidden-cost",
)
logging_obj.model_call_details["litellm_params"] = {"model": "openai/gpt-4o-mini"}
logging_obj.optional_params = {}
result = ModelResponse(
id="success",
choices=[{"message": {"role": "assistant", "content": "ok"}}],
usage=Usage(prompt_tokens=100, completion_tokens=10, total_tokens=110),
)
result._hidden_params = {"response_cost": None}
logging_obj._process_hidden_params_and_response_cost(result, datetime.now(), datetime.now())
cost = logging_obj.model_call_details.get("response_cost")
assert cost is not None and cost > 0
slo = logging_obj.model_call_details.get("standard_logging_object") or {}
assert slo.get("response_cost", 0) > 0
def test_function_setup_litellm_metadata_populates_metadata():
"""
Test that function_setup() properly handles litellm_metadata (used by /v1/messages,