diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 8ed64faceb..a1fd7f7366 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -4625,6 +4625,7 @@ "supports_tool_choice": true }, "claude-3-5-sonnet-latest": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -4671,6 +4672,7 @@ "supports_tool_choice": true }, "claude-3-7-sonnet-latest": { + "supports_computer_use": true, "max_tokens": 128000, "max_input_tokens": 200000, "max_output_tokens": 128000, @@ -4697,6 +4699,7 @@ "supports_reasoning": true }, "claude-3-7-sonnet-20250219": { + "supports_computer_use": true, "max_tokens": 128000, "max_input_tokens": 200000, "max_output_tokens": 128000, @@ -4724,6 +4727,7 @@ "supports_web_search": true }, "claude-3-5-sonnet-20241022": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6458,6 +6462,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6486,6 +6491,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet-v2": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6500,6 +6506,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet-v2@20241022": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6514,6 +6521,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-7-sonnet@20250219": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8055,6 +8063,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.5-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8069,6 +8078,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.5-sonnet:beta": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8082,6 +8092,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.7-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8098,6 +8109,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.7-sonnet:beta": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9110,6 +9122,7 @@ "supports_tool_choice": true }, "anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9129,6 +9142,7 @@ "supports_tool_choice": true }, "anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9219,6 +9233,7 @@ "supports_tool_choice": true }, "us.anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9237,6 +9252,7 @@ "supports_tool_choice": true }, "us.anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9328,6 +9344,7 @@ "supports_tool_choice": true }, "eu.anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9344,6 +9361,7 @@ "supports_tool_choice": true }, "eu.anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -12434,6 +12452,7 @@ "mode": "chat" }, "snowflake/claude-3-5-sonnet": { + "supports_computer_use": true, "max_tokens": 18000, "max_input_tokens": 18000, "max_output_tokens": 8192, @@ -12746,4 +12765,4 @@ "litellm_provider": "featherless_ai", "mode": "chat" } -} +} \ No newline at end of file diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 9c70900d03..2b230d089c 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -111,6 +111,7 @@ class ProviderSpecificModelInfo(TypedDict, total=False): supports_tool_choice: Optional[bool] supports_assistant_prefill: Optional[bool] supports_prompt_caching: Optional[bool] + supports_computer_use: Optional[bool] supports_audio_input: Optional[bool] supports_embedding_image_input: Optional[bool] supports_audio_output: Optional[bool] diff --git a/litellm/utils.py b/litellm/utils.py index d2cf36f24c..5d6a64cd34 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -1967,6 +1967,28 @@ def supports_prompt_caching( key="supports_prompt_caching", ) +def supports_computer_use( + model: str, custom_llm_provider: Optional[str] = None +) -> bool: + """ + Check if the given model supports computer use and return a boolean value. + + Parameters: + model (str): The model name to be checked. + custom_llm_provider (Optional[str]): The provider to be checked. + + Returns: + bool: True if the model supports computer use, False otherwise. + + Raises: + Exception: If the given model is not found or there's an error in retrieval. + """ + return _supports_factory( + model=model, + custom_llm_provider=custom_llm_provider, + key="supports_computer_use", + ) + def supports_vision(model: str, custom_llm_provider: Optional[str] = None) -> bool: """ @@ -4271,6 +4293,7 @@ def _get_model_info_helper( # noqa: PLR0915 supports_tool_choice=None, supports_assistant_prefill=None, supports_prompt_caching=None, + supports_computer_use=None, supports_pdf_input=None, ) elif ( @@ -4444,6 +4467,7 @@ def _get_model_info_helper( # noqa: PLR0915 ), supports_web_search=_model_info.get("supports_web_search", False), supports_reasoning=_model_info.get("supports_reasoning", False), + supports_computer_use=_model_info.get("supports_computer_use", False), search_context_cost_per_query=_model_info.get( "search_context_cost_per_query", None ), diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 8ed64faceb..a1fd7f7366 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -4625,6 +4625,7 @@ "supports_tool_choice": true }, "claude-3-5-sonnet-latest": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -4671,6 +4672,7 @@ "supports_tool_choice": true }, "claude-3-7-sonnet-latest": { + "supports_computer_use": true, "max_tokens": 128000, "max_input_tokens": 200000, "max_output_tokens": 128000, @@ -4697,6 +4699,7 @@ "supports_reasoning": true }, "claude-3-7-sonnet-20250219": { + "supports_computer_use": true, "max_tokens": 128000, "max_input_tokens": 200000, "max_output_tokens": 128000, @@ -4724,6 +4727,7 @@ "supports_web_search": true }, "claude-3-5-sonnet-20241022": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6458,6 +6462,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6486,6 +6491,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet-v2": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6500,6 +6506,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-5-sonnet-v2@20241022": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -6514,6 +6521,7 @@ "supports_tool_choice": true }, "vertex_ai/claude-3-7-sonnet@20250219": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8055,6 +8063,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.5-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8069,6 +8078,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.5-sonnet:beta": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8082,6 +8092,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.7-sonnet": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -8098,6 +8109,7 @@ "supports_tool_choice": true }, "openrouter/anthropic/claude-3.7-sonnet:beta": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9110,6 +9122,7 @@ "supports_tool_choice": true }, "anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9129,6 +9142,7 @@ "supports_tool_choice": true }, "anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9219,6 +9233,7 @@ "supports_tool_choice": true }, "us.anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9237,6 +9252,7 @@ "supports_tool_choice": true }, "us.anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9328,6 +9344,7 @@ "supports_tool_choice": true }, "eu.anthropic.claude-3-5-sonnet-20241022-v2:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -9344,6 +9361,7 @@ "supports_tool_choice": true }, "eu.anthropic.claude-3-7-sonnet-20250219-v1:0": { + "supports_computer_use": true, "max_tokens": 8192, "max_input_tokens": 200000, "max_output_tokens": 8192, @@ -12434,6 +12452,7 @@ "mode": "chat" }, "snowflake/claude-3-5-sonnet": { + "supports_computer_use": true, "max_tokens": 18000, "max_input_tokens": 18000, "max_output_tokens": 8192, @@ -12746,4 +12765,4 @@ "litellm_provider": "featherless_ai", "mode": "chat" } -} +} \ No newline at end of file diff --git a/tests/litellm/test_utils.py b/tests/litellm/test_utils.py index c6c6b6d466..7a2b6aa010 100644 --- a/tests/litellm/test_utils.py +++ b/tests/litellm/test_utils.py @@ -339,6 +339,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "additionalProperties": { "type": "object", "properties": { + "supports_computer_use": {"type": "boolean"}, "cache_creation_input_audio_token_cost": {"type": "number"}, "cache_creation_input_token_cost": {"type": "number"}, "cache_read_input_token_cost": {"type": "number"}, @@ -693,3 +694,64 @@ async def test_supports_tool_choice(): assert ( supports_tool_choice_result == tool_choice_in_params ), f"Tool choice support mismatch for {model_name}. supports_tool_choice() returned: {supports_tool_choice_result}, tool_choice in supported params: {tool_choice_in_params}\nConfig: {config}" + + +def test_supports_computer_use_utility(): + """ + Tests the litellm.utils.supports_computer_use utility function. + """ + from litellm.utils import supports_computer_use + # Ensure LITELLM_LOCAL_MODEL_COST_MAP is set for consistent test behavior, + # as supports_computer_use relies on get_model_info. + # This also requires litellm.model_cost to be populated. + original_env_var = os.getenv("LITELLM_LOCAL_MODEL_COST_MAP") + original_model_cost = getattr(litellm, "model_cost", None) + + os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" + litellm.model_cost = litellm.get_model_cost_map(url="") # Load with local/backup + + try: + # Test a model known to support computer_use from backup JSON + supports_cu_anthropic = supports_computer_use(model="anthropic/claude-3-7-sonnet-20250219") + assert supports_cu_anthropic is True + + # Test a model known not to have the flag or set to false (defaults to False via get_model_info) + supports_cu_gpt = supports_computer_use(model="gpt-3.5-turbo") + assert supports_cu_gpt is False + finally: + # Restore original environment and model_cost to avoid side effects + if original_env_var is None: + del os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] + else: + os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = original_env_var + + if original_model_cost is not None: + litellm.model_cost = original_model_cost + elif hasattr(litellm, "model_cost"): + delattr(litellm, "model_cost") + +def test_get_model_info_shows_supports_computer_use(): + """ + Tests if 'supports_computer_use' is correctly retrieved by get_model_info. + We'll use 'claude-3-7-sonnet-20250219' as it's configured + in the backup JSON to have supports_computer_use: True. + """ + os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" + # Ensure litellm.model_cost is loaded, relying on the backup mechanism if primary fails + # as per previous debugging. + litellm.model_cost = litellm.get_model_cost_map(url="") + + # This model should have 'supports_computer_use': True in the backup JSON + model_known_to_support_computer_use = "claude-3-7-sonnet-20250219" + info = litellm.get_model_info(model_known_to_support_computer_use) + print(f"Info for {model_known_to_support_computer_use}: {info}") + + # After the fix in utils.py, this should now be present and True + assert info.get("supports_computer_use") is True + + # Optionally, test a model known NOT to support it, or where it's undefined (should default to False) + # For example, if "gpt-3.5-turbo" doesn't have it defined, it should be False. + model_known_not_to_support_computer_use = "gpt-3.5-turbo" + info_gpt = litellm.get_model_info(model_known_not_to_support_computer_use) + print(f"Info for {model_known_not_to_support_computer_use}: {info_gpt}") + assert info_gpt.get("supports_computer_use") is False # Expecting False due to the default in ModelInfoBase \ No newline at end of file diff --git a/tests/local_testing/test_get_model_info.py b/tests/local_testing/test_get_model_info.py index cff7be4cc0..40e52c8173 100644 --- a/tests/local_testing/test_get_model_info.py +++ b/tests/local_testing/test_get_model_info.py @@ -392,4 +392,3 @@ def test_get_model_info_cost_calculator_bedrock_region_cris_stripped(model, prov print("info", info) assert info["key"] == "us.anthropic.claude-3-haiku-20240307-v1:0" assert info["litellm_provider"] == "bedrock" -