diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 8dcd52cae2d..997ce2f6640 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -9641,6 +9641,56 @@ "supports_system_messages": true, "supports_tool_choice": false }, + "deepseek-v4-flash": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "input_cost_per_token_cache_hit": 2.8e-08, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true + }, + "deepseek-v4-pro": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 1.4e-07, + "input_cost_per_token": 1.74e-06, + "input_cost_per_token_cache_hit": 1.4e-07, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 3.48e-06, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true + }, "dashscope/qwen-coder": { "input_cost_per_token": 3e-07, "litellm_provider": "dashscope", @@ -12231,6 +12281,56 @@ "supports_reasoning": true, "supports_tool_choice": true }, + "deepseek/deepseek-v4-flash": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "input_cost_per_token_cache_hit": 2.8e-08, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 2.8e-07, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true + }, + "deepseek/deepseek-v4-pro": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 1.4e-07, + "input_cost_per_token": 1.74e-06, + "input_cost_per_token_cache_hit": 1.4e-07, + "litellm_provider": "deepseek", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "output_cost_per_token": 3.48e-06, + "source": "https://api-docs.deepseek.com/quick_start/pricing", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true + }, "deepseek.v3-v1:0": { "input_cost_per_token": 5.8e-07, "litellm_provider": "bedrock_converse", diff --git a/tests/test_litellm/test_deepseek_model_metadata.py b/tests/test_litellm/test_deepseek_model_metadata.py index 4900af5d97d..e2b68f05a94 100644 --- a/tests/test_litellm/test_deepseek_model_metadata.py +++ b/tests/test_litellm/test_deepseek_model_metadata.py @@ -178,3 +178,98 @@ class TestBareModelFallback: finally: if key in litellm.model_cost and original is not None: litellm.model_cost[key]["supports_function_calling"] = original + + +# --------------------------------------------------------------------------- +# DeepSeek V4 model metadata tests +# --------------------------------------------------------------------------- + + +class TestDeepSeekV4ModelMetadata: + """Verify that DeepSeek V4 Flash and V4 Pro model entries exist + and have correct metadata in the main JSON file.""" + + def _load_main_json(self) -> dict: + main_path = os.path.join( + os.path.dirname(os.path.dirname(litellm.__file__)), + "model_prices_and_context_window.json", + ) + with open(main_path, encoding="utf-8") as f: + return json.load(f) + + def test_v4_flash_exists_prefixed(self): + data = self._load_main_json() + assert "deepseek/deepseek-v4-flash" in data + + def test_v4_pro_exists_prefixed(self): + data = self._load_main_json() + assert "deepseek/deepseek-v4-pro" in data + + def test_v4_flash_exists_bare(self): + data = self._load_main_json() + assert "deepseek-v4-flash" in data + + def test_v4_pro_exists_bare(self): + data = self._load_main_json() + assert "deepseek-v4-pro" in data + + def test_v4_flash_context_window(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-flash"] + assert entry["max_input_tokens"] == 1000000 + assert entry["max_output_tokens"] == 384000 + + def test_v4_pro_context_window(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-pro"] + assert entry["max_input_tokens"] == 1000000 + assert entry["max_output_tokens"] == 384000 + + def test_v4_flash_supports_function_calling(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-flash"] + assert entry.get("supports_function_calling") is True + assert entry.get("supports_tool_choice") is True + + def test_v4_pro_supports_function_calling(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-pro"] + assert entry.get("supports_function_calling") is True + assert entry.get("supports_tool_choice") is True + + def test_v4_flash_supports_reasoning(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-flash"] + assert entry.get("supports_reasoning") is True + + def test_v4_pro_supports_reasoning(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-pro"] + assert entry.get("supports_reasoning") is True + + def test_v4_flash_provider_is_deepseek(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-flash"] + assert entry["litellm_provider"] == "deepseek" + + def test_v4_pro_provider_is_deepseek(self): + data = self._load_main_json() + entry = data["deepseek/deepseek-v4-pro"] + assert entry["litellm_provider"] == "deepseek" + + def test_v4_flash_bare_and_prefixed_match(self): + """Bare and prefixed entries must have the same context window.""" + data = self._load_main_json() + bare = data["deepseek-v4-flash"] + prefixed = data["deepseek/deepseek-v4-flash"] + assert bare["max_input_tokens"] == prefixed["max_input_tokens"] + assert bare["max_output_tokens"] == prefixed["max_output_tokens"] + + def test_v4_pro_bare_and_prefixed_match(self): + """Bare and prefixed entries must have the same context window.""" + data = self._load_main_json() + bare = data["deepseek-v4-pro"] + prefixed = data["deepseek/deepseek-v4-pro"] + assert bare["max_input_tokens"] == prefixed["max_input_tokens"] + assert bare["max_output_tokens"] == prefixed["max_output_tokens"] +