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.
This commit is contained in:
mateo-berri 2026-06-11 18:56:50 +00:00
parent 73f396b96a
commit 1eafdbfba9
15 changed files with 6 additions and 1384 deletions

View file

@ -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():

View file

@ -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"

View file

@ -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):

View file

@ -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()

View file

@ -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 (

View file

@ -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

View file

@ -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"""

View file

@ -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()

View file

@ -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"]

View file

@ -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

View file

@ -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",
[

View file

@ -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

View file

@ -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}")

View file

@ -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
):

View file

@ -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