diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index e09f2fb71c7..c7e46829aba 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -198,6 +198,8 @@ def test_get_model_info_resolves_provider_prefixed_model_ids(local_model_cost_ma ("perplexity/perplexity/kimi-k3", True), ("perplexity/perplexity/deepseek-v4-flash-0731", True), ("perplexity/perplexity/kimi-k2.7-code", False), + ("perplexity/perplexity/nemotron-3.5-lightning-30b-a3b", True), + ("perplexity/perplexity/nemotron-3-ultra-550b-a55b", True), ): assert litellm.supports_reasoning(model=model) is reasoning, model @@ -209,6 +211,18 @@ def test_get_model_info_resolves_provider_prefixed_model_ids(local_model_cost_ma assert via_provider["output_cost_per_token"] == 4.4e-06 assert via_provider["mode"] == "responses" + lightning = litellm.get_model_info( + model="perplexity/nemotron-3.5-lightning-30b-a3b", custom_llm_provider="perplexity" + ) + assert lightning["key"] == "perplexity/perplexity/nemotron-3.5-lightning-30b-a3b" + assert lightning["input_cost_per_token"] == 1.15e-08 + assert lightning["output_cost_per_token"] == 1.7e-07 + assert lightning["cache_read_input_token_cost"] == 1.15e-09 + assert lightning["mode"] == "responses" + + ultra = litellm.get_model_info(model="perplexity/perplexity/nemotron-3-ultra-550b-a55b") + assert ultra["key"] == "perplexity/perplexity/nemotron-3-ultra-550b-a55b" + def test_get_model_info_strips_openai_finetune_ids_without_a_custom_suffix(local_model_cost_map): info = litellm.get_model_info(model="ft:gpt-4o-2024-08-06:my-org::abc123", custom_llm_provider="openai") @@ -4088,9 +4102,9 @@ def test_deepseek_v4_models_in_cost_map(): model_cost = json.load(f) # --- bare model names --- - for key, expected_input, expected_output, expected_cache in [ - ("deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09), - ("deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08), + for key, expected_input, expected_output, expected_cache, expected_vision in [ + ("deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09, True), + ("deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08, False), ]: info = model_cost.get(key) assert info is not None, f"{key} missing from model_prices_and_context_window.json" @@ -4102,11 +4116,12 @@ def test_deepseek_v4_models_in_cost_map(): assert info["max_input_tokens"] == 1_000_000 assert info["supports_function_calling"] is True assert info["supports_tool_choice"] is True + assert info.get("supports_vision", False) is expected_vision # --- provider-prefixed names --- - for key, expected_input, expected_output, expected_cache in [ - ("deepseek/deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09), - ("deepseek/deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08), + for key, expected_input, expected_output, expected_cache, expected_vision in [ + ("deepseek/deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09, True), + ("deepseek/deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08, False), ]: info = model_cost.get(key) assert info is not None, f"{key} missing from model_prices_and_context_window.json" @@ -4117,6 +4132,7 @@ def test_deepseek_v4_models_in_cost_map(): assert info["cache_read_input_token_cost"] == expected_cache assert info["supports_function_calling"] is True assert info["supports_tool_choice"] is True + assert info.get("supports_vision", False) is expected_vision def test_deepseek_v4_models_in_backup_cost_map(): @@ -4132,9 +4148,9 @@ def test_deepseek_v4_models_in_backup_cost_map(): model_cost = json.load(f) # --- bare model names --- - for key, expected_input, expected_output, expected_cache in [ - ("deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09), - ("deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08), + for key, expected_input, expected_output, expected_cache, expected_vision in [ + ("deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09, True), + ("deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08, False), ]: info = model_cost.get(key) assert info is not None, f"{key} missing from backup JSON" @@ -4144,11 +4160,12 @@ def test_deepseek_v4_models_in_backup_cost_map(): assert info["output_cost_per_token"] == expected_output assert info["cache_read_input_token_cost"] == expected_cache assert info["max_input_tokens"] == 1_000_000 + assert info.get("supports_vision", False) is expected_vision # --- provider-prefixed names --- - for key, expected_input, expected_output, expected_cache in [ - ("deepseek/deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09), - ("deepseek/deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08), + for key, expected_input, expected_output, expected_cache, expected_vision in [ + ("deepseek/deepseek-v4-flash", 3e-07, 1.2e-06, 6e-09, True), + ("deepseek/deepseek-v4-pro", 1.32e-06, 3.96e-06, 4.4e-08, False), ]: info = model_cost.get(key) assert info is not None, f"{key} missing from backup JSON" @@ -4157,6 +4174,21 @@ def test_deepseek_v4_models_in_backup_cost_map(): assert info["input_cost_per_token"] == expected_input assert info["output_cost_per_token"] == expected_output assert info["cache_read_input_token_cost"] == expected_cache + assert info.get("supports_vision", False) is expected_vision + + +def test_deprecation_dates_for_retired_xai_and_groq_models(): + import json + from pathlib import Path + + json_path = Path(__file__).parents[2] / "model_prices_and_context_window.json" + with open(json_path) as f: + model_cost = json.load(f) + + assert model_cost["xai/grok-imagine-image-quality"]["deprecation_date"] == "2026-11-02" + assert model_cost["xai/grok-imagine-image-quality-latest"]["deprecation_date"] == "2026-11-02" + assert model_cost["xai/grok-imagine-image-quality-20260403"]["deprecation_date"] == "2026-11-02" + assert model_cost["groq/gemma-7b-it"]["deprecation_date"] == "2024-12-18" @pytest.mark.usefixtures("local_model_cost_map")