diff --git a/litellm/proxy/openai_files_endpoints/files_endpoints.py b/litellm/proxy/openai_files_endpoints/files_endpoints.py index 143e208a94b..f2a7ccccdf9 100644 --- a/litellm/proxy/openai_files_endpoints/files_endpoints.py +++ b/litellm/proxy/openai_files_endpoints/files_endpoints.py @@ -69,29 +69,6 @@ def get_files_provider_config( ): global files_config if custom_llm_provider == "vertex_ai": - # For Vertex AI, extract config from model_list instead of files_config - from litellm.proxy.proxy_server import proxy_config - - if hasattr(proxy_config, "config") and "model_list" in proxy_config.config: - for model in proxy_config.config["model_list"]: - if isinstance(model, dict) and "litellm_params" in model: - litellm_params = model["litellm_params"] - if litellm_params.get("model", "").startswith("vertex_ai/"): - # Extract vertex_ai specific parameters - vertex_config = {} - if "vertex_project" in litellm_params: - vertex_config["vertex_project"] = litellm_params[ - "vertex_project" - ] - if "vertex_location" in litellm_params: - vertex_config["vertex_location"] = litellm_params[ - "vertex_location" - ] - if "vertex_credentials" in litellm_params: - vertex_config["vertex_credentials"] = litellm_params[ - "vertex_credentials" - ] - return vertex_config return None if files_config is None: raise ValueError("files_settings is not set, set it on your config.yaml file.") diff --git a/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py b/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py index 73c5c51ab91..710e4265013 100644 --- a/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py +++ b/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py @@ -476,176 +476,3 @@ def test_create_file_for_each_model( openai_call_found = True break assert openai_call_found, "OpenAI call not found with expected parameters" - - -def test_get_files_provider_config_vertex_ai_with_model_list(): - """ - Test that get_files_provider_config correctly extracts Vertex AI config from model_list - This test verifies the fix for the proxy file upload issue - """ - from litellm.proxy.openai_files_endpoints.files_endpoints import get_files_provider_config, files_config - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with a model_list containing Vertex AI configuration - mock_config = { - 'model_list': [ - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'test-project-123', - 'vertex_location': 'us-central1', - 'vertex_credentials': '/path/to/service_account.json' - } - }, - { - 'model_name': 'gpt-3.5-turbo', - 'litellm_params': { - 'model': 'openai/gpt-3.5-turbo', - 'api_key': 'test-key' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - # Mock files_config to avoid ValueError for non-vertex_ai providers - original_files_config = files_config - import litellm.proxy.openai_files_endpoints.files_endpoints - litellm.proxy.openai_files_endpoints.files_endpoints.files_config = [] - - try: - # Test that vertex_ai provider returns the correct config - result = get_files_provider_config('vertex_ai') - - assert result is not None, "get_files_provider_config should return config for vertex_ai" - assert result['vertex_project'] == 'test-project-123' - assert result['vertex_location'] == 'us-central1' - assert result['vertex_credentials'] == '/path/to/service_account.json' - - # Test that non-vertex_ai providers still work as before - result_openai = get_files_provider_config('openai') - assert result_openai is None # Should return None when files_config is empty - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - # Restore original files_config - litellm.proxy.openai_files_endpoints.files_endpoints.files_config = original_files_config - - -def test_get_files_provider_config_vertex_ai_no_model_list(): - """ - Test that get_files_provider_config returns None when no model_list is available - This ensures graceful handling when proxy_config is not properly initialized - """ - from litellm.proxy.openai_files_endpoints.files_endpoints import get_files_provider_config - from litellm.proxy.proxy_server import proxy_config - - # Mock proxy_config without model_list - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = {} - - try: - result = get_files_provider_config('vertex_ai') - assert result is None, "get_files_provider_config should return None when no model_list" - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_get_files_provider_config_vertex_ai_no_vertex_models(): - """ - Test that get_files_provider_config returns None when no vertex_ai models are in model_list - This ensures the function handles cases where only non-vertex models are configured - """ - from litellm.proxy.openai_files_endpoints.files_endpoints import get_files_provider_config - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with a model_list containing only non-Vertex AI models - mock_config = { - 'model_list': [ - { - 'model_name': 'gpt-3.5-turbo', - 'litellm_params': { - 'model': 'openai/gpt-3.5-turbo', - 'api_key': 'test-key' - } - }, - { - 'model_name': 'claude-3', - 'litellm_params': { - 'model': 'anthropic/claude-3', - 'api_key': 'test-key' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - assert result is None, "get_files_provider_config should return None when no vertex_ai models in model_list" - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_get_files_provider_config_vertex_ai_partial_config(): - """ - Test that get_files_provider_config handles partial Vertex AI configuration gracefully - This ensures the function works even when some vertex_ai parameters are missing - """ - from litellm.proxy.openai_files_endpoints.files_endpoints import get_files_provider_config - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with partial Vertex AI configuration - mock_config = { - 'model_list': [ - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'test-project-123', - # Missing vertex_location and vertex_credentials - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - assert result is not None, "get_files_provider_config should return config even with partial vertex_ai params" - assert result['vertex_project'] == 'test-project-123' - assert 'vertex_location' not in result - assert 'vertex_credentials' not in result - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') diff --git a/tests/test_litellm/proxy/openai_files_endpoint/test_vertex_ai_files_regression.py b/tests/test_litellm/proxy/openai_files_endpoint/test_vertex_ai_files_regression.py deleted file mode 100644 index e67d70d7602..00000000000 --- a/tests/test_litellm/proxy/openai_files_endpoint/test_vertex_ai_files_regression.py +++ /dev/null @@ -1,271 +0,0 @@ -""" -Regression tests for Vertex AI file upload functionality in the proxy. - -This module contains tests to ensure that the fix for Vertex AI file uploads -in the proxy server continues to work and prevents regression of the issue -where get_files_provider_config returned None for vertex_ai provider. -""" - -import pytest -from unittest.mock import Mock, patch -from litellm.proxy.openai_files_endpoints.files_endpoints import get_files_provider_config - - -def test_vertex_ai_files_provider_config_never_returns_none_when_configured(): - """ - Regression test: Ensure that get_files_provider_config never returns None - for vertex_ai when properly configured in model_list. - - This test prevents regression of the bug where vertex_ai provider - always returned None, causing "Could not resolve project_id" errors. - """ - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with a proper Vertex AI configuration - mock_config = { - 'model_list': [ - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'test-project-123', - 'vertex_location': 'us-central1', - 'vertex_credentials': '/path/to/service_account.json' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - # This should NEVER be None when vertex_ai is properly configured - assert result is not None, ( - "CRITICAL REGRESSION: get_files_provider_config returned None for vertex_ai " - "when it should return configuration. This would cause 'Could not resolve project_id' errors." - ) - - # Verify all expected parameters are present - assert 'vertex_project' in result - assert 'vertex_location' in result - assert 'vertex_credentials' in result - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_vertex_ai_files_provider_config_handles_multiple_vertex_models(): - """ - Test that get_files_provider_config correctly handles multiple Vertex AI models - in the model_list and returns configuration from the first one found. - """ - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with multiple Vertex AI models - mock_config = { - 'model_list': [ - { - 'model_name': 'gemini-1.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-1.5-flash', - 'vertex_project': 'project-1', - 'vertex_location': 'us-east1', - 'vertex_credentials': '/path/to/creds1.json' - } - }, - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'project-2', - 'vertex_location': 'us-central1', - 'vertex_credentials': '/path/to/creds2.json' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - assert result is not None, "Should return config when multiple vertex_ai models are present" - - # Should return config from the first vertex_ai model found - assert result['vertex_project'] == 'project-1' - assert result['vertex_location'] == 'us-east1' - assert result['vertex_credentials'] == '/path/to/creds1.json' - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_vertex_ai_files_provider_config_ignores_non_vertex_models(): - """ - Test that get_files_provider_config correctly identifies vertex_ai models - and ignores other model types when searching for configuration. - """ - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with mixed model types - mock_config = { - 'model_list': [ - { - 'model_name': 'gpt-3.5-turbo', - 'litellm_params': { - 'model': 'openai/gpt-3.5-turbo', - 'api_key': 'test-key' - } - }, - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'test-project', - 'vertex_location': 'us-central1', - 'vertex_credentials': '/path/to/creds.json' - } - }, - { - 'model_name': 'claude-3', - 'litellm_params': { - 'model': 'anthropic/claude-3', - 'api_key': 'test-key' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - assert result is not None, "Should find vertex_ai config even with mixed model types" - assert result['vertex_project'] == 'test-project' - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_vertex_ai_files_provider_config_handles_malformed_model_list(): - """ - Test that get_files_provider_config gracefully handles malformed model_list entries - without crashing. - """ - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with malformed entries - mock_config = { - 'model_list': [ - # Missing litellm_params - { - 'model_name': 'gemini-2.5-flash' - }, - # Missing model field - { - 'model_name': 'gemini-1.5-flash', - 'litellm_params': { - 'vertex_project': 'test-project' - } - }, - # Valid vertex_ai model - { - 'model_name': 'gemini-2.0-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.0-flash', - 'vertex_project': 'test-project', - 'vertex_location': 'us-central1', - 'vertex_credentials': '/path/to/creds.json' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - # Should still work and find the valid vertex_ai model - assert result is not None, "Should handle malformed entries and find valid vertex_ai model" - assert result['vertex_project'] == 'test-project' - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config') - - -def test_vertex_ai_files_provider_config_old_behavior_regression(): - """ - Regression test: Ensure that the old behavior of always returning None - for vertex_ai provider is completely eliminated. - - This test specifically checks that the function no longer has the old - hardcoded return None for vertex_ai. - """ - from litellm.proxy.proxy_server import proxy_config - - # Mock the proxy_config with a minimal but valid Vertex AI configuration - mock_config = { - 'model_list': [ - { - 'model_name': 'gemini-2.5-flash', - 'litellm_params': { - 'model': 'vertex_ai/gemini-2.5-flash', - 'vertex_project': 'minimal-project' - } - } - ] - } - - # Mock proxy_config.config - original_config = getattr(proxy_config, 'config', None) - proxy_config.config = mock_config - - try: - result = get_files_provider_config('vertex_ai') - - # The old behavior would always return None here - # The new behavior should return the configuration - assert result is not None, ( - "REGRESSION DETECTED: The old behavior of returning None for vertex_ai " - "has returned. This indicates the fix has been reverted." - ) - - # Verify we get the expected configuration - assert isinstance(result, dict), "Result should be a dictionary" - assert 'vertex_project' in result, "Should contain vertex_project" - - finally: - # Restore original config - if original_config is not None: - proxy_config.config = original_config - else: - delattr(proxy_config, 'config')