From 783bad54efe8f463d8900f0f3b4ce98c1ac4b681 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 16:33:14 +0000 Subject: [PATCH] refactor(router): scope cost float-cast to model-group merge comparison --- litellm/router.py | 4 ++-- tests/test_litellm/test_router.py | 31 +++++++++++++++++-------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/litellm/router.py b/litellm/router.py index 21b18829743..16b57870f7b 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -8720,8 +8720,8 @@ class Router: # Get mode from database model_info if available, otherwise default to "chat" db_model_info = model.get("model_info", {}) mode = db_model_info.get("mode", "chat") - input_cost_per_token = safe_cast_to_float(db_model_info.get("input_cost_per_token")) - output_cost_per_token = safe_cast_to_float(db_model_info.get("output_cost_per_token")) + input_cost_per_token = db_model_info.get("input_cost_per_token") + output_cost_per_token = db_model_info.get("output_cost_per_token") model_info = ModelMapInfo( key=model_group, diff --git a/tests/test_litellm/test_router.py b/tests/test_litellm/test_router.py index e386f4f24f5..c77fbd1267b 100644 --- a/tests/test_litellm/test_router.py +++ b/tests/test_litellm/test_router.py @@ -1455,11 +1455,12 @@ def test_model_group_info_cost_none_when_db_model_info_has_no_cost(): assert result.output_cost_per_token is None -def test_model_group_info_casts_string_cost_from_model_info(): +def test_model_group_info_casts_string_cost_from_db_model_info(): """ Regression for #32787: cost values round-tripped through the DB - (store_model_in_db) can come back as strings such as "1e-05". Comparing a - str against a float in _set_model_group_info raised + (store_model_in_db) can come back as strings such as "1e-05". When + get_deployment_model_info falls back to the raw db model_info, comparing a + str against a float across deployments in _set_model_group_info raised "TypeError: '>' not supported between instances of 'str' and 'float'". Costs read from model_info must be cast to float. """ @@ -1470,32 +1471,34 @@ def test_model_group_info_casts_string_cost_from_model_info(): { "model_name": "grp", "litellm_params": {"model": "openai/a", "api_key": "fake"}, - "model_info": {"id": "d1"}, + "model_info": { + "id": "d1", + "input_cost_per_token": "1e-05", + "output_cost_per_token": "2e-05", + }, }, { "model_name": "grp", "litellm_params": {"model": "openai/b", "api_key": "fake"}, - "model_info": {"id": "d2"}, + "model_info": { + "id": "d2", + "input_cost_per_token": "2e-05", + "output_cost_per_token": "4e-05", + }, }, ] ) - def fake_model_info(model_id, model_name): - return { - "input_cost_per_token": "1e-05", - "output_cost_per_token": "2e-05", - } - with patch.object( - router, "get_deployment_model_info", side_effect=fake_model_info + router, "get_deployment_model_info", side_effect=Exception("not found") ): result = router._cached_get_model_group_info("grp") assert result is not None assert isinstance(result.input_cost_per_token, float) assert isinstance(result.output_cost_per_token, float) - assert result.input_cost_per_token == 1e-05 - assert result.output_cost_per_token == 2e-05 + assert result.input_cost_per_token == 2e-05 + assert result.output_cost_per_token == 4e-05 def test_get_model_access_groups_caching():