From 82d9f2788790fcf2062da538fb7db391e5eba7b6 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Sat, 13 Jun 2026 11:52:30 -0700 Subject: [PATCH] test(fireworks): mock whisper transcription tests instead of live calls (#30391) TestFireworksAIAudioTranscription inherited two tests from BaseLLMAudioTranscriptionTest that made real calls to audio-prod.api.fireworks.ai. The audio host is a separately-entitled product, and the CI key gets a 401 there, so both tests fail without signalling anything about litellm. Override them in the subclass with a dependency-injected mock OpenAI client (the openai-compatible path uses the openai SDK, which is why the failure surfaced as openai.AuthenticationError). The real routing, model-prefix stripping, and response parsing still run; only the network call is mocked. The sync path mocks audio.transcriptions.create and the async path mocks audio.transcriptions.with_raw_response.create. This matches the existing direction in this file, where the document-inlining and global-disable tests were already converted off live Fireworks calls. --- .../test_fireworks_ai_translation.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/llm_translation/test_fireworks_ai_translation.py b/tests/llm_translation/test_fireworks_ai_translation.py index c4f15ac4c3e..4e5bef16b8c 100644 --- a/tests/llm_translation/test_fireworks_ai_translation.py +++ b/tests/llm_translation/test_fireworks_ai_translation.py @@ -70,6 +70,11 @@ def test_map_response_format(): assert result == {"response_format": response_format} +_AUDIO_FILE_PATH = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "gettysburg.wav" +) + + class TestFireworksAIAudioTranscription(BaseLLMAudioTranscriptionTest): def get_base_audio_transcription_call_args(self) -> dict: return { @@ -80,6 +85,60 @@ class TestFireworksAIAudioTranscription(BaseLLMAudioTranscriptionTest): def get_custom_llm_provider(self) -> litellm.LlmProviders: return litellm.LlmProviders.FIREWORKS_AI + def test_audio_transcription(self): + from unittest.mock import MagicMock + + from openai.types.audio import Transcription + + audio_file = open(_AUDIO_FILE_PATH, "rb") + mock_client = MagicMock() + mock_client.audio.transcriptions.create.return_value = Transcription( + text="four score and seven years ago" + ) + + transcript = transcription( + **self.get_base_audio_transcription_call_args(), + file=audio_file, + api_key="fw-test-key", + client=mock_client, + ) + + assert transcript.text == "four score and seven years ago" + sent = mock_client.audio.transcriptions.create.call_args.kwargs + assert sent["model"] == "whisper-v3" + assert sent["file"] is audio_file + + @pytest.mark.asyncio + async def test_audio_transcription_async(self): + from unittest.mock import AsyncMock, MagicMock + + from openai.types.audio import Transcription + + audio_file = open(_AUDIO_FILE_PATH, "rb") + raw_response = MagicMock() + raw_response.headers = {} + raw_response.parse.return_value = Transcription( + text="four score and seven years ago" + ) + mock_client = MagicMock() + mock_client.audio.transcriptions.with_raw_response.create = AsyncMock( + return_value=raw_response + ) + + transcript = await litellm.atranscription( + **self.get_base_audio_transcription_call_args(), + file=audio_file, + api_key="fw-test-key", + client=mock_client, + ) + + assert transcript.text == "four score and seven years ago" + sent = ( + mock_client.audio.transcriptions.with_raw_response.create.call_args.kwargs + ) + assert sent["model"] == "whisper-v3" + assert sent["file"] is audio_file + @pytest.mark.parametrize( "disable_add_transform_inline_image_block",