mirror of
https://github.com/tiennm99/litellm.git
synced 2026-06-18 03:31:23 +00:00
271 lines
8.7 KiB
Python
271 lines
8.7 KiB
Python
# What is this?
|
|
## Tests `litellm.transcription` endpoint. Outside litellm module b/c of audio file used in testing (it's ~700kb).
|
|
|
|
import asyncio
|
|
import logging
|
|
import os
|
|
import sys
|
|
import time
|
|
import traceback
|
|
from typing import Optional
|
|
|
|
import aiohttp
|
|
import dotenv
|
|
import pytest
|
|
from dotenv import load_dotenv
|
|
from openai import AsyncOpenAI
|
|
|
|
import litellm
|
|
from litellm.integrations.custom_logger import CustomLogger
|
|
|
|
# Get the current directory of the file being run
|
|
pwd = os.path.dirname(os.path.realpath(__file__))
|
|
print(pwd)
|
|
|
|
file_path = os.path.join(pwd, "gettysburg.wav")
|
|
|
|
audio_file = open(file_path, "rb")
|
|
|
|
|
|
file2_path = os.path.join(pwd, "eagle.wav")
|
|
audio_file2 = open(file2_path, "rb")
|
|
|
|
load_dotenv()
|
|
|
|
sys.path.insert(
|
|
0, os.path.abspath("../")
|
|
) # Adds the parent directory to the system path
|
|
import litellm
|
|
from litellm import Router
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"model, api_key, api_base",
|
|
[
|
|
("whisper-1", None, None),
|
|
(
|
|
"azure/whisper",
|
|
os.getenv("AZURE_WHISPER_API_KEY"),
|
|
os.getenv("AZURE_WHISPER_API_BASE"),
|
|
),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"response_format, timestamp_granularities",
|
|
[("json", None), ("vtt", None), ("verbose_json", ["word"])],
|
|
)
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.flaky(retries=3, delay=1)
|
|
async def test_transcription(
|
|
model, api_key, api_base, response_format, timestamp_granularities
|
|
):
|
|
transcript = await litellm.atranscription(
|
|
model=model,
|
|
file=audio_file,
|
|
api_key=api_key,
|
|
api_base=api_base,
|
|
response_format=response_format,
|
|
timestamp_granularities=timestamp_granularities,
|
|
drop_params=True,
|
|
)
|
|
print(f"transcript: {transcript.model_dump()}")
|
|
print(f"transcript hidden params: {transcript._hidden_params}")
|
|
|
|
assert transcript.text is not None
|
|
|
|
|
|
@pytest.mark.asyncio()
|
|
async def test_transcription_caching():
|
|
import litellm
|
|
from litellm.caching.caching import Cache
|
|
|
|
litellm.set_verbose = True
|
|
litellm.cache = Cache()
|
|
|
|
# make raw llm api call
|
|
|
|
response_1 = await litellm.atranscription(
|
|
model="whisper-1",
|
|
file=audio_file,
|
|
)
|
|
|
|
await asyncio.sleep(5)
|
|
|
|
# cache hit
|
|
|
|
response_2 = await litellm.atranscription(
|
|
model="whisper-1",
|
|
file=audio_file,
|
|
)
|
|
|
|
print("response_1", response_1)
|
|
print("response_2", response_2)
|
|
print("response2 hidden params", response_2._hidden_params)
|
|
assert response_2._hidden_params["cache_hit"] is True
|
|
|
|
# cache miss
|
|
|
|
response_3 = await litellm.atranscription(
|
|
model="whisper-1",
|
|
file=audio_file2,
|
|
)
|
|
print("response_3", response_3)
|
|
print("response3 hidden params", response_3._hidden_params)
|
|
assert response_3._hidden_params.get("cache_hit") is not True
|
|
assert response_3.text != response_2.text
|
|
|
|
litellm.cache = None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_whisper_log_pre_call():
|
|
from litellm.litellm_core_utils.litellm_logging import Logging
|
|
from datetime import datetime
|
|
from unittest.mock import patch, MagicMock
|
|
from litellm.integrations.custom_logger import CustomLogger
|
|
|
|
custom_logger = CustomLogger()
|
|
|
|
litellm.callbacks = [custom_logger]
|
|
|
|
with patch.object(custom_logger, "log_pre_api_call") as mock_log_pre_call:
|
|
await litellm.atranscription(
|
|
model="whisper-1",
|
|
file=audio_file,
|
|
)
|
|
mock_log_pre_call.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_whisper_log_pre_call():
|
|
from litellm.litellm_core_utils.litellm_logging import Logging
|
|
from datetime import datetime
|
|
from unittest.mock import patch, MagicMock
|
|
from litellm.integrations.custom_logger import CustomLogger
|
|
|
|
custom_logger = CustomLogger()
|
|
|
|
litellm.callbacks = [custom_logger]
|
|
|
|
with patch.object(custom_logger, "log_pre_api_call") as mock_log_pre_call:
|
|
await litellm.atranscription(
|
|
model="whisper-1",
|
|
file=audio_file,
|
|
)
|
|
mock_log_pre_call.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_gpt_4o_transcribe():
|
|
from litellm.litellm_core_utils.litellm_logging import Logging
|
|
from datetime import datetime
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
await litellm.atranscription(
|
|
model="openai/gpt-4o-transcribe", file=audio_file, response_format="json"
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_gpt_4o_transcribe_model_mapping():
|
|
"""Test that GPT-4o transcription models are correctly mapped and not hardcoded to whisper-1"""
|
|
|
|
# Test GPT-4o mini transcribe
|
|
response = await litellm.atranscription(
|
|
model="openai/gpt-4o-mini-transcribe",
|
|
file=audio_file,
|
|
response_format="json"
|
|
)
|
|
|
|
# Check that the response contains the correct model in hidden params
|
|
assert response._hidden_params is not None
|
|
assert response._hidden_params["model"] == "gpt-4o-mini-transcribe"
|
|
assert response._hidden_params["custom_llm_provider"] == "openai"
|
|
assert response.text is not None
|
|
|
|
# Test GPT-4o transcribe
|
|
response2 = await litellm.atranscription(
|
|
model="openai/gpt-4o-transcribe",
|
|
file=audio_file,
|
|
response_format="json"
|
|
)
|
|
|
|
# Check that the response contains the correct model in hidden params
|
|
assert response2._hidden_params is not None
|
|
assert response2._hidden_params["model"] == "gpt-4o-transcribe"
|
|
assert response2._hidden_params["custom_llm_provider"] == "openai"
|
|
assert response2.text is not None
|
|
|
|
# Test traditional whisper-1 still works
|
|
response3 = await litellm.atranscription(
|
|
model="openai/whisper-1",
|
|
file=audio_file,
|
|
response_format="json"
|
|
)
|
|
|
|
# Check that the response contains the correct model in hidden params
|
|
assert response3._hidden_params is not None
|
|
assert response3._hidden_params["model"] == "whisper-1"
|
|
assert response3._hidden_params["custom_llm_provider"] == "openai"
|
|
assert response3.text is not None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_azure_transcribe_model_mapping():
|
|
"""
|
|
Test that Azure transcription models are correctly mapped and not hardcoded to whisper-1.
|
|
This test validates that the request body contains the correct model parameter.
|
|
"""
|
|
from unittest.mock import AsyncMock, patch, MagicMock
|
|
from openai import AsyncAzureOpenAI
|
|
|
|
# Create a mock response that looks like OpenAI's transcription response (as a BaseModel)
|
|
from pydantic import BaseModel as PydanticBaseModel
|
|
|
|
class MockTranscriptionResponse(PydanticBaseModel):
|
|
text: str
|
|
|
|
mock_transcription_response = MockTranscriptionResponse(text="This is a test transcription")
|
|
|
|
# Create mock raw response with headers and parse() method
|
|
mock_raw_response = MagicMock()
|
|
mock_raw_response.headers = {"content-type": "application/json"}
|
|
mock_raw_response.parse = MagicMock(return_value=mock_transcription_response)
|
|
|
|
# Create a mock Azure client instance
|
|
mock_azure_client = MagicMock(spec=AsyncAzureOpenAI)
|
|
mock_azure_client.audio.transcriptions.with_raw_response.create = AsyncMock(return_value=mock_raw_response)
|
|
mock_azure_client.api_key = "test-api-key"
|
|
mock_azure_client._base_url = MagicMock()
|
|
mock_azure_client._base_url._uri_reference = "https://my-endpoint-europe-berri-992.openai.azure.com/"
|
|
|
|
# Mock the get_azure_openai_client method to return our mock client
|
|
with patch("litellm.llms.azure.audio_transcriptions.AzureAudioTranscription.get_azure_openai_client", return_value=mock_azure_client):
|
|
# Make the transcription call
|
|
response = await litellm.atranscription(
|
|
model="azure/whisper-1",
|
|
file=audio_file,
|
|
response_format="json",
|
|
api_key="test-api-key",
|
|
api_base="https://my-endpoint-europe-berri-992.openai.azure.com/",
|
|
api_version="2024-02-15-preview",
|
|
drop_params=True
|
|
)
|
|
|
|
# Verify the create method was called
|
|
mock_azure_client.audio.transcriptions.with_raw_response.create.assert_called_once()
|
|
|
|
# Get the call arguments to validate the model parameter
|
|
call_kwargs = mock_azure_client.audio.transcriptions.with_raw_response.create.call_args.kwargs
|
|
|
|
# Assert that the model parameter is "whisper-1" (not hardcoded incorrectly)
|
|
assert call_kwargs["model"] == "whisper-1", f"Expected model 'whisper-1', got {call_kwargs['model']}"
|
|
assert "file" in call_kwargs
|
|
assert call_kwargs["response_format"] == "json"
|
|
|
|
# Check that the response contains the correct model in hidden params
|
|
assert response._hidden_params is not None
|
|
assert response._hidden_params["model"] == "whisper-1"
|
|
assert response._hidden_params["custom_llm_provider"] == "azure"
|
|
assert response.text is not None
|