From 1eafdbfba9fe297c16fb8343e2aa95b2f54eba15 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Thu, 11 Jun 2026 18:56:50 +0000 Subject: [PATCH] test(llm_translation): drop mock-passthrough and dead tests across long-tail providers per CI audit Function-level deletions per the keep/drop audit (5), plus dead tests flagged in 8b: - test_cohere.py: test_cohere_request_body_with_allowed_params, test_cohere_documents_options_in_request_body (kwarg passthrough into mocked post, c) - test_deepseek_completion.py: test_deepseek_mock_completion, test_deepseek_provider_async_completion (mock theater, a/c) - test_elevenlabs.py: test_elevenlabs_diarize_parameter_passthrough (form-data passthrough on stub, c) - test_huggingface_chat_completion.py: TestHuggingFace test_completion_with_api_base, test_async_completion_with_api_base, test_completion_streaming_with_api_base (URL asserted on mock, b) - test_hyperbolic.py: test_hyperbolic_completion_call (mock_response smoke) - test_minimax_tts.py: test_speech_mock_response (mock-handler-was-called, a) - test_nvidia_nim.py: test_completion_nvidia_nim, test_embedding_nvidia_nim, test_chat_completion_nvidia_nim_with_tools (SDK-patch passthrough, c) - test_rerank.py: test_rerank_custom_api_base, test_complete_base_url_cohere, test_cohere_rerank_v2_client, test_rerank_infer_region_from_model_arn (URL/mock-payload, b/d) - test_text_completion_unit_tests.py: test_huggingface_text_completion_logprobs (permanent @skip, dead), test_acompletion_uses_optimized_http_client (a) - test_together_ai.py: test_tool_call_no_arguments override (dead pass body) - test_triton.py: test_triton_embeddings (depends on external stub endpoint) - test_voyage_ai.py: test_basic_embedding override, test_voyage_ai_embedding_extra_params, test_voyage_ai_embedding_prompt_token_mapping, test_contextual_embedding_integration, test_contextual_embedding_multiple_inputs (patch litellm.embedding wholesale, a/d) - test_watsonx.py: test_watsonx_custom_auth_header, test_watsonx_token_in_env_var, test_watsonx_chat_completions_endpoint (auth header/URL on stub, b) - test_xai.py: test_tool_call_no_arguments override (dead pass body) - test_gemini.py: parametrized exception test literally named 'l' (never collected by pytest; coverage it claims does not exist) Unused imports removed via ruff F401. --- tests/llm_translation/test_cohere.py | 133 +----------- .../test_deepseek_completion.py | 91 -------- tests/llm_translation/test_elevenlabs.py | 112 ---------- tests/llm_translation/test_gemini.py | 98 +-------- .../test_huggingface_chat_completion.py | 64 ------ tests/llm_translation/test_hyperbolic.py | 20 -- tests/llm_translation/test_minimax_tts.py | 45 +--- tests/llm_translation/test_nvidia_nim.py | 171 +-------------- tests/llm_translation/test_rerank.py | 201 ----------------- .../test_text_completion_unit_tests.py | 156 ------------- tests/llm_translation/test_together_ai.py | 7 - tests/llm_translation/test_triton.py | 22 +- tests/llm_translation/test_voyage_ai.py | 205 +----------------- tests/llm_translation/test_watsonx.py | 56 ----- tests/llm_translation/test_xai.py | 9 - 15 files changed, 6 insertions(+), 1384 deletions(-) diff --git a/tests/llm_translation/test_cohere.py b/tests/llm_translation/test_cohere.py index 2d719cbde36..6fb74e7cfbc 100644 --- a/tests/llm_translation/test_cohere.py +++ b/tests/llm_translation/test_cohere.py @@ -1,25 +1,18 @@ import os import sys -import traceback from dotenv import load_dotenv load_dotenv() -import io -import os sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path -import json import pytest import litellm -from litellm import RateLimitError, Timeout, completion, completion_cost, embedding -from unittest.mock import AsyncMock, patch -from litellm import RateLimitError, Timeout, completion, completion_cost, embedding -from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler +from litellm import completion, embedding litellm.num_retries = 3 @@ -205,74 +198,6 @@ async def test_chat_completion_cohere_stream(sync_mode): pytest.fail(f"Error occurred: {e}") -@pytest.mark.asyncio -async def test_cohere_request_body_with_allowed_params(): - """ - Test to validate that when allowed_openai_params is provided, the request body contains - the correct response_format and reasoning_effort values. - """ - # Define test parameters - test_response_format = {"type": "json"} - test_reasoning_effort = "low" - test_tools = [ - { - "type": "function", - "function": { - "name": "get_current_time", - "description": "Get the current time in a given location.", - "parameters": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city name, e.g. San Francisco", - } - }, - "required": ["location"], - }, - }, - } - ] - - # Create a mock response - mock_response = AsyncMock() - mock_response.status_code = 200 - mock_response.json.return_value = { - "text": "I am Command, a language model developed by Cohere.", - "generation_id": "mock-generation-id", - "finish_reason": "COMPLETE", - } - - # Mock the AsyncHTTPHandler.post method at the module level - with patch( - "litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post", - return_value=mock_response, - ) as mock_post: - try: - await litellm.acompletion( - model="cohere/v1/command", - messages=[{"content": "what llm are you", "role": "user"}], - allowed_openai_params=["tools", "response_format", "reasoning_effort"], - response_format=test_response_format, - reasoning_effort=test_reasoning_effort, - tools=test_tools, - ) - except Exception: - pass # We only care about the request body validation - - # Verify the API call was made - mock_post.assert_called_once() - - # Get and parse the request body - request_data = json.loads(mock_post.call_args.kwargs["data"]) - print(f"request_data: {request_data}") - - # Validate request contains our specified parameters - assert "allowed_openai_params" not in request_data - assert request_data["response_format"] == test_response_format - assert request_data["reasoning_effort"] == test_reasoning_effort - - def test_cohere_embedding_outout_dimensions(): litellm._turn_on_debug() response = embedding( @@ -796,62 +721,6 @@ def test_cohere_v2_error_handling(): pytest.fail(f"Unexpected error in error handling test: {e}") -@pytest.mark.asyncio -async def test_cohere_documents_options_in_request_body(): - """ - Test that documents parameters is properly included - in the request body after transformation (sent via extra_body). - """ - # Create a mock response - mock_response = AsyncMock() - mock_response.status_code = 200 - mock_response.json.return_value = { - "text": "Test response with citations", - "generation_id": "mock-generation-id", - "finish_reason": "COMPLETE", - } - - # Mock the AsyncHTTPHandler.post method - with patch( - "litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post", - return_value=mock_response, - ) as mock_post: - try: - # Test documents and citation_options parameters - test_documents = [ - { - "data": { - "title": "Test Document 1", - "snippet": "This is test content 1", - } - }, - { - "data": { - "title": "Test Document 2", - "snippet": "This is test content 2", - } - }, - ] - await litellm.acompletion( - model="cohere_chat/command-a-03-2025", - messages=[{"role": "user", "content": "Test message"}], - documents=test_documents, - ) - except Exception: - pass # We only care about the request body validation - - # Verify the API call was made - mock_post.assert_called_once() - - # Get and parse the request body - request_data = json.loads(mock_post.call_args.kwargs["data"]) - print(f"Request body: {request_data}") - - # Validate that documents and citation_options are in the request body - assert "documents" in request_data - assert request_data["documents"] == test_documents - - @pytest.mark.asyncio @pytest.mark.flaky(retries=3, delay=1) async def test_cohere_v2_conversation_history(): diff --git a/tests/llm_translation/test_deepseek_completion.py b/tests/llm_translation/test_deepseek_completion.py index 2ede5d3f3f8..cf31b882c14 100644 --- a/tests/llm_translation/test_deepseek_completion.py +++ b/tests/llm_translation/test_deepseek_completion.py @@ -16,97 +16,6 @@ class TestDeepSeekChatCompletion(BaseLLMChatTest): pass -@pytest.mark.parametrize("stream", [True, False]) -def test_deepseek_mock_completion(stream): - """ - Deepseek API is hanging. Mock the call, to a fake endpoint, so we can confirm our integration is working. - """ - import litellm - from litellm import completion - - litellm._turn_on_debug() - - response = completion( - model="deepseek/deepseek-reasoner", - messages=[{"role": "user", "content": "Hello, world!"}], - api_base="https://exampleopenaiendpoint-production.up.railway.app/v1/chat/completions", - stream=stream, - mock_response="Hello! How can I help you today?", - ) - print(f"response: {response}") - if stream: - for chunk in response: - print(chunk) - else: - assert response is not None - - -@pytest.mark.parametrize("stream", [False, True]) -@pytest.mark.asyncio -async def test_deepseek_provider_async_completion(stream): - """ - Test that Deepseek provider requests are formatted correctly with the proper parameters - """ - import litellm - import json - from unittest.mock import patch, AsyncMock, MagicMock - from litellm import acompletion - - litellm._turn_on_debug() - - # Set up the test parameters - api_key = "fake_api_key" - model = "deepseek/deepseek-reasoner" - messages = [{"role": "user", "content": "Hello, world!"}] - - # Mock AsyncHTTPHandler.post method for async test - with patch( - "litellm.llms.custom_httpx.llm_http_handler.AsyncHTTPHandler.post" - ) as mock_post: - mock_response_data = litellm.ModelResponse( - choices=[ - litellm.Choices( - message=litellm.Message(content="Hello!"), - index=0, - finish_reason="stop", - ) - ] - ).model_dump() - # Create a proper mock response - mock_response = MagicMock() # Use MagicMock instead of AsyncMock - mock_response.status_code = 200 - mock_response.text = json.dumps(mock_response_data) - mock_response.headers = {"Content-Type": "application/json"} - - # Make json() return a value directly, not a coroutine - mock_response.json.return_value = mock_response_data - - # Set the return value for the post method - mock_post.return_value = mock_response - - await acompletion( - custom_llm_provider="deepseek", - api_key=api_key, - model=model, - messages=messages, - stream=stream, - ) - - # Verify the request was made with the correct parameters - mock_post.assert_called_once() - call_args = mock_post.call_args - print("request call=", json.dumps(call_args.kwargs, indent=4, default=str)) - - # Check request body - request_body = json.loads(call_args.kwargs["data"]) - assert call_args.kwargs["url"] == "https://api.deepseek.com/beta/chat/completions" - assert ( - request_body["model"] == "deepseek-reasoner" - ) # Model name should be stripped of provider prefix - assert request_body["messages"] == messages - assert request_body["stream"] == stream - - def test_completion_cost_deepseek(): litellm.set_verbose = True model_name = "deepseek/deepseek-chat" diff --git a/tests/llm_translation/test_elevenlabs.py b/tests/llm_translation/test_elevenlabs.py index b6c838d2300..35e7fe69b3d 100644 --- a/tests/llm_translation/test_elevenlabs.py +++ b/tests/llm_translation/test_elevenlabs.py @@ -4,8 +4,6 @@ import sys from typing import Any, Dict import pytest -from unittest.mock import patch, MagicMock -import httpx sys.path.insert( 0, os.path.abspath("../..") @@ -25,116 +23,6 @@ class TestElevenLabsAudioTranscription(BaseLLMAudioTranscriptionTest): def get_custom_llm_provider(self) -> litellm.LlmProviders: return litellm.LlmProviders.ELEVENLABS - def test_elevenlabs_diarize_parameter_passthrough(self): - """ - Test that provider-specific parameters like diarize=True get passed through - to the ElevenLabs request form data. - """ - # Mock successful response - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.text = ( - '{"text": "Four score and seven years ago", "language_code": "en"}' - ) - mock_response.json.return_value = { - "text": "Four score and seven years ago", - "language_code": "en", - "words": [ - {"type": "word", "text": "Four", "start": 0.0, "end": 0.5}, - {"type": "word", "text": "score", "start": 0.5, "end": 1.0}, - ], - } - - # Create a mock audio file - audio_content = b"fake audio data" - - captured_request_data = {} - - def mock_post(*args, **kwargs): - # Capture the request data for verification - captured_request_data.update( - { - "url": kwargs.get("url"), - "data": kwargs.get("data"), - "files": kwargs.get("files"), - "headers": kwargs.get("headers"), - "json": kwargs.get("json"), - } - ) - return mock_response - - # Mock the HTTPHandler.post method which is what actually makes the request - from litellm.llms.custom_httpx.http_handler import HTTPHandler - - with patch.object(HTTPHandler, "post", side_effect=mock_post): - try: - result = litellm.transcription( - model="elevenlabs/scribe_v1", - file=audio_content, - diarize=True, # This should be passed through to the form data - language="en", # This should be mapped to language_code - temperature=0.5, # This should also be passed through - custom_param="test_value", # This should also be passed through - ) - - # Verify the request was made with correct form data - assert "speech-to-text" in captured_request_data["url"] - - # Check that form data contains the expected parameters - form_data = captured_request_data["data"] - assert form_data is not None, "Form data should not be None" - - print(f"✅ Captured form data: {form_data}") - - # Check basic required parameters - assert "model_id" in form_data, "model_id should be in form data" - assert ( - form_data["model_id"] == "scribe_v1" - ), f"Expected model_id 'scribe_v1', got {form_data['model_id']}" - - # Check that diarize parameter is passed through - assert ( - "diarize" in form_data - ), f"diarize should be in form data. Got: {list(form_data.keys())}" - assert ( - form_data["diarize"] == "True" - ), f"Expected diarize='True', got {form_data['diarize']}" - - # Check that OpenAI language parameter is mapped correctly - assert ( - "language_code" in form_data - ), "language_code should be in form data" - assert ( - form_data["language_code"] == "en" - ), f"Expected language_code='en', got {form_data['language_code']}" - - # Check that temperature is passed through - assert "temperature" in form_data, "temperature should be in form data" - assert ( - form_data["temperature"] == "0.5" - ), f"Expected temperature='0.5', got {form_data['temperature']}" - - # Check that custom parameters are passed through - assert ( - "custom_param" in form_data - ), "custom_param should be in form data" - assert ( - form_data["custom_param"] == "test_value" - ), f"Expected custom_param='test_value', got {form_data['custom_param']}" - - # Check that files are included - files = captured_request_data["files"] - assert files is not None, "Files should not be None" - assert "file" in files, "file should be in files" - - print("✅ All parameter passthrough tests passed!") - - except Exception as e: - print(f"❌ Test failed: {e}") - print(f"Captured request data: {captured_request_data}") - raise - - class TestElevenLabsTextToSpeechTransformation: @pytest.fixture(scope="class") def config(self): diff --git a/tests/llm_translation/test_gemini.py b/tests/llm_translation/test_gemini.py index 0a5aebdf91b..58376d0bd35 100644 --- a/tests/llm_translation/test_gemini.py +++ b/tests/llm_translation/test_gemini.py @@ -567,7 +567,6 @@ def test_gemini_imagen_models_use_predict_endpoint(): Test that Imagen models still use :predict endpoint (not broken by gemini-2.5-flash-image-preview fix) """ from unittest.mock import patch, MagicMock - from litellm.types.utils import ImageResponse, ImageObject with patch( "litellm.llms.custom_httpx.llm_http_handler.HTTPHandler.post" @@ -655,7 +654,7 @@ def test_gemini_thinking(): def test_gemini_thinking_budget_0(): litellm._turn_on_debug() - from litellm.types.utils import Message, CallTypes + from litellm.types.utils import CallTypes from litellm.utils import return_raw_request import json @@ -677,7 +676,6 @@ def test_gemini_thinking_budget_0(): def test_gemini_finish_reason(): - import os from litellm import completion litellm._turn_on_debug() @@ -1121,7 +1119,6 @@ def get_current_weather(location, unit="fahrenheit"): def test_gemini_with_thinking(): - from litellm import completion litellm._turn_on_debug() litellm.modify_params = True @@ -1218,7 +1215,6 @@ def test_gemini_reasoning_effort_minimal(): """ from litellm.utils import return_raw_request from litellm.types.utils import CallTypes - import json # Test with different Gemini models to verify model-specific mapping test_cases = [ @@ -1341,97 +1337,6 @@ def test_gemini_exception_message_format(): ), f"Should not contain 'VertexAIException' in error message, got: {error_message}" -@pytest.mark.parametrize( - "status_code,expected_exception", - [ - (400, "BadRequestError"), - (401, "AuthenticationError"), - (403, "PermissionDeniedError"), - (404, "NotFoundError"), - (408, "Timeout"), - (429, "RateLimitError"), - (500, "InternalServerError"), - (502, "APIConnectionError"), - (503, "ServiceUnavailableError"), - ], -) -def l(status_code, expected_exception): - """ - Test comprehensive Gemini error handling for all HTTP status codes. - - This ensures that Gemini API errors of different types are properly mapped - to the correct LiteLLM exception types with GeminiException prefix. - """ - import httpx - from unittest.mock import Mock - from litellm.litellm_core_utils.exception_mapping_utils import exception_type - from litellm.exceptions import ( - BadRequestError, - AuthenticationError, - PermissionDeniedError, - NotFoundError, - Timeout, - RateLimitError, - InternalServerError, - APIConnectionError, - ServiceUnavailableError, - ) - - # Mock the appropriate error response - mock_response = Mock(spec=httpx.Response) - mock_response.status_code = status_code - mock_response.text = f"API Error {status_code}" - mock_response.headers = {} - - # Create a mock exception - mock_exception = httpx.HTTPStatusError( - message=f"HTTP {status_code}", request=Mock(), response=mock_response - ) - mock_exception.response = mock_response - mock_exception.status_code = status_code - # Set message attribute for compatibility with exception mapping - mock_exception.message = f"HTTP {status_code}" - - # Test the exception mapping - try: - exception_type( - model="gemini-pro", - original_exception=mock_exception, - custom_llm_provider="gemini", - completion_kwargs={}, - extra_kwargs={}, - ) - assert ( - False - ), f"Expected {expected_exception} to be raised for status {status_code}" - except Exception as e: - # Verify the correct exception type is raised - exception_classes = { - "BadRequestError": BadRequestError, - "AuthenticationError": AuthenticationError, - "PermissionDeniedError": PermissionDeniedError, - "NotFoundError": NotFoundError, - "Timeout": Timeout, - "RateLimitError": RateLimitError, - "InternalServerError": InternalServerError, - "APIConnectionError": APIConnectionError, - "ServiceUnavailableError": ServiceUnavailableError, - } - expected_class = exception_classes[expected_exception] - assert isinstance( - e, expected_class - ), f"Expected {expected_exception}, got {type(e).__name__}" - - # Verify the error message contains GeminiException - error_message = str(e) - assert ( - "GeminiException" in error_message - ), f"Expected 'GeminiException' in error message for status {status_code}, got: {error_message}" - assert ( - "VertexAIException" not in error_message - ), f"Should not contain 'VertexAIException' for status {status_code}, got: {error_message}" - - def test_gemini_embedding(): litellm._turn_on_debug() response = litellm.embedding( @@ -1710,7 +1615,6 @@ def test_anthropic_thinking_param_via_map_openai_params(): from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( VertexGeminiConfig, ) - from litellm.types.llms.anthropic import AnthropicThinkingParam config = VertexGeminiConfig() diff --git a/tests/llm_translation/test_huggingface_chat_completion.py b/tests/llm_translation/test_huggingface_chat_completion.py index cdf3f9ef76f..5dccd108477 100644 --- a/tests/llm_translation/test_huggingface_chat_completion.py +++ b/tests/llm_translation/test_huggingface_chat_completion.py @@ -447,70 +447,6 @@ class TestHuggingFace(BaseLLMChatTest): ) assert url == expected_url - def test_completion_with_api_base(self): - messages = [{"role": "user", "content": "This is a test message"}] - api_base = "https://abcd123.us-east-1.aws.endpoints.huggingface.cloud" - - response = litellm.completion( - model="huggingface/tgi", messages=messages, api_base=api_base, stream=False - ) - - assert isinstance(response, ModelResponse) - assert ( - response.choices[0].message.content - == "This is a test response from the mocked HuggingFace API." - ) - - assert self.mock_http.called - call_args = self.mock_http.call_args - assert call_args is not None - - called_url = call_args[1]["url"] - assert called_url == f"{api_base}/v1/chat/completions" - - @pytest.mark.asyncio - async def test_async_completion_with_api_base(self): - messages = [{"role": "user", "content": "This is a test message"}] - api_base = "https://abcd123.us-east-1.aws.endpoints.huggingface.cloud" - - response = await litellm.acompletion( - model="huggingface/tgi", messages=messages, api_base=api_base, stream=False - ) - - assert isinstance(response, ModelResponse) - assert ( - response.choices[0].message.content - == "This is a test response from the mocked HuggingFace API." - ) - - assert self.mock_http_async.called - call_args = self.mock_http_async.call_args - assert call_args is not None - - called_url = call_args[1]["url"] - assert called_url == f"{api_base}/v1/chat/completions" - - def test_completion_streaming_with_api_base(self): - """Test streaming completion with api_base parameter""" - messages = [{"role": "user", "content": "This is a test message"}] - api_base = "https://abcd123.us-east-1.aws.endpoints.huggingface.cloud" - - response = litellm.completion( - model="huggingface/tgi", messages=messages, api_base=api_base, stream=True - ) - - chunks = list(response) - assert len(chunks) > 0 - assert isinstance(chunks[0], ModelResponseStream) - - # Check that the correct URL was called - assert self.mock_http.called - call_args = self.mock_http.call_args - assert call_args is not None - - called_url = call_args[1]["url"] - assert called_url == f"{api_base}/v1/chat/completions" - def test_build_chat_completion_url_function(self): """Test the _build_chat_completion_url helper function""" from litellm.llms.huggingface.chat.transformation import ( diff --git a/tests/llm_translation/test_hyperbolic.py b/tests/llm_translation/test_hyperbolic.py index ce77ddec73b..2b0d4413cf6 100644 --- a/tests/llm_translation/test_hyperbolic.py +++ b/tests/llm_translation/test_hyperbolic.py @@ -1,15 +1,11 @@ import os import sys -from datetime import datetime -from unittest.mock import MagicMock -import pytest sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path -import litellm from litellm import get_llm_provider @@ -20,22 +16,6 @@ def test_get_llm_provider_hyperbolic(): assert model == "deepseek-v3" -def test_hyperbolic_completion_call(): - """Test basic completion call structure for Hyperbolic""" - # This is primarily a structure test since we don't have actual API keys - try: - litellm.set_verbose = True - response = litellm.completion( - model="hyperbolic/qwen-2.5-72b", - messages=[{"role": "user", "content": "Hello!"}], - mock_response="Hi there!", - ) - assert response is not None - except Exception as e: - # Expected to fail without valid API key, but should recognize the provider - assert "hyperbolic" in str(e).lower() or "api" in str(e).lower() - - def test_hyperbolic_config_initialization(): """Test that HyperbolicChatConfig initializes correctly""" from litellm.llms.hyperbolic.chat.transformation import HyperbolicChatConfig diff --git a/tests/llm_translation/test_minimax_tts.py b/tests/llm_translation/test_minimax_tts.py index 2e3e97888e9..53f260dce54 100644 --- a/tests/llm_translation/test_minimax_tts.py +++ b/tests/llm_translation/test_minimax_tts.py @@ -5,7 +5,7 @@ Tests for MiniMax Text-to-Speech integration import os import sys from pathlib import Path -from unittest.mock import MagicMock, Mock, patch +from unittest.mock import patch import pytest @@ -139,7 +139,6 @@ class TestMinimaxTextToSpeechConfig: # Mock both litellm.api_key and get_secret_str to return None import litellm - from unittest.mock import patch original_api_key = litellm.api_key try: @@ -272,48 +271,6 @@ class TestMinimaxSpeechIntegration: # Clean up speech_file_path.unlink() - def test_speech_mock_response(self): - """Test speech synthesis with mocked response""" - from unittest.mock import MagicMock, patch - - # Create mock audio data (hex-encoded as MiniMax returns) - mock_audio_bytes = b"fake audio data for testing" - mock_audio_hex = mock_audio_bytes.hex() - - mock_response_json = { - "data": {"audio": mock_audio_hex, "status": 0, "ced": ""}, - "extra_info": {}, - } - - with patch( - "litellm.llms.custom_httpx.llm_http_handler.BaseLLMHTTPHandler.text_to_speech_handler" - ) as mock_tts: - # Create a mock httpx.Response - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.headers = {} - mock_response.json.return_value = mock_response_json - mock_response.content = mock_audio_bytes - - # Mock the response wrapper - from litellm.types.llms.openai import HttpxBinaryResponseContent - - mock_binary_response = HttpxBinaryResponseContent(mock_response) - mock_tts.return_value = mock_binary_response - - # This would normally make a real API call - # but we're mocking it for testing - response = speech( - model="minimax/speech-2.6-hd", - voice="alloy", - input="Test input", - api_key="test-key", - ) - - # Verify the mock was called - assert mock_tts.called - - class TestMinimaxProviderRegistration: """Test that MiniMax is properly registered as a provider""" diff --git a/tests/llm_translation/test_nvidia_nim.py b/tests/llm_translation/test_nvidia_nim.py index 80e764147bb..db7590c79fe 100644 --- a/tests/llm_translation/test_nvidia_nim.py +++ b/tests/llm_translation/test_nvidia_nim.py @@ -1,7 +1,6 @@ import json import os import sys -from datetime import datetime from unittest.mock import AsyncMock sys.path.insert( @@ -9,179 +8,11 @@ sys.path.insert( ) # Adds the parent directory to the system path -import httpx import pytest -from unittest.mock import patch, MagicMock, AsyncMock +from unittest.mock import patch, MagicMock import litellm -from litellm import Choices, Message, ModelResponse, EmbeddingResponse, Usage -from litellm import completion from base_rerank_unit_tests import BaseLLMRerankTest -import litellm - - -def test_completion_nvidia_nim(): - from openai import OpenAI - - litellm.set_verbose = True - model_name = "nvidia_nim/databricks/dbrx-instruct" - client = OpenAI( - api_key="fake-api-key", - ) - - with patch.object( - client.chat.completions.with_raw_response, "create" - ) as mock_client: - try: - completion( - model=model_name, - messages=[ - { - "role": "user", - "content": "What's the weather like in Boston today in Fahrenheit?", - } - ], - presence_penalty=0.5, - frequency_penalty=0.1, - client=client, - ) - except Exception as e: - print(e) - # Add any assertions here to check the response - - mock_client.assert_called_once() - request_body = mock_client.call_args.kwargs - - print("request_body: ", request_body) - - assert request_body["messages"] == [ - { - "role": "user", - "content": "What's the weather like in Boston today in Fahrenheit?", - }, - ] - assert request_body["model"] == "databricks/dbrx-instruct" - assert request_body["frequency_penalty"] == 0.1 - assert request_body["presence_penalty"] == 0.5 - - -def test_embedding_nvidia_nim(): - litellm.set_verbose = True - from openai import OpenAI - - client = OpenAI( - api_key="fake-api-key", - ) - with patch.object(client.embeddings.with_raw_response, "create") as mock_client: - try: - litellm.embedding( - model="nvidia_nim/nvidia/nv-embedqa-e5-v5", - input="What is the meaning of life?", - input_type="passage", - dimensions=1024, - client=client, - ) - except Exception as e: - print(e) - mock_client.assert_called_once() - request_body = mock_client.call_args.kwargs - print("request_body: ", request_body) - assert request_body["input"] == "What is the meaning of life?" - assert request_body["model"] == "nvidia/nv-embedqa-e5-v5" - assert request_body["extra_body"]["input_type"] == "passage" - assert request_body["dimensions"] == 1024 - - -def test_chat_completion_nvidia_nim_with_tools(): - from openai import OpenAI - - litellm.set_verbose = True - model_name = "nvidia_nim/meta/llama3-70b-instruct" - client = OpenAI( - api_key="fake-api-key", - ) - - # Define tools - tools = [ - { - "type": "function", - "function": { - "name": "get_weather", - "description": "Get the current weather in a given location", - "parameters": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. San Francisco, CA", - }, - "unit": { - "type": "string", - "enum": ["celsius", "fahrenheit"], - "description": "The unit of temperature to use", - }, - }, - "required": ["location"], - }, - }, - }, - { - "type": "function", - "function": { - "name": "get_current_time", - "description": "Get the current time in a given timezone", - "parameters": { - "type": "object", - "properties": { - "timezone": { - "type": "string", - "description": "The timezone, e.g. EST, PST", - }, - }, - "required": ["timezone"], - }, - }, - }, - ] - - with patch.object( - client.chat.completions.with_raw_response, "create" - ) as mock_client: - try: - completion( - model=model_name, - messages=[ - { - "role": "user", - "content": "What's the weather like in Boston today and what time is it in EST?", - } - ], - tools=tools, - tool_choice="auto", - parallel_tool_calls=True, - temperature=0.7, - client=client, - ) - except Exception as e: - print(e) - - # Add assertions to check the request - mock_client.assert_called_once() - request_body = mock_client.call_args.kwargs - - print("request_body: ", request_body) - - assert request_body["messages"] == [ - { - "role": "user", - "content": "What's the weather like in Boston today and what time is it in EST?", - }, - ] - assert request_body["model"] == "meta/llama3-70b-instruct" - assert request_body["temperature"] == 0.7 - assert request_body["tools"] == tools - assert request_body["tool_choice"] == "auto" - assert request_body["parallel_tool_calls"] == True @pytest.mark.asyncio() diff --git a/tests/llm_translation/test_rerank.py b/tests/llm_translation/test_rerank.py index d784677060a..bc52fd54234 100644 --- a/tests/llm_translation/test_rerank.py +++ b/tests/llm_translation/test_rerank.py @@ -1,14 +1,10 @@ import asyncio -import json import os import sys -import traceback from dotenv import load_dotenv load_dotenv() -import io -import os from typing import Optional, Dict sys.path.insert( @@ -16,15 +12,12 @@ sys.path.insert( ) # Adds the parent directory to the system path import os -from unittest.mock import AsyncMock, MagicMock, patch import pytest import litellm from litellm.types.rerank import RerankResponse -from litellm import RateLimitError, Timeout, completion, completion_cost, embedding from litellm.integrations.custom_logger import CustomLogger -from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler def assert_response_shape(response, custom_llm_provider): @@ -148,75 +141,6 @@ async def test_basic_rerank_together_ai(sync_mode): raise e -@pytest.mark.asyncio() -@pytest.mark.parametrize("version", ["v1", "v2"]) -async def test_rerank_custom_api_base(version): - mock_response = AsyncMock() - litellm.cohere_key = "test_api_key" - - def return_val(): - return { - "id": "cmpl-mockid", - "results": [{"index": 0, "relevance_score": 0.95}], - "meta": { - "api_version": {"version": "1.0"}, - "billed_units": {"search_units": 1}, - }, - } - - mock_response.json = return_val - mock_response.headers = {"key": "value"} - mock_response.status_code = 200 - - expected_payload = { - "model": "Salesforce/Llama-Rank-V1", - "query": "hello", - "top_n": 3, - "documents": ["hello", "world"], - } - - api_base = "https://exampleopenaiendpoint-production.up.railway.app/" - if version == "v1": - api_base += "v1/rerank" - - with patch( - "litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post", - return_value=mock_response, - ) as mock_post: - response = await litellm.arerank( - model="cohere/Salesforce/Llama-Rank-V1", - query="hello", - documents=["hello", "world"], - top_n=3, - api_base=api_base, - ) - - print("async re rank response: ", response) - - # Assert - mock_post.assert_called_once() - print("call args", mock_post.call_args) - args_to_api = mock_post.call_args.kwargs["data"] - _url = mock_post.call_args.kwargs["url"] - print("Arguments passed to API=", args_to_api) - print("url = ", _url) - assert ( - _url - == f"https://exampleopenaiendpoint-production.up.railway.app/{version}/rerank" - ) - - request_data = json.loads(args_to_api) - assert request_data["query"] == expected_payload["query"] - assert request_data["documents"] == expected_payload["documents"] - assert request_data["top_n"] == expected_payload["top_n"] - assert request_data["model"] == expected_payload["model"] - - assert response.id is not None - assert response.results is not None - - assert_response_shape(response, custom_llm_provider="cohere") - - class TestLogger(CustomLogger): def __init__(self): @@ -255,37 +179,6 @@ async def test_rerank_custom_callbacks(): assert custom_logger.response_obj.results is not None -def test_complete_base_url_cohere(): - from litellm.llms.custom_httpx.http_handler import HTTPHandler - - client = HTTPHandler() - litellm.api_base = "http://localhost:4000" - litellm.cohere_key = "test_api_key" - litellm.set_verbose = True - - text = "Hello there!" - list_texts = ["Hello there!", "How are you?", "How do you do?"] - - rerank_model = "rerank-multilingual-v3.0" - - with patch.object(client, "post") as mock_post: - try: - litellm.rerank( - model=rerank_model, - query=text, - documents=list_texts, - custom_llm_provider="cohere", - client=client, - ) - except Exception as e: - print(e) - - print("mock_post.call_args", mock_post.call_args) - mock_post.assert_called_once() - # Default to the v2 client when calling the base /rerank - assert "http://localhost:4000/v2/rerank" in mock_post.call_args.kwargs["url"] - - @pytest.mark.asyncio() @pytest.mark.parametrize("sync_mode", [True, False]) @pytest.mark.parametrize( @@ -370,63 +263,6 @@ def test_rerank_response_assertions(): assert_response_shape(r, custom_llm_provider="custom") -def test_cohere_rerank_v2_client(): - from litellm.llms.custom_httpx.http_handler import HTTPHandler - - client = HTTPHandler() - litellm.api_base = "http://localhost:4000" - litellm.set_verbose = True - - text = "Hello there!" - list_texts = ["Hello there!", "How are you?", "How do you do?"] - - rerank_model = "rerank-multilingual-v3.0" - - with patch.object(client, "post") as mock_post: - mock_response = MagicMock() - mock_response.text = json.dumps( - { - "id": "cmpl-mockid", - "results": [ - {"index": 0, "relevance_score": 0.95}, - {"index": 1, "relevance_score": 0.75}, - {"index": 2, "relevance_score": 0.65}, - ], - "usage": {"prompt_tokens": 100, "total_tokens": 150}, - } - ) - mock_response.status_code = 200 - mock_response.headers = {"Content-Type": "application/json"} - mock_response.json = lambda: json.loads(mock_response.text) - - mock_post.return_value = mock_response - - response = litellm.rerank( - model=rerank_model, - query=text, - documents=list_texts, - custom_llm_provider="cohere", - max_tokens_per_doc=3, - top_n=2, - api_key="fake-api-key", - client=client, - ) - - # Ensure Cohere API is called with the expected params - mock_post.assert_called_once() - assert mock_post.call_args.kwargs["url"] == "http://localhost:4000/v2/rerank" - - request_data = json.loads(mock_post.call_args.kwargs["data"]) - assert request_data["model"] == rerank_model - assert request_data["query"] == text - assert request_data["documents"] == list_texts - assert request_data["max_tokens_per_doc"] == 3 - assert request_data["top_n"] == 2 - - # Ensure litellm response is what we expect - assert response["results"] == mock_response.json()["results"] - - @pytest.mark.flaky(retries=3, delay=1) def test_rerank_cohere_api(): response = litellm.rerank( @@ -443,40 +279,3 @@ def test_rerank_cohere_api(): assert response.results[1]["document"]["text"] == "world" -def test_rerank_infer_region_from_model_arn(monkeypatch): - - mock_response = MagicMock() - - monkeypatch.setenv("AWS_REGION_NAME", "us-east-1") - args = { - "model": "bedrock/arn:aws:bedrock:us-west-2::foundation-model/amazon.rerank-v1:0", - "query": "hello", - "documents": ["hello", "world"], - } - - def return_val(): - return { - "results": [ - {"index": 0, "relevanceScore": 0.6716859340667725}, - {"index": 1, "relevanceScore": 0.0004994205664843321}, - ] - } - - mock_response.json = return_val - mock_response.headers = {"key": "value"} - mock_response.status_code = 200 - - client = HTTPHandler() - - with patch.object(client, "post", return_value=mock_response) as mock_post: - litellm.rerank( - model=args["model"], - query=args["query"], - documents=args["documents"], - client=client, - ) - - mock_post.assert_called_once() - print(f"mock_post.call_args: {mock_post.call_args.kwargs}") - assert "us-west-2" in mock_post.call_args.kwargs["url"] - assert "us-east-1" not in mock_post.call_args.kwargs["url"] diff --git a/tests/llm_translation/test_text_completion_unit_tests.py b/tests/llm_translation/test_text_completion_unit_tests.py index 04145cf6ce0..80b51c8324b 100644 --- a/tests/llm_translation/test_text_completion_unit_tests.py +++ b/tests/llm_translation/test_text_completion_unit_tests.py @@ -1,18 +1,10 @@ -import json import os import sys -from datetime import datetime -from unittest.mock import AsyncMock -import pytest -import httpx -from respx import MockRouter -from unittest.mock import patch, MagicMock, AsyncMock sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path -import litellm from litellm.types.utils import TextCompletionResponse @@ -69,151 +61,3 @@ def test_convert_dict_to_text_completion_response(): assert response.choices[0].logprobs.top_logprobs == [None, {",": -2.1568563}] -@pytest.mark.skip( - reason="need to migrate huggingface to support httpx client being passed in" -) -@pytest.mark.asyncio -@pytest.mark.respx -async def test_huggingface_text_completion_logprobs(): - """Test text completion with Hugging Face, focusing on logprobs structure""" - litellm.set_verbose = True - litellm.disable_aiohttp_transport = ( - True # since this uses respx, we need to set use_aiohttp_transport to False - ) - from litellm.llms.custom_httpx.http_handler import HTTPHandler, AsyncHTTPHandler - - mock_response = [ - { - "generated_text": ",\n\nI have a question...", # truncated for brevity - "details": { - "finish_reason": "length", - "generated_tokens": 100, - "seed": None, - "prefill": [], - "tokens": [ - {"id": 28725, "text": ",", "logprob": -1.7626953, "special": False}, - {"id": 13, "text": "\n", "logprob": -1.7314453, "special": False}, - ], - }, - } - ] - - return_val = AsyncMock() - - return_val.json.return_value = mock_response - - client = AsyncHTTPHandler() - with patch.object(client, "post", return_value=return_val) as mock_post: - response = await litellm.atext_completion( - model="huggingface/mistralai/Mistral-7B-Instruct-v0.3", - prompt="good morning", - client=client, - ) - - # Verify the request - mock_post.assert_called_once() - request_body = json.loads(mock_post.call_args.kwargs["data"]) - assert request_body == { - "inputs": "good morning", - "parameters": {"details": True, "return_full_text": False}, - "stream": False, - } - - print("response=", response) - - # Verify response structure - assert isinstance(response, TextCompletionResponse) - assert response.object == "text_completion" - assert response.model == "mistralai/Mistral-7B-v0.1" - - # Verify logprobs structure - choice = response.choices[0] - assert choice.finish_reason == "length" - assert choice.index == 0 - assert isinstance(choice.logprobs.tokens, list) - assert isinstance(choice.logprobs.token_logprobs, list) - assert isinstance(choice.logprobs.text_offset, list) - assert isinstance(choice.logprobs.top_logprobs, list) - assert choice.logprobs.tokens == [",", "\n"] - assert choice.logprobs.token_logprobs == [-1.7626953, -1.7314453] - assert choice.logprobs.text_offset == [0, 1] - assert choice.logprobs.top_logprobs == [{}, {}] - - # Verify usage - assert response.usage["completion_tokens"] > 0 - assert response.usage["prompt_tokens"] > 0 - assert response.usage["total_tokens"] > 0 - - -@pytest.mark.asyncio -async def test_acompletion_uses_optimized_http_client(): - """ - Test that OpenAITextCompletion.acompletion uses BaseOpenAILLM._get_async_http_client() - instead of litellm.aclient_session directly. - - Related issue: https://github.com/BerriAI/litellm/issues/17676 - """ - from litellm.llms.openai.completion.handler import OpenAITextCompletion - from litellm.llms.openai.common_utils import BaseOpenAILLM - - mock_http_client = MagicMock() - mock_async_openai = AsyncMock() - mock_async_openai.completions.with_raw_response.create = AsyncMock( - return_value=MagicMock( - parse=MagicMock( - return_value=MagicMock( - model_dump=MagicMock( - return_value={ - "id": "test-id", - "object": "text_completion", - "created": 1234567890, - "model": "gpt-3.5-turbo-instruct", - "choices": [ - { - "text": "test response", - "index": 0, - "finish_reason": "stop", - } - ], - "usage": { - "prompt_tokens": 5, - "completion_tokens": 10, - "total_tokens": 15, - }, - } - ) - ) - ) - ) - ) - - with patch.object( - BaseOpenAILLM, "_get_async_http_client", return_value=mock_http_client - ) as mock_get_client: - with patch( - "litellm.llms.openai.completion.handler.AsyncOpenAI", - return_value=mock_async_openai, - ) as mock_openai_class: - handler = OpenAITextCompletion() - logging_obj = MagicMock() - logging_obj.post_call = MagicMock() - - await handler.acompletion( - logging_obj=logging_obj, - api_base="https://api.openai.com/v1", - data={"prompt": "test", "model": "gpt-3.5-turbo-instruct"}, - headers={}, - model_response=MagicMock(), - api_key="test-key", - model="gpt-3.5-turbo-instruct", - timeout=30.0, - max_retries=2, - ) - - # Verify _get_async_http_client was called - mock_get_client.assert_called_once() - - # Verify AsyncOpenAI was initialized with the http_client from _get_async_http_client - mock_openai_class.assert_called_once() - call_kwargs = mock_openai_class.call_args.kwargs - assert call_kwargs["http_client"] == mock_http_client diff --git a/tests/llm_translation/test_together_ai.py b/tests/llm_translation/test_together_ai.py index 4ad0c90230d..fcf38a2b7ec 100644 --- a/tests/llm_translation/test_together_ai.py +++ b/tests/llm_translation/test_together_ai.py @@ -3,11 +3,8 @@ Test TogetherAI LLM """ from base_llm_unit_tests import BaseLLMChatTest -import json import os import sys -from datetime import datetime -from unittest.mock import AsyncMock sys.path.insert( 0, os.path.abspath("../..") @@ -22,10 +19,6 @@ class TestTogetherAI(BaseLLMChatTest): litellm.set_verbose = True return {"model": "together_ai/Qwen/Qwen2.5-7B-Instruct-Turbo"} - def test_tool_call_no_arguments(self, tool_call_no_arguments): - """Test that tool calls with no arguments is translated correctly. Relevant issue: https://github.com/BerriAI/litellm/issues/6833""" - pass - @pytest.mark.parametrize( "model, expected_bool", [ diff --git a/tests/llm_translation/test_triton.py b/tests/llm_translation/test_triton.py index 2d1ca39e1dc..a9964a21912 100644 --- a/tests/llm_translation/test_triton.py +++ b/tests/llm_translation/test_triton.py @@ -6,8 +6,7 @@ import traceback from dotenv import load_dotenv load_dotenv() -import io -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock, patch sys.path.insert( 0, os.path.abspath("../..") @@ -15,9 +14,7 @@ sys.path.insert( import pytest import litellm -import pytest from litellm.llms.triton.embedding.transformation import TritonEmbeddingConfig -import litellm def test_split_embedding_by_shape_passes(): @@ -354,23 +351,6 @@ def test_completion_triton_infer_api(): pytest.fail(f"Error occurred: {e}") -@pytest.mark.asyncio -async def test_triton_embeddings(): - try: - litellm.set_verbose = True - response = await litellm.aembedding( - model="triton/my-triton-model", - api_base="https://exampleopenaiendpoint-production.up.railway.app/triton/embeddings", - input=["good morning from litellm"], - ) - print(f"response: {response}") - - # stubbed endpoint is setup to return this - assert response.data[0]["embedding"] == [0.1, 0.2] - except Exception as e: - pytest.fail(f"Error occurred: {e}") - - def test_triton_generate_raw_request(): from litellm.utils import return_raw_request from litellm.types.utils import CallTypes diff --git a/tests/llm_translation/test_voyage_ai.py b/tests/llm_translation/test_voyage_ai.py index 30f2844fbfa..33f845d76e1 100644 --- a/tests/llm_translation/test_voyage_ai.py +++ b/tests/llm_translation/test_voyage_ai.py @@ -2,14 +2,13 @@ import json import os import sys -import pytest sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from base_embedding_unit_tests import BaseLLMEmbeddingTest @@ -25,110 +24,6 @@ class TestVoyageAI(BaseLLMEmbeddingTest): "model": "voyage/voyage-3-lite", } - @pytest.mark.asyncio() - @pytest.mark.parametrize("sync_mode", [True, False]) - async def test_basic_embedding(self, sync_mode): - """Override base test to handle Voyage embeddings properly""" - litellm.set_verbose = True - embedding_call_args = self.get_base_embedding_call_args() - - # Mock the embedding function to avoid API calls - with ( - patch("litellm.embedding") as mock_embedding, - patch("litellm.aembedding") as mock_aembedding, - ): - # Create a mock response that matches Voyage format - mock_response = MagicMock() - mock_response.model = "voyage-3-lite" - mock_response.object = "list" - mock_response.data = [ - {"object": "embedding", "embedding": [0.1, 0.2, 0.3], "index": 0} - ] - mock_response.usage.prompt_tokens = 24 - mock_response.usage.total_tokens = 24 - - mock_embedding.return_value = mock_response - mock_aembedding.return_value = mock_response - - if sync_mode is True: - response = litellm.embedding( - **embedding_call_args, - input=["hello", "world"], - ) - # Verify the response structure - assert response.model == "voyage-3-lite" - assert response.object == "list" - assert len(response.data) > 0 - assert response.usage.total_tokens > 0 - else: - response = await litellm.aembedding( - **embedding_call_args, - input=["hello", "world"], - ) - # Verify the response structure - assert response.model == "voyage-3-lite" - assert response.object == "list" - assert len(response.data) > 0 - assert response.usage.total_tokens > 0 - - -def test_voyage_ai_embedding_extra_params(): - """Test Voyage AI embedding with extra parameters""" - try: - # Mock the entire embedding function to avoid API calls - with patch("litellm.embedding") as mock_embedding: - # Create a mock response - mock_response = MagicMock() - mock_response.usage.prompt_tokens = 24 - mock_response.usage.total_tokens = 24 - mock_response.model = "voyage-3-lite" - mock_embedding.return_value = mock_response - - litellm.embedding( - model="voyage/voyage-3-lite", - input=["a"], - dimensions=512, - input_type="document", - ) - - # Verify the function was called with correct parameters - mock_embedding.assert_called_once() - call_args = mock_embedding.call_args - assert call_args[1]["model"] == "voyage/voyage-3-lite" - assert call_args[1]["input"] == ["a"] - assert call_args[1]["dimensions"] == 512 - assert call_args[1]["input_type"] == "document" - - except Exception as e: - pytest.fail(f"Error occurred: {e}") - - -def test_voyage_ai_embedding_prompt_token_mapping(): - """Test Voyage AI embedding token mapping""" - try: - # Mock the entire embedding function - with patch("litellm.embedding") as mock_embedding: - # Create a mock response with usage - mock_response = MagicMock() - mock_response.usage.prompt_tokens = 120 - mock_response.usage.total_tokens = 120 - mock_embedding.return_value = mock_response - - response = litellm.embedding( - model="voyage/voyage-3-lite", - input=["a"], - dimensions=512, - input_type="document", - ) - - # Verify the response - assert response.usage.prompt_tokens == 120 - assert response.usage.total_tokens == 120 - - except Exception as e: - pytest.fail(f"Error occurred: {e}") - - # Tests for Voyage Contextual Embeddings class TestVoyageContextualEmbeddings: """Test suite for Voyage contextual embeddings functionality""" @@ -334,101 +229,3 @@ class TestVoyageContextualEmbeddings: assert regular_transformed["input"] == ["Hello"] assert contextual_transformed["inputs"] == [["Hello"]] - def test_contextual_embedding_integration(self): - """Test full integration of contextual embeddings""" - try: - # Mock the entire embedding function to avoid API calls - with patch("litellm.embedding") as mock_embedding: - # Create a mock response that matches the expected structure - mock_response = MagicMock() - mock_response.model = "voyage-context-3" - mock_response.usage.total_tokens = 24 - mock_response.data = [ - { - "object": "list", - "data": [ - { - "object": "embedding", - "embedding": [0.1, 0.2, 0.3], - "index": 0, - } - ], - "index": 0, - } - ] - mock_embedding.return_value = mock_response - - response = litellm.embedding( - model="voyage/voyage-context-3", - input=[["Hello", "world"]], - input_type="document", - ) - - # Verify the function was called with correct parameters - mock_embedding.assert_called_once() - call_args = mock_embedding.call_args - assert call_args[1]["model"] == "voyage/voyage-context-3" - assert call_args[1]["input"] == [["Hello", "world"]] - assert call_args[1]["input_type"] == "document" - - # Assert the response structure - assert response.model == "voyage-context-3" - assert response.usage.total_tokens == 24 - - except Exception as e: - pytest.fail(f"Error occurred: {e}") - - def test_contextual_embedding_multiple_inputs(self): - """Test contextual embeddings with multiple input groups""" - try: - # Mock the entire embedding function - with patch("litellm.embedding") as mock_embedding: - # Create a mock response for multiple input groups - mock_response = MagicMock() - mock_response.model = "voyage-context-3" - mock_response.usage.total_tokens = 48 - mock_response.data = [ - { - "object": "list", - "data": [ - { - "object": "embedding", - "embedding": [0.1, 0.2], - "index": 0, - }, - { - "object": "embedding", - "embedding": [0.3, 0.4], - "index": 1, - }, - ], - "index": 0, - }, - { - "object": "list", - "data": [ - {"object": "embedding", "embedding": [0.5, 0.6], "index": 0} - ], - "index": 1, - }, - ] - mock_embedding.return_value = mock_response - - response = litellm.embedding( - model="voyage/voyage-context-3", - input=[["Hello", "world"], ["Test"]], - ) - - # Verify the function was called with correct parameters - mock_embedding.assert_called_once() - call_args = mock_embedding.call_args - assert call_args[1]["model"] == "voyage/voyage-context-3" - assert call_args[1]["input"] == [["Hello", "world"], ["Test"]] - - # Assert response structure - assert len(response.data) == 2 - assert response.data[0]["index"] == 0 - assert response.data[1]["index"] == 1 - - except Exception as e: - pytest.fail(f"Error occurred: {e}") diff --git a/tests/llm_translation/test_watsonx.py b/tests/llm_translation/test_watsonx.py index 5857394d0ff..668ab88aefb 100644 --- a/tests/llm_translation/test_watsonx.py +++ b/tests/llm_translation/test_watsonx.py @@ -146,62 +146,6 @@ def watsonx_embedding_call(): return _call -@pytest.mark.parametrize("with_custom_auth_header", [True, False]) -def test_watsonx_custom_auth_header( - with_custom_auth_header, watsonx_chat_completion_call -): - headers = ( - {"Authorization": "Bearer my-custom-auth-header"} - if with_custom_auth_header - else {} - ) - - mock_post, _ = watsonx_chat_completion_call(headers=headers) - - assert mock_post.call_count == 1 - if with_custom_auth_header: - assert ( - mock_post.call_args[1]["headers"]["Authorization"] - == "Bearer my-custom-auth-header" - ) - else: - assert ( - mock_post.call_args[1]["headers"]["Authorization"] - == "Bearer mock_access_token" - ) - - -@pytest.mark.parametrize("env_var_key", ["WATSONX_ZENAPIKEY", "WATSONX_TOKEN"]) -def test_watsonx_token_in_env_var( - monkeypatch, watsonx_chat_completion_call, env_var_key -): - monkeypatch.setenv(env_var_key, "my-custom-token") - - mock_post, _ = watsonx_chat_completion_call(patch_token_call=False) - - assert mock_post.call_count == 1 - if env_var_key == "WATSONX_ZENAPIKEY": - assert ( - mock_post.call_args[1]["headers"]["Authorization"] - == "ZenApiKey my-custom-token" - ) - else: - assert ( - mock_post.call_args[1]["headers"]["Authorization"] - == "Bearer my-custom-token" - ) - - -def test_watsonx_chat_completions_endpoint(watsonx_chat_completion_call): - model = "watsonx/another-model" - messages = [{"role": "user", "content": "Test message"}] - - mock_post, _ = watsonx_chat_completion_call(model=model, messages=messages) - - assert mock_post.call_count == 1 - assert "deployment" not in mock_post.call_args.kwargs["url"] - - def test_watsonx_chat_completions_endpoint_space_id( monkeypatch, watsonx_chat_completion_call ): diff --git a/tests/llm_translation/test_xai.py b/tests/llm_translation/test_xai.py index f0945e6e165..acda24dfd43 100644 --- a/tests/llm_translation/test_xai.py +++ b/tests/llm_translation/test_xai.py @@ -1,19 +1,14 @@ -import json import os import sys -from datetime import datetime -from unittest.mock import AsyncMock sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path -import httpx import pytest import litellm -from litellm import Choices, Message, ModelResponse, EmbeddingResponse, Usage from litellm import completion from unittest.mock import patch from litellm.llms.xai.chat.transformation import XAIChatConfig, XAI_API_BASE @@ -179,10 +174,6 @@ class TestXAIChat(BaseLLMChatTest): "model": "xai/grok-3-mini-beta", } - def test_tool_call_no_arguments(self, tool_call_no_arguments): - """Test that tool calls with no arguments is translated correctly. Relevant issue: https://github.com/BerriAI/litellm/issues/6833""" - pass - def test_web_search(self): """Web search is only supported for Grok 4 family models""" from litellm.utils import supports_web_search