From 024a8875214f971cefc354405e40833db188f5c8 Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 22:49:35 +0000 Subject: [PATCH 1/6] feat(model_info): add Gemini fallback generalization rules (vertex routing + 2.5+ family baseline) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...odel_prices_and_context_window_backup.json | 32 +++++++ model_prices_and_context_window.json | 32 +++++++ .../test_fallback_generalizations.py | 93 ++++++++++++++++++- 3 files changed, 154 insertions(+), 3 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 9f91cf82f41..afe2cb3deb9 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58149,6 +58149,38 @@ "model_info": { "supports_reasoning": true } + }, + { + "name": "vertex-gemini-ids", + "pattern": "^gemini-(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?:-(?:preview|exp|latest))?(?:-\\d{2}-\\d{2,4})?$", + "description": "A bare Gemini text-chat id at 2.5 or higher, anchored to the whole name: gemini-[.minor]-(pro|flash)[-lite] with an optional preview/exp/latest tag and an optional MM-YYYY or MM-DD date. Bare Gemini ids in this map already infer vertex_ai (gemini-2.5-pro is filed under vertex_ai-language-models), so an unmapped id such as gemini-4-pro follows the same convention instead of raising 'LLM Provider NOT provided'. Anchored so a namespaced or non-chat id (gemini/..., -image, -tts) stays on its own path.", + "model_info": { + "litellm_provider": "vertex_ai" + } + }, + { + "name": "gemini-family-baseline", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with a 1M context and 64K output; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "model_info": { + "mode": "chat", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true, + "supports_pdf_input": true, + "supports_audio_input": true, + "supports_video_input": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_web_search": true, + "supports_url_context": true + } } ] }, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 9f91cf82f41..afe2cb3deb9 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58149,6 +58149,38 @@ "model_info": { "supports_reasoning": true } + }, + { + "name": "vertex-gemini-ids", + "pattern": "^gemini-(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?:-(?:preview|exp|latest))?(?:-\\d{2}-\\d{2,4})?$", + "description": "A bare Gemini text-chat id at 2.5 or higher, anchored to the whole name: gemini-[.minor]-(pro|flash)[-lite] with an optional preview/exp/latest tag and an optional MM-YYYY or MM-DD date. Bare Gemini ids in this map already infer vertex_ai (gemini-2.5-pro is filed under vertex_ai-language-models), so an unmapped id such as gemini-4-pro follows the same convention instead of raising 'LLM Provider NOT provided'. Anchored so a namespaced or non-chat id (gemini/..., -image, -tts) stays on its own path.", + "model_info": { + "litellm_provider": "vertex_ai" + } + }, + { + "name": "gemini-family-baseline", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with a 1M context and 64K output; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "model_info": { + "mode": "chat", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true, + "supports_pdf_input": true, + "supports_audio_input": true, + "supports_video_input": true, + "supports_tool_choice": true, + "supports_system_messages": true, + "supports_response_schema": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_web_search": true, + "supports_url_context": true + } } ] }, diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index 057fa228562..e91a2bb4394 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -135,9 +135,7 @@ def test_fill_missing_requires_per_rule_opt_in(restore_generalizations): "supports_vision": True, } - restore_generalizations( - [{"name": "base", "pattern": r"^acme-", "model_info": {"supports_reasoning": True}}] - ) + restore_generalizations([{"name": "base", "pattern": r"^acme-", "model_info": {"supports_reasoning": True}}]) assert match_fill_missing_generalizations("acme-1", "openai") is None restore_generalizations( @@ -451,6 +449,95 @@ def shipped_cost_map(monkeypatch): set_fallback_generalizations(previous_rules) +def test_shipped_bare_gemini_id_routes_to_vertex_ai(shipped_cost_map): + for model in ( + "gemini-3.9-flash", + "gemini-4-pro", + "gemini-4-pro-preview", + "gemini-3.9-flash-lite-preview-09-2026", + ): + assert model not in litellm.model_cost + assert litellm.get_llm_provider(model=model)[1] == "vertex_ai" + + assert litellm.get_llm_provider(model="gemini-2.5-pro")[1] == "vertex_ai" + + +def test_shipped_gemini_routing_rule_is_anchored(shipped_cost_map): + for model in ( + "gemini-4-flash-image", + "gemini-3.9-flash-preview-tts", + "gemini-2.0-flash-new", + "gemini-1.5-flash-new", + "gemini-4-flashy", + "gemini/gemini-4-pro", + ): + assert match_routing_generalization(model) is None, model + + +@pytest.mark.parametrize( + "model,provider", + [ + ("gemini-4-pro", "gemini"), + ("gemini-3.9-flash", "vertex_ai"), + ("databricks-gemini-4-1-pro", "databricks"), + ("gemini-4-pro-preview-customtools", "gemini"), + ], +) +def test_shipped_gemini_baseline_resolves_unmapped_ids_provider_neutral(shipped_cost_map, model, provider): + assert model not in litellm.model_cost + if provider == "gemini": + assert f"gemini/{model}" not in litellm.model_cost + + info = litellm.get_model_info(model, custom_llm_provider=provider) + assert info["litellm_provider"] == provider + assert info["mode"] == "chat" + assert info["max_input_tokens"] == 1048576 + assert info["max_tokens"] == 65536 + assert info["supports_reasoning"] is True + assert info["supports_function_calling"] is True + assert info["supports_vision"] is True + assert not info.get("input_cost_per_token") + assert not info.get("output_cost_per_token") + + +def test_shipped_gemini_baseline_skips_non_chat_and_pre_2_5_ids(shipped_cost_map): + for model in ( + "gemini-4-flash-image", + "gemini-3.9-flash-preview-tts", + "gemini-4-flash-live-preview", + "gemini-4-flash-native-audio", + "gemini-embedding-4", + "gemini-2.5-computer-use-preview-12-2026", + "gemini-2.0-flash-new", + "gemini-1.5-pro-new", + "gemini-4-flashy", + ): + assert match_capability_generalizations(model) is None, model + + +def test_shipped_gemini_baseline_keeps_reasoning_effort_on_unmapped_model(shipped_cost_map): + assert litellm.supports_reasoning(model="gemini-4-pro", custom_llm_provider="gemini") is True + + optional_params = litellm.utils.get_optional_params( + model="gemini-4-pro", + custom_llm_provider="gemini", + reasoning_effort="medium", + drop_params=False, + ) + assert isinstance(optional_params, dict) + assert optional_params["thinkingConfig"]["thinkingBudget"] > 0 + assert optional_params["thinkingConfig"]["includeThoughts"] is True + + +def test_shipped_gemini_baseline_loses_to_exact_entries(shipped_cost_map): + model = "gemini-2.5-flash-lite" + info = litellm.get_model_info(model, custom_llm_provider="gemini") + entry = litellm.model_cost["gemini/gemini-2.5-flash-lite"] + assert info["max_tokens"] == entry["max_tokens"] + assert info["input_cost_per_token"] == entry["input_cost_per_token"] + assert entry["input_cost_per_token"] > 0 + + def test_shipped_bare_claude_id_routes_to_anthropic(shipped_cost_map): _, provider, _, _ = litellm.get_llm_provider(model="claude-haiku-4-6") assert provider == "anthropic" From 082f02bd739497d6221ebe71e6885eb4a5ffeba7 Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 22:55:29 +0000 Subject: [PATCH 2/6] refactor(model_info): drop Gemini vertex routing rule, keep baseline to certain capabilities Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...odel_prices_and_context_window_backup.json | 24 ++------------- model_prices_and_context_window.json | 24 ++------------- .../test_fallback_generalizations.py | 30 ++----------------- 3 files changed, 9 insertions(+), 69 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index afe2cb3deb9..3f77bd49a0d 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58150,36 +58150,18 @@ "supports_reasoning": true } }, - { - "name": "vertex-gemini-ids", - "pattern": "^gemini-(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?:-(?:preview|exp|latest))?(?:-\\d{2}-\\d{2,4})?$", - "description": "A bare Gemini text-chat id at 2.5 or higher, anchored to the whole name: gemini-[.minor]-(pro|flash)[-lite] with an optional preview/exp/latest tag and an optional MM-YYYY or MM-DD date. Bare Gemini ids in this map already infer vertex_ai (gemini-2.5-pro is filed under vertex_ai-language-models), so an unmapped id such as gemini-4-pro follows the same convention instead of raising 'LLM Provider NOT provided'. Anchored so a namespaced or non-chat id (gemini/..., -image, -tts) stays on its own path.", - "model_info": { - "litellm_provider": "vertex_ai" - } - }, { "name": "gemini-family-baseline", "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with a 1M context and 64K output; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with tool calling and multimodal input; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", - "max_input_tokens": 1048576, - "max_output_tokens": 65536, - "max_tokens": 65536, "supports_function_calling": true, - "supports_parallel_function_calling": true, - "supports_vision": true, - "supports_pdf_input": true, - "supports_audio_input": true, - "supports_video_input": true, "supports_tool_choice": true, "supports_system_messages": true, + "supports_vision": true, "supports_response_schema": true, - "supports_prompt_caching": true, - "supports_reasoning": true, - "supports_web_search": true, - "supports_url_context": true + "supports_reasoning": true } } ] diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index afe2cb3deb9..3f77bd49a0d 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58150,36 +58150,18 @@ "supports_reasoning": true } }, - { - "name": "vertex-gemini-ids", - "pattern": "^gemini-(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?:-(?:preview|exp|latest))?(?:-\\d{2}-\\d{2,4})?$", - "description": "A bare Gemini text-chat id at 2.5 or higher, anchored to the whole name: gemini-[.minor]-(pro|flash)[-lite] with an optional preview/exp/latest tag and an optional MM-YYYY or MM-DD date. Bare Gemini ids in this map already infer vertex_ai (gemini-2.5-pro is filed under vertex_ai-language-models), so an unmapped id such as gemini-4-pro follows the same convention instead of raising 'LLM Provider NOT provided'. Anchored so a namespaced or non-chat id (gemini/..., -image, -tts) stays on its own path.", - "model_info": { - "litellm_provider": "vertex_ai" - } - }, { "name": "gemini-family-baseline", "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with a 1M context and 64K output; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no pricing, so cost stays on the standard unpriced behavior rather than a guessed number.", + "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with tool calling and multimodal input; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", - "max_input_tokens": 1048576, - "max_output_tokens": 65536, - "max_tokens": 65536, "supports_function_calling": true, - "supports_parallel_function_calling": true, - "supports_vision": true, - "supports_pdf_input": true, - "supports_audio_input": true, - "supports_video_input": true, "supports_tool_choice": true, "supports_system_messages": true, + "supports_vision": true, "supports_response_schema": true, - "supports_prompt_caching": true, - "supports_reasoning": true, - "supports_web_search": true, - "supports_url_context": true + "supports_reasoning": true } } ] diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index e91a2bb4394..556a23c13be 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -449,31 +449,6 @@ def shipped_cost_map(monkeypatch): set_fallback_generalizations(previous_rules) -def test_shipped_bare_gemini_id_routes_to_vertex_ai(shipped_cost_map): - for model in ( - "gemini-3.9-flash", - "gemini-4-pro", - "gemini-4-pro-preview", - "gemini-3.9-flash-lite-preview-09-2026", - ): - assert model not in litellm.model_cost - assert litellm.get_llm_provider(model=model)[1] == "vertex_ai" - - assert litellm.get_llm_provider(model="gemini-2.5-pro")[1] == "vertex_ai" - - -def test_shipped_gemini_routing_rule_is_anchored(shipped_cost_map): - for model in ( - "gemini-4-flash-image", - "gemini-3.9-flash-preview-tts", - "gemini-2.0-flash-new", - "gemini-1.5-flash-new", - "gemini-4-flashy", - "gemini/gemini-4-pro", - ): - assert match_routing_generalization(model) is None, model - - @pytest.mark.parametrize( "model,provider", [ @@ -491,10 +466,11 @@ def test_shipped_gemini_baseline_resolves_unmapped_ids_provider_neutral(shipped_ info = litellm.get_model_info(model, custom_llm_provider=provider) assert info["litellm_provider"] == provider assert info["mode"] == "chat" - assert info["max_input_tokens"] == 1048576 - assert info["max_tokens"] == 65536 + assert not info.get("max_input_tokens") assert info["supports_reasoning"] is True assert info["supports_function_calling"] is True + assert info["supports_tool_choice"] is True + assert info["supports_response_schema"] is True assert info["supports_vision"] is True assert not info.get("input_cost_per_token") assert not info.get("output_cost_per_token") From 726430c0e7e812804b39251aa11c8df569c731d7 Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 23:16:32 +0000 Subject: [PATCH 3/6] refactor(model_info): scope Gemini baseline to first-party chat ids Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...odel_prices_and_context_window_backup.json | 11 ++-- model_prices_and_context_window.json | 11 ++-- .../test_fallback_generalizations.py | 53 +++++++++++++------ .../test_get_supported_openai_params.py | 50 +++++------------ 4 files changed, 62 insertions(+), 63 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 3f77bd49a0d..9569f29aa0e 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58151,17 +58151,20 @@ } }, { - "name": "gemini-family-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with tool calling and multimodal input; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "name": "gemini-chat-baseline", + "pattern": "^(?:gemini|vertex_ai)/gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2\\.[5-9]|[3-9](?:\\.\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "A first-party Gemini text-chat id at 2.5 or higher, as gemini/ or vertex_ai/ (get_model_info tries the provider-prefixed name first, so a bare id under those providers matches too): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. Scoped to Google's own namespaces because resellers wrap the same models differently (one exposes them as mode responses without reasoning), so nothing below is certain there. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. 2.5 is the floor: every first-party text-chat Gemini from 2.5 onward in this map carries all of these fields, 1.5 and 2.0 do not and are fully mapped. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", + "supports_reasoning": true, "supports_function_calling": true, "supports_tool_choice": true, "supports_system_messages": true, "supports_vision": true, "supports_response_schema": true, - "supports_reasoning": true + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_web_search": true } } ] diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 3f77bd49a0d..9569f29aa0e 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58151,17 +58151,20 @@ } }, { - "name": "gemini-family-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics))(?:2\\.[5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any provider namespace (bare, gemini/, vertex_ai/, databricks-gemini-3-1-pro, ...): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The lookahead excludes the tts, image, live, audio, embedding, computer-use and robotics lines, which are not text-chat models and carry different limits and modes. 2.5 is the floor because every Gemini from 2.5 onward is a thinking model with tool calling and multimodal input; 1.5 and 2.0 are not and are fully mapped. Carries the model-family facts every such Gemini shares, so an unmapped gemini-4-pro keeps reasoning params and tool calling instead of having them dropped; it carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "name": "gemini-chat-baseline", + "pattern": "^(?:gemini|vertex_ai)/gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2\\.[5-9]|[3-9](?:\\.\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "A first-party Gemini text-chat id at 2.5 or higher, as gemini/ or vertex_ai/ (get_model_info tries the provider-prefixed name first, so a bare id under those providers matches too): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. Scoped to Google's own namespaces because resellers wrap the same models differently (one exposes them as mode responses without reasoning), so nothing below is certain there. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. 2.5 is the floor: every first-party text-chat Gemini from 2.5 onward in this map carries all of these fields, 1.5 and 2.0 do not and are fully mapped. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", + "supports_reasoning": true, "supports_function_calling": true, "supports_tool_choice": true, "supports_system_messages": true, "supports_vision": true, "supports_response_schema": true, - "supports_reasoning": true + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_web_search": true } } ] diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index 556a23c13be..a4fbd79187e 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -453,45 +453,64 @@ def shipped_cost_map(monkeypatch): "model,provider", [ ("gemini-4-pro", "gemini"), - ("gemini-3.9-flash", "vertex_ai"), - ("databricks-gemini-4-1-pro", "databricks"), + ("gemini/gemini-4-pro", None), + ("gemini-3.9-flash-lite-preview-09-2026", "vertex_ai"), + ("vertex_ai/gemini-4-pro", None), ("gemini-4-pro-preview-customtools", "gemini"), ], ) -def test_shipped_gemini_baseline_resolves_unmapped_ids_provider_neutral(shipped_cost_map, model, provider): +def test_shipped_gemini_chat_baseline_resolves_first_party_unmapped_ids(shipped_cost_map, model, provider): assert model not in litellm.model_cost if provider == "gemini": assert f"gemini/{model}" not in litellm.model_cost info = litellm.get_model_info(model, custom_llm_provider=provider) - assert info["litellm_provider"] == provider + assert info["litellm_provider"] == (provider or model.split("/")[0]) assert info["mode"] == "chat" assert not info.get("max_input_tokens") assert info["supports_reasoning"] is True assert info["supports_function_calling"] is True assert info["supports_tool_choice"] is True - assert info["supports_response_schema"] is True + assert info["supports_system_messages"] is True assert info["supports_vision"] is True + assert info["supports_response_schema"] is True + assert info["supports_pdf_input"] is True + assert info["supports_prompt_caching"] is True + assert info["supports_web_search"] is True assert not info.get("input_cost_per_token") assert not info.get("output_cost_per_token") -def test_shipped_gemini_baseline_skips_non_chat_and_pre_2_5_ids(shipped_cost_map): +def test_shipped_gemini_chat_baseline_skips_reseller_namespaces(shipped_cost_map): + for model, provider in ( + ("google/gemini-4-pro", "perplexity"), + ("google/gemini-4-pro", "openrouter"), + ("databricks-gemini-4-1-pro", "databricks"), + ): + with pytest.raises(Exception, match="isn't mapped yet"): + litellm.get_model_info(model, custom_llm_provider=provider) + + assert match_capability_generalizations("google/gemini-4-pro") is None + + +def test_shipped_gemini_chat_baseline_skips_non_chat_and_pre_2_5_ids(shipped_cost_map): for model in ( - "gemini-4-flash-image", - "gemini-3.9-flash-preview-tts", - "gemini-4-flash-live-preview", - "gemini-4-flash-native-audio", - "gemini-embedding-4", - "gemini-2.5-computer-use-preview-12-2026", - "gemini-2.0-flash-new", - "gemini-1.5-pro-new", - "gemini-4-flashy", + "gemini/gemini-4-flash-image", + "gemini/gemini-3.9-flash-preview-tts", + "gemini/gemini-4-flash-live-preview", + "gemini/gemini-4-flash-native-audio", + "gemini/gemini-embedding-4", + "gemini/gemini-2.5-computer-use-preview-12-2026", + "gemini/gemini-2.0-flash-new", + "gemini/gemini-1.5-pro-new", + "gemini/gemini-4-flashy", + "gemini/gemini-4-flash-transcribe", + "gemini/gemini-4-flash-live-translate-preview", ): assert match_capability_generalizations(model) is None, model -def test_shipped_gemini_baseline_keeps_reasoning_effort_on_unmapped_model(shipped_cost_map): +def test_shipped_gemini_chat_baseline_keeps_reasoning_effort_on_unmapped_model(shipped_cost_map): assert litellm.supports_reasoning(model="gemini-4-pro", custom_llm_provider="gemini") is True optional_params = litellm.utils.get_optional_params( @@ -505,7 +524,7 @@ def test_shipped_gemini_baseline_keeps_reasoning_effort_on_unmapped_model(shippe assert optional_params["thinkingConfig"]["includeThoughts"] is True -def test_shipped_gemini_baseline_loses_to_exact_entries(shipped_cost_map): +def test_shipped_gemini_chat_baseline_loses_to_exact_entries(shipped_cost_map): model = "gemini-2.5-flash-lite" info = litellm.get_model_info(model, custom_llm_provider="gemini") entry = litellm.model_cost["gemini/gemini-2.5-flash-lite"] diff --git a/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py b/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py index 722818598af..f9e285cf9fb 100644 --- a/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py +++ b/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py @@ -1,7 +1,5 @@ - import pytest - from litellm.litellm_core_utils.get_supported_openai_params import ( get_supported_openai_params, ) @@ -33,9 +31,7 @@ def test_base_model_label_alone_lacks_bedrock_tools(): """The label by itself does not advertise tools; this is what made the union necessary. Guards against the discrepancy disappearing (and the regression test above silently passing for the wrong reason).""" - params = get_supported_openai_params( - model=BEDROCK_LABEL, custom_llm_provider="bedrock" - ) + params = get_supported_openai_params(model=BEDROCK_LABEL, custom_llm_provider="bedrock") assert params is not None assert "tools" not in params @@ -46,14 +42,8 @@ def test_base_model_is_additive_not_replacement(): Bedrock: real id supports ``tools`` but not the label's reasoning hint; the union must contain the real model's ``tools`` regardless of the label being a subset.""" - real_only = set( - get_supported_openai_params( - model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock" - ) - ) - label_only = set( - get_supported_openai_params(model=BEDROCK_LABEL, custom_llm_provider="bedrock") - ) + real_only = set(get_supported_openai_params(model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock")) + label_only = set(get_supported_openai_params(model=BEDROCK_LABEL, custom_llm_provider="bedrock")) combined = set( get_supported_openai_params( model=BEDROCK_REAL_MODEL, @@ -70,19 +60,15 @@ def test_base_model_is_additive_not_replacement(): def test_base_model_adds_capabilities_the_real_model_lacks(): """Regression for #27717 (the behavior the union must preserve). - ``gemini-3.1-pro`` isn't in the cost map so it advertises no reasoning support, + ``gemini-exp-9999`` isn't in the cost map so it advertises no reasoning support, but the registered ``gemini-3.1-pro-preview`` base_model does. The hint must add ``reasoning_effort``/``thinking`` without the call erroring.""" - real_only = set( - get_supported_openai_params( - model="gemini-3.1-pro", custom_llm_provider="gemini" - ) - ) + real_only = set(get_supported_openai_params(model="gemini-exp-9999", custom_llm_provider="gemini")) assert "reasoning_effort" not in real_only combined = set( get_supported_openai_params( - model="gemini-3.1-pro", + model="gemini-exp-9999", custom_llm_provider="gemini", base_model="gemini-3.1-pro-preview", ) @@ -93,21 +79,15 @@ def test_base_model_adds_capabilities_the_real_model_lacks(): def test_no_base_model_is_unchanged(): """Omitting ``base_model`` must resolve purely from ``model``.""" - with_none = get_supported_openai_params( - model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock", base_model=None - ) - plain = get_supported_openai_params( - model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock" - ) + with_none = get_supported_openai_params(model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock", base_model=None) + plain = get_supported_openai_params(model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock") assert with_none == plain def test_base_model_equal_to_model_is_unchanged(): """A ``base_model`` identical to ``model`` must not double-resolve or reorder.""" - plain = get_supported_openai_params( - model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock" - ) + plain = get_supported_openai_params(model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock") same = get_supported_openai_params( model=BEDROCK_REAL_MODEL, custom_llm_provider="bedrock", @@ -152,14 +132,10 @@ def test_bedrock_converse_alias_resolves_like_bedrock(): params saw no Bedrock capabilities for a Converse model invoked via the alias.""" anthropic_model = "bedrock/converse/us.anthropic.claude-sonnet-4-6" - via_alias = get_supported_openai_params( - model=anthropic_model, custom_llm_provider="bedrock_converse" - ) + via_alias = get_supported_openai_params(model=anthropic_model, custom_llm_provider="bedrock_converse") assert via_alias is not None - assert via_alias == get_supported_openai_params( - model=anthropic_model, custom_llm_provider="bedrock" - ) + assert via_alias == get_supported_openai_params(model=anthropic_model, custom_llm_provider="bedrock") assert "web_search_options" not in via_alias assert "tools" in via_alias @@ -167,9 +143,7 @@ def test_bedrock_converse_alias_resolves_like_bedrock(): def test_bedrock_converse_alias_keeps_nova_web_search_options(): """Nova on the ``bedrock_converse`` alias still advertises web_search_options, proving the alias routes through the model-aware config rather than a blanket Bedrock default.""" - nova_params = get_supported_openai_params( - model="amazon.nova-pro-v1:0", custom_llm_provider="bedrock_converse" - ) + nova_params = get_supported_openai_params(model="amazon.nova-pro-v1:0", custom_llm_provider="bedrock_converse") assert nova_params is not None assert "web_search_options" in nova_params From 5b54bf2328c53244d9509256defbc9f06f54d97a Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 23:36:22 +0000 Subject: [PATCH 4/6] refactor(model_info): restore provider-neutral Gemini chat baseline Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- ...odel_prices_and_context_window_backup.json | 4 +-- model_prices_and_context_window.json | 4 +-- .../test_fallback_generalizations.py | 26 +++++++++++-------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 9569f29aa0e..cc4c7feffad 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58152,8 +58152,8 @@ }, { "name": "gemini-chat-baseline", - "pattern": "^(?:gemini|vertex_ai)/gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2\\.[5-9]|[3-9](?:\\.\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "A first-party Gemini text-chat id at 2.5 or higher, as gemini/ or vertex_ai/ (get_model_info tries the provider-prefixed name first, so a bare id under those providers matches too): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. Scoped to Google's own namespaces because resellers wrap the same models differently (one exposes them as mode responses without reasoning), so nothing below is certain there. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. 2.5 is the floor: every first-party text-chat Gemini from 2.5 onward in this map carries all of these fields, 1.5 and 2.0 do not and are fully mapped. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", "supports_reasoning": true, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 9569f29aa0e..cc4c7feffad 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58152,8 +58152,8 @@ }, { "name": "gemini-chat-baseline", - "pattern": "^(?:gemini|vertex_ai)/gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2\\.[5-9]|[3-9](?:\\.\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "A first-party Gemini text-chat id at 2.5 or higher, as gemini/ or vertex_ai/ (get_model_info tries the provider-prefixed name first, so a bare id under those providers matches too): gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. Scoped to Google's own namespaces because resellers wrap the same models differently (one exposes them as mode responses without reasoning), so nothing below is certain there. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. 2.5 is the floor: every first-party text-chat Gemini from 2.5 onward in this map carries all of these fields, 1.5 and 2.0 do not and are fully mapped. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", "model_info": { "mode": "chat", "supports_reasoning": true, diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index a4fbd79187e..71e6e20b1a4 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -457,12 +457,19 @@ def shipped_cost_map(monkeypatch): ("gemini-3.9-flash-lite-preview-09-2026", "vertex_ai"), ("vertex_ai/gemini-4-pro", None), ("gemini-4-pro-preview-customtools", "gemini"), + ("google/gemini-4-pro", "openrouter"), + ("google/gemini-4-pro", "deepinfra"), + ("google/gemini-4-pro", "vercel_ai_gateway"), + ("google.gemini-4-pro", "oci"), + ("databricks-gemini-4-1-pro", "databricks"), ], ) -def test_shipped_gemini_chat_baseline_resolves_first_party_unmapped_ids(shipped_cost_map, model, provider): +def test_shipped_gemini_chat_baseline_resolves_unmapped_ids(shipped_cost_map, model, provider): assert model not in litellm.model_cost if provider == "gemini": assert f"gemini/{model}" not in litellm.model_cost + elif provider in {"openrouter", "deepinfra", "vercel_ai_gateway", "oci", "databricks"}: + assert f"{provider}/{model}" not in litellm.model_cost info = litellm.get_model_info(model, custom_llm_provider=provider) assert info["litellm_provider"] == (provider or model.split("/")[0]) @@ -481,16 +488,11 @@ def test_shipped_gemini_chat_baseline_resolves_first_party_unmapped_ids(shipped_ assert not info.get("output_cost_per_token") -def test_shipped_gemini_chat_baseline_skips_reseller_namespaces(shipped_cost_map): - for model, provider in ( - ("google/gemini-4-pro", "perplexity"), - ("google/gemini-4-pro", "openrouter"), - ("databricks-gemini-4-1-pro", "databricks"), - ): - with pytest.raises(Exception, match="isn't mapped yet"): - litellm.get_model_info(model, custom_llm_provider=provider) - - assert match_capability_generalizations("google/gemini-4-pro") is None +def test_shipped_gemini_chat_baseline_loses_to_perplexity_exact_entries(shipped_cost_map): + info = litellm.get_model_info("google/gemini-2.5-pro", custom_llm_provider="perplexity") + entry = litellm.model_cost["perplexity/google/gemini-2.5-pro"] + assert info["mode"] == "responses" + assert entry["supports_reasoning"] is False def test_shipped_gemini_chat_baseline_skips_non_chat_and_pre_2_5_ids(shipped_cost_map): @@ -506,6 +508,8 @@ def test_shipped_gemini_chat_baseline_skips_non_chat_and_pre_2_5_ids(shipped_cos "gemini/gemini-4-flashy", "gemini/gemini-4-flash-transcribe", "gemini/gemini-4-flash-live-translate-preview", + "databricks-gemini-3-1-flash-image", + "openrouter/google/gemini-2.0-flash-001", ): assert match_capability_generalizations(model) is None, model From 945adfb603bad0ee0f9a5054196e0b8beeb05a39 Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 23:49:18 +0000 Subject: [PATCH 5/6] refactor(model_info): support multi-digit Gemini majors Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/model_prices_and_context_window_backup.json | 4 ++-- model_prices_and_context_window.json | 4 ++-- .../litellm_core_utils/test_fallback_generalizations.py | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index cc4c7feffad..5537f13f5fd 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58152,8 +58152,8 @@ }, { "name": "gemini-chat-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|(?:[3-9]|[1-9]\\d)(?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number. Source check 2026-09-15: all 45 first-party 2.5+ text-chat entries in this map carry every field below, and the OpenRouter (openrouter.ai/api/v1/models), Vercel AI Gateway (ai-gateway.vercel.sh/v1/models), DeepInfra (api.deepinfra.com/models/list), OCI and Databricks model docs list reasoning, tools and image input for the same models.", "model_info": { "mode": "chat", "supports_reasoning": true, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index cc4c7feffad..5537f13f5fd 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58152,8 +58152,8 @@ }, { "name": "gemini-chat-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", - "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number.", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|(?:[3-9]|[1-9]\\d)(?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number. Source check 2026-09-15: all 45 first-party 2.5+ text-chat entries in this map carry every field below, and the OpenRouter (openrouter.ai/api/v1/models), Vercel AI Gateway (ai-gateway.vercel.sh/v1/models), DeepInfra (api.deepinfra.com/models/list), OCI and Databricks model docs list reasoning, tools and image input for the same models.", "model_info": { "mode": "chat", "supports_reasoning": true, diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index 71e6e20b1a4..4e7d7e85a8c 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -458,10 +458,12 @@ def shipped_cost_map(monkeypatch): ("vertex_ai/gemini-4-pro", None), ("gemini-4-pro-preview-customtools", "gemini"), ("google/gemini-4-pro", "openrouter"), + ("google/gemini-12.5-flash-lite", "openrouter"), ("google/gemini-4-pro", "deepinfra"), ("google/gemini-4-pro", "vercel_ai_gateway"), ("google.gemini-4-pro", "oci"), ("databricks-gemini-4-1-pro", "databricks"), + ("gemini-10-pro", "gemini"), ], ) def test_shipped_gemini_chat_baseline_resolves_unmapped_ids(shipped_cost_map, model, provider): From c9dd4b44f8d696d3d703f31b77f6257990db3ecf Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 15 Sep 2026 23:51:56 +0000 Subject: [PATCH 6/6] revert(model_info): keep Gemini baseline majors single-digit Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/model_prices_and_context_window_backup.json | 2 +- model_prices_and_context_window.json | 2 +- .../litellm_core_utils/test_fallback_generalizations.py | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 5537f13f5fd..36b4a2c308a 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58152,7 +58152,7 @@ }, { "name": "gemini-chat-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|(?:[3-9]|[1-9]\\d)(?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number. Source check 2026-09-15: all 45 first-party 2.5+ text-chat entries in this map carry every field below, and the OpenRouter (openrouter.ai/api/v1/models), Vercel AI Gateway (ai-gateway.vercel.sh/v1/models), DeepInfra (api.deepinfra.com/models/list), OCI and Databricks model docs list reasoning, tools and image input for the same models.", "model_info": { "mode": "chat", diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 5537f13f5fd..36b4a2c308a 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58152,7 +58152,7 @@ }, { "name": "gemini-chat-baseline", - "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|(?:[3-9]|[1-9]\\d)(?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", + "pattern": "gemini-(?!.*(?:-tts|-image|-live|-audio|-embedding|-computer-use|-robotics|-transcribe|-translate))(?:2[.-][5-9]|[3-9](?:[.-]\\d{1,2})?)-(?:pro|flash)(?:-lite)?(?![a-z])", "description": "Any Gemini text-chat id at 2.5 or higher under any namespace, including bare ids, gemini/, vertex_ai/, openrouter/google/, deepinfra/google/, vercel_ai_gateway/google/, oci/google., and databricks-gemini--: gemini-[.minor]-(pro|flash)[-lite] with any trailing preview, date or variant tag. The capability flags were verified against each of those providers' own catalogs and docs. The lookahead excludes the tts, image, live, audio, embedding, computer-use, robotics, transcribe and translate lines, which are different modes with different capabilities. Provider-specific deviations, such as Perplexity's Agent API serving these as mode responses, are carried by their exact map entries, which always win over this rule. Carries no token limits or pricing, so those stay on the standard unmapped behavior rather than a guessed number. Source check 2026-09-15: all 45 first-party 2.5+ text-chat entries in this map carry every field below, and the OpenRouter (openrouter.ai/api/v1/models), Vercel AI Gateway (ai-gateway.vercel.sh/v1/models), DeepInfra (api.deepinfra.com/models/list), OCI and Databricks model docs list reasoning, tools and image input for the same models.", "model_info": { "mode": "chat", diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index 4e7d7e85a8c..71e6e20b1a4 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -458,12 +458,10 @@ def shipped_cost_map(monkeypatch): ("vertex_ai/gemini-4-pro", None), ("gemini-4-pro-preview-customtools", "gemini"), ("google/gemini-4-pro", "openrouter"), - ("google/gemini-12.5-flash-lite", "openrouter"), ("google/gemini-4-pro", "deepinfra"), ("google/gemini-4-pro", "vercel_ai_gateway"), ("google.gemini-4-pro", "oci"), ("databricks-gemini-4-1-pro", "databricks"), - ("gemini-10-pro", "gemini"), ], ) def test_shipped_gemini_chat_baseline_resolves_unmapped_ids(shipped_cost_map, model, provider):