diff --git a/litellm/utils.py b/litellm/utils.py index 584ab8805a0..7576e3bb83d 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -2780,7 +2780,7 @@ def register_model(model_cost: Union[str, dict]): # noqa: PLR0915 elif value.get("litellm_provider") == "openrouter": split_string = key.split("/", 1) if key not in litellm.openrouter_models: - litellm.openrouter_models.add(split_string[1]) + litellm.openrouter_models.add(split_string[-1]) elif value.get("litellm_provider") == "vercel_ai_gateway": if key not in litellm.vercel_ai_gateway_models: litellm.vercel_ai_gateway_models.add(key) diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index f6c24d19df5..6d99d64f7b2 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -2300,6 +2300,64 @@ def test_register_model_with_scientific_notation(): assert registered_model["mode"] == "chat" +def test_register_model_openrouter_without_slash(): + """ + Test that register_model handles openrouter models without '/' in the name. + + Fixes https://github.com/BerriAI/litellm/issues/18936 + + Previously, the code did `split_string[1]` which would fail with IndexError + when the model name didn't contain '/'. Now it uses `split_string[-1]` which + always works. + """ + # Clear any existing entries + litellm.openrouter_models.discard("my-custom-alias") + litellm.openrouter_models.discard("gpt-4") + litellm.openrouter_models.discard("openai/gpt-4") + + # Test 1: Model name without '/' (this was the bug - would raise IndexError) + litellm.register_model( + { + "my-custom-alias": { + "max_tokens": 8192, + "input_cost_per_token": 0.00001, + "output_cost_per_token": 0.00002, + "litellm_provider": "openrouter", + "mode": "chat", + }, + } + ) + assert "my-custom-alias" in litellm.openrouter_models + + # Test 2: Model name with single '/' (openrouter/model format) + litellm.register_model( + { + "openrouter/gpt-4": { + "max_tokens": 8192, + "input_cost_per_token": 0.00001, + "output_cost_per_token": 0.00002, + "litellm_provider": "openrouter", + "mode": "chat", + }, + } + ) + assert "gpt-4" in litellm.openrouter_models + + # Test 3: Model name with double '/' (openrouter/provider/model format) + litellm.register_model( + { + "openrouter/openai/gpt-4-turbo": { + "max_tokens": 8192, + "input_cost_per_token": 0.00001, + "output_cost_per_token": 0.00002, + "litellm_provider": "openrouter", + "mode": "chat", + }, + } + ) + assert "openai/gpt-4-turbo" in litellm.openrouter_models + + def test_reasoning_content_preserved_in_text_completion_wrapper(): """Ensure reasoning_content is copied from delta to text_choices.""" chunk = ModelResponseStream(