main
py 133 lines 4.11 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Integration tests for Whisper models with LoRA adapters.
4
5 These tests verify that Whisper models can correctly load and use LoRA adapters
6 for speech-to-text transcription tasks.
7 """
8
9 import pytest
10
11 import vllm
12 from vllm.assets.audio import AudioAsset
13 from vllm.lora.request import LoRARequest
14 from vllm.platforms import current_platform
15
16 from ..utils import create_new_process_for_each_test
17
18 # Model configuration
19 WHISPER_MODEL = "openai/whisper-small"
20
21 # Test prompts for Whisper transcription
22 WHISPER_PROMPT = "<|startoftranscript|><|en|><|transcribe|><|notimestamps|>"
23
24 # Note: whisper_lora_files fixture is defined in conftest.py
25
26
27 @pytest.fixture(autouse=True)
28 def use_spawn_for_whisper(monkeypatch):
29 """Whisper has issues with forked workers, use spawn instead."""
30 monkeypatch.setenv("VLLM_WORKER_MULTIPROC_METHOD", "spawn")
31
32
33 def create_whisper_llm(
34 enable_lora: bool = True, max_loras: int = 2, attn_backend: str | None = None
35 ):
36 """Create a Whisper LLM instance with optional LoRA support."""
37 return vllm.LLM(
38 model=WHISPER_MODEL,
39 enable_lora=enable_lora,
40 max_loras=max_loras if enable_lora else 1,
41 max_lora_rank=64,
42 max_model_len=448,
43 dtype="half",
44 enforce_eager=True, # For stability in tests
45 attention_config={"backend": attn_backend},
46 )
47
48
49 def run_whisper_inference(
50 llm: vllm.LLM,
51 lora_path: str | None = None,
52 lora_id: int = 1,
53 ) -> list[str]:
54 """Run Whisper inference with optional LoRA adapter."""
55 # Load test audio
56 audio_asset = AudioAsset("mary_had_lamb")
57 audio_data = audio_asset.audio_and_sample_rate
58
59 inputs = [
60 {
61 "prompt": WHISPER_PROMPT,
62 "multi_modal_data": {"audio": audio_data},
63 }
64 ]
65
66 sampling_params = vllm.SamplingParams(
67 temperature=0,
68 max_tokens=200,
69 )
70
71 # Prepare LoRA request if adapter path is provided
72 lora_request = None
73 if lora_path:
74 lora_request = LoRARequest(
75 lora_name=f"whisper_lora_{lora_id}",
76 lora_int_id=lora_id,
77 lora_path=lora_path,
78 )
79
80 outputs = llm.generate(inputs, sampling_params, lora_request=lora_request)
81
82 return [output.outputs[0].text for output in outputs]
83
84
85 @create_new_process_for_each_test()
86 def test_whisper_lora_inference(whisper_lora_files):
87 """Test basic Whisper inference with a LoRA adapter.
88
89 This test verifies that:
90 1. Whisper model can be loaded with LoRA support enabled
91 2. A LoRA adapter can be applied during inference
92 3. The model produces valid transcription output
93 """
94 llm = create_whisper_llm(enable_lora=True)
95
96 # Run inference with LoRA
97 outputs = run_whisper_inference(llm, lora_path=whisper_lora_files, lora_id=1)
98
99 # Verify we got a non-empty transcription
100 assert len(outputs) == 1
101 assert len(outputs[0]) > 0, "Expected non-empty transcription output"
102
103 # The output should contain some recognizable words from the audio
104 # (Mary had a little lamb)
105 print(f"Transcription output: {outputs[0]}")
106
107
108 @create_new_process_for_each_test()
109 def test_whisper_multi_lora(whisper_lora_files):
110 """Test Whisper with multiple LoRA adapter IDs.
111
112 This test verifies that the same LoRA adapter can be loaded with
113 different IDs and produce consistent results.
114 """
115 llm = create_whisper_llm(
116 enable_lora=True,
117 max_loras=4,
118 attn_backend="TRITON_ATTN" if current_platform.is_rocm() else None,
119 )
120
121 # Test with different LoRA IDs using the same adapter
122 outputs_lora1 = run_whisper_inference(llm, lora_path=whisper_lora_files, lora_id=1)
123 outputs_lora2 = run_whisper_inference(llm, lora_path=whisper_lora_files, lora_id=2)
124
125 # Both should produce valid outputs
126 assert len(outputs_lora1[0]) > 0
127 assert len(outputs_lora2[0]) > 0
128
129 # Same adapter with different IDs should produce same output
130 assert outputs_lora1 == outputs_lora2, (
131 f"Expected same outputs for same adapter with different IDs. "
132 f"Got: {outputs_lora1} vs {outputs_lora2}"
133 )