main
py 164 lines 4.6 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Adapted from
5 # https://github.com/fmmoret/vllm/blob/fm-support-lora-on-quantized-models/tests/lora/test_llama.py
6 from dataclasses import dataclass
7
8 import pytest
9
10 import vllm
11 from vllm.distributed import cleanup_dist_env_and_memory
12 from vllm.lora.request import LoRARequest
13 from vllm.platforms import current_platform
14
15
16 @dataclass
17 class ModelWithQuantization:
18 model_path: str
19 quantization: str
20
21
22 MODELS: list[ModelWithQuantization]
23 # AWQ quantization is currently not supported in ROCm.
24 if current_platform.is_rocm():
25 MODELS = [
26 ModelWithQuantization(
27 model_path="JunHowie/Qwen3-0.6B-GPTQ-Int4",
28 quantization="gptq",
29 ),
30 ]
31 else:
32 MODELS = [
33 ModelWithQuantization(
34 model_path="Orion-zhen/Qwen3-0.6B-AWQ", quantization="awq"
35 ),
36 ModelWithQuantization(
37 model_path="JunHowie/Qwen3-0.6B-GPTQ-Int4",
38 quantization="gptq",
39 ),
40 ]
41
42
43 def do_sample(
44 llm: vllm.LLM, lora_path: str | None, lora_id: int, max_tokens: int = 256
45 ) -> list[str]:
46 messages = [
47 [
48 {
49 "role": "system",
50 "content": "Follow the instructions to make animal noises",
51 },
52 {"role": "user", "content": "Make your favorite animal noise."},
53 ],
54 [
55 {
56 "role": "system",
57 "content": "You are a cat. Reply only with your sound.",
58 },
59 {"role": "user", "content": "What do you say?"},
60 ],
61 ]
62 sampling_params = vllm.SamplingParams(temperature=0, max_tokens=max_tokens)
63 outputs = llm.chat(
64 messages,
65 sampling_params,
66 chat_template_kwargs={"enable_thinking": False},
67 lora_request=(
68 LoRARequest(str(lora_id), lora_id, lora_path) if lora_path else None
69 ),
70 use_tqdm=False,
71 )
72 generated_texts: list[str] = []
73 for output in outputs:
74 prompt = output.prompt
75 generated_text = output.outputs[0].text
76 generated_texts.append(generated_text)
77 print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")
78 return generated_texts
79
80
81 @pytest.mark.parametrize("model", MODELS)
82 def test_quant_model_lora(qwen3_meowing_lora_files, qwen3_woofing_lora_files, model):
83 llm = vllm.LLM(
84 model=model.model_path,
85 enable_lora=True,
86 max_num_seqs=16,
87 max_loras=4,
88 max_model_len=400,
89 gpu_memory_utilization=0.2, # avoid OOM
90 quantization=model.quantization,
91 enable_chunked_prefill=True,
92 )
93
94 loras = [
95 (
96 qwen3_meowing_lora_files,
97 1,
98 ["Meow Meow Meow Meow Meow"] * 2,
99 ),
100 (
101 qwen3_woofing_lora_files,
102 2,
103 ["Woof Woof Woof Woof Woof"] * 2,
104 ),
105 ]
106 max_tokens = 10
107 try:
108 base_output = do_sample(llm, None, lora_id=0, max_tokens=max_tokens)
109 for lora_path, lora_id, expected_output in loras:
110 output = do_sample(
111 llm,
112 lora_path,
113 lora_id=lora_id,
114 max_tokens=max_tokens,
115 )
116 assert output == expected_output
117 assert output != base_output
118 finally:
119 del llm
120 cleanup_dist_env_and_memory()
121
122
123 @pytest.mark.parametrize("model", MODELS)
124 def test_quant_model_tp_equality(qwen3_meowing_lora_files, num_gpus_available, model):
125 if num_gpus_available < 2:
126 pytest.skip(f"Not enough GPUs for tensor parallelism {2}")
127 llm_tp1 = vllm.LLM(
128 model=model.model_path,
129 enable_lora=True,
130 max_num_seqs=16,
131 max_loras=4,
132 max_model_len=400,
133 gpu_memory_utilization=0.2, # avoid OOM
134 quantization=model.quantization,
135 enable_chunked_prefill=True,
136 )
137 try:
138 output_tp1 = do_sample(
139 llm_tp1, qwen3_meowing_lora_files, lora_id=1, max_tokens=10
140 )
141 finally:
142 del llm_tp1
143 cleanup_dist_env_and_memory()
144
145 llm_tp2 = vllm.LLM(
146 model=model.model_path,
147 enable_lora=True,
148 max_num_seqs=16,
149 max_loras=4,
150 tensor_parallel_size=2,
151 max_model_len=400,
152 gpu_memory_utilization=0.2, # avoid OOM
153 quantization=model.quantization,
154 enable_chunked_prefill=True,
155 )
156 try:
157 output_tp2 = do_sample(
158 llm_tp2, qwen3_meowing_lora_files, lora_id=1, max_tokens=10
159 )
160 finally:
161 del llm_tp2
162 cleanup_dist_env_and_memory()
163
164 assert output_tp1 == output_tp2