main
py 164 lines 4.82 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
5 import pytest
6 import torch
7
8 from vllm.multimodal.image import rescale_image_size
9
10 from ...conftest import IMAGE_ASSETS, ImageTestAssets, VllmRunner
11 from ..utils import check_logprobs_close
12
13 HF_IMAGE_PROMPTS = IMAGE_ASSETS.prompts(
14 {
15 "stop_sign": "<|im_start|>User\n<image>\nWhat's the content in the center of the image?<|im_end|>\n<|im_start|>Assistant\n", # noqa: E501
16 "cherry_blossom": "<|im_start|>User\n<image>\nWhat is the season?<|im_end|>\n<|im_start|>Assistant\n", # noqa: E501
17 }
18 )
19
20 IMAGE_SIZE_FACTOR_GROUPS = (
21 # Single-scale
22 (1.0,),
23 # Single-scale, batched
24 (1.0, 1.0, 1.0),
25 # Multi-scale
26 (0.25, 0.5, 1.0),
27 )
28
29
30 def run_awq_test(
31 vllm_runner: type[VllmRunner],
32 image_assets: ImageTestAssets,
33 source_model: str,
34 quant_model: str,
35 *,
36 size_factor_groups: tuple[tuple[float, ...], ...],
37 dtype: str,
38 max_tokens: int,
39 num_logprobs: int,
40 tensor_parallel_size: int,
41 distributed_executor_backend: str | None = None,
42 ):
43 images = [asset.pil_image for asset in image_assets]
44
45 inputs_per_image_and_size_group = [
46 (
47 [prompt for _ in size_factors],
48 [rescale_image_size(image, factor) for factor in size_factors],
49 )
50 for size_factors in size_factor_groups
51 for image, prompt in zip(images, HF_IMAGE_PROMPTS)
52 ]
53
54 # NOTE: take care of the order. run vLLM first, and then run HF.
55 # vLLM needs a fresh new process without cuda initialization.
56 # if we run HF first, the cuda initialization will be done and it
57 # will hurt multiprocessing backend with fork method (the default method).
58
59 # max_model_len should be greater than image_feature_size
60 with vllm_runner(
61 source_model,
62 max_model_len=4096,
63 dtype=dtype,
64 tensor_parallel_size=tensor_parallel_size,
65 distributed_executor_backend=distributed_executor_backend,
66 enforce_eager=True,
67 default_torch_num_threads=1,
68 ) as vllm_model:
69 source_outputs_per_image = [
70 vllm_model.generate_greedy_logprobs(
71 prompts, max_tokens, num_logprobs=num_logprobs, images=images
72 )
73 for prompts, images in inputs_per_image_and_size_group
74 ]
75
76 with vllm_runner(
77 quant_model,
78 quantization="awq",
79 max_model_len=4096,
80 dtype=dtype,
81 tensor_parallel_size=tensor_parallel_size,
82 distributed_executor_backend=distributed_executor_backend,
83 enforce_eager=True,
84 default_torch_num_threads=1,
85 ) as vllm_model:
86 quant_outputs_per_image = [
87 vllm_model.generate_greedy_logprobs(
88 prompts, max_tokens, num_logprobs=num_logprobs, images=images
89 )
90 for prompts, images in inputs_per_image_and_size_group
91 ]
92
93 for source_outputs, quant_outputs in zip(
94 source_outputs_per_image, quant_outputs_per_image
95 ):
96 # TODO: Check whether using original CLIPVisionModel can improve
97 # consistency against HF
98 check_logprobs_close(
99 outputs_0_lst=source_outputs,
100 outputs_1_lst=quant_outputs,
101 name_0="source",
102 name_1="awq",
103 )
104
105
106 @pytest.mark.parametrize(
107 ("model", "quantization", "dtype"),
108 [
109 ("mattbucci/gemma-4-26B-AWQ", "awq", "float16"),
110 ("cyankiwi/gemma-4-26B-A4B-it-AWQ-4bit", "compressed-tensors", "bfloat16"),
111 ],
112 ids=[
113 "gemma4-moe-standard-awq-dot-suffix",
114 "gemma4-moe-compressed-tensors-underscore-suffix",
115 ],
116 )
117 @torch.inference_mode()
118 def test_awq_load(
119 vllm_runner: type[VllmRunner],
120 example_prompts: list[str],
121 model: str,
122 quantization: str,
123 dtype: str,
124 ) -> None:
125 """Regression test: AWQ weight loading must not KeyError."""
126 with vllm_runner(
127 model,
128 quantization=quantization,
129 dtype=dtype,
130 max_model_len=128,
131 enforce_eager=True,
132 ) as vllm_model:
133 outputs = vllm_model.generate_greedy(example_prompts[:2], max_tokens=32)
134 assert len(outputs) == 2
135
136
137 @pytest.mark.parametrize(
138 ("source_model", "quant_model"),
139 [("OpenGVLab/InternVL2-2B", "OpenGVLab/InternVL2-2B-AWQ")],
140 )
141 @pytest.mark.parametrize("dtype", ["half"])
142 @pytest.mark.parametrize("max_tokens", [128])
143 @pytest.mark.parametrize("num_logprobs", [5])
144 @torch.inference_mode()
145 def test_awq_models(
146 vllm_runner,
147 image_assets,
148 source_model,
149 quant_model,
150 dtype,
151 max_tokens,
152 num_logprobs,
153 ) -> None:
154 run_awq_test(
155 vllm_runner,
156 image_assets,
157 source_model,
158 quant_model,
159 size_factor_groups=IMAGE_SIZE_FACTOR_GROUPS,
160 dtype=dtype,
161 max_tokens=max_tokens,
162 num_logprobs=num_logprobs,
163 tensor_parallel_size=1,
164 )