Skip to content

Commit dbfa8ec

Browse files
Fix end user cost tracking in the responses API (#15124)
#13860
1 parent f8f4207 commit dbfa8ec

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

litellm/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
get_set_callbacks,
9191
)
9292
from litellm.litellm_core_utils.core_helpers import (
93+
get_litellm_metadata_from_kwargs,
9394
map_finish_reason,
9495
process_response_headers,
9596
)
@@ -7582,7 +7583,7 @@ def get_end_user_id_for_cost_tracking(
75827583
75837584
service_type: "litellm_logging" or "prometheus" - used to allow prometheus only disable cost tracking.
75847585
"""
7585-
_metadata = cast(dict, litellm_params.get("metadata", {}) or {})
7586+
_metadata = cast(dict, get_litellm_metadata_from_kwargs(dict(litellm_params=litellm_params)))
75867587

75877588
end_user_id = cast(
75887589
Optional[str],

tests/litellm_utils_tests/test_utils.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,44 @@ def test_get_end_user_id_for_cost_tracking_prometheus_only(
14261426
)
14271427

14281428

1429+
@pytest.mark.parametrize(
1430+
"litellm_params, expected_end_user_id",
1431+
[
1432+
# Test with only metadata field (old behavior)
1433+
({"metadata": {"user_api_key_end_user_id": "user_from_metadata"}}, "user_from_metadata"),
1434+
# Test with only litellm_metadata field (new behavior)
1435+
({"litellm_metadata": {"user_api_key_end_user_id": "user_from_litellm_metadata"}}, "user_from_litellm_metadata"),
1436+
# Test with both fields - metadata should take precedence for user_api_key fields
1437+
({"metadata": {"user_api_key_end_user_id": "user_from_metadata"},
1438+
"litellm_metadata": {"user_api_key_end_user_id": "user_from_litellm_metadata"}},
1439+
"user_from_metadata"),
1440+
# Test with user_api_key_end_user_id in litellm_params (should take precedence over metadata)
1441+
({"user_api_key_end_user_id": "user_from_params",
1442+
"metadata": {"user_api_key_end_user_id": "user_from_metadata"}},
1443+
"user_from_params"),
1444+
# Test with empty metadata but valid litellm_metadata
1445+
({"metadata": {}, "litellm_metadata": {"user_api_key_end_user_id": "user_from_litellm_metadata"}},
1446+
"user_from_litellm_metadata"),
1447+
# Test with no metadata fields
1448+
({}, None),
1449+
],
1450+
)
1451+
def test_get_end_user_id_for_cost_tracking_metadata_handling(
1452+
litellm_params, expected_end_user_id
1453+
):
1454+
"""
1455+
Test that get_end_user_id_for_cost_tracking correctly handles both metadata and litellm_metadata
1456+
fields using the get_litellm_metadata_from_kwargs helper function.
1457+
"""
1458+
from litellm.utils import get_end_user_id_for_cost_tracking
1459+
1460+
# Ensure cost tracking is enabled for this test
1461+
litellm.disable_end_user_cost_tracking = False
1462+
1463+
result = get_end_user_id_for_cost_tracking(litellm_params=litellm_params)
1464+
assert result == expected_end_user_id
1465+
1466+
14291467
def test_is_prompt_caching_enabled_error_handling():
14301468
"""
14311469
Assert that `is_prompt_caching_valid_prompt` safely handles errors in `token_counter`.

0 commit comments

Comments
 (0)