main
py 107 lines 3.67 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import weakref
4
5 import pytest
6 import torch
7
8 from tests.models.utils import softmax
9 from vllm import LLM, ClassificationRequestOutput, PoolingParams
10 from vllm.inputs import PromptType
11 from vllm.tasks import PoolingTask
12
13 MODEL_NAME = "jason9693/Qwen2.5-1.5B-apeach"
14
15 prompt = "The chef prepared a delicious meal."
16 prompt_token_ids = [785, 29706, 10030, 264, 17923, 15145, 13]
17 num_labels = 2
18
19
20 @pytest.fixture(scope="module")
21 def llm(vllm_runner):
22 with vllm_runner(
23 MODEL_NAME,
24 max_model_len=None,
25 max_num_batched_tokens=32768,
26 tensor_parallel_size=1,
27 gpu_memory_utilization=0.75,
28 enforce_eager=True,
29 seed=0,
30 enable_chunked_prefill=None,
31 ) as runner:
32 # pytest caches yielded fixtures until after teardown, so use a proxy to
33 # avoid retaining the LLM while VllmRunner.__exit__ releases ROCm memory.
34 yield weakref.proxy(runner.llm)
35
36
37 @pytest.mark.skip_global_cleanup
38 def test_str_prompts(llm: LLM):
39 outputs = llm.classify(prompt, use_tqdm=False)
40 assert len(outputs) == 1
41 assert isinstance(outputs[0], ClassificationRequestOutput)
42 assert outputs[0].prompt_token_ids == prompt_token_ids
43 assert len(outputs[0].outputs.probs) == num_labels
44
45
46 @pytest.mark.skip_global_cleanup
47 def test_token_ids_prompts(llm: LLM):
48 outputs = llm.classify([prompt_token_ids], use_tqdm=False)
49 assert len(outputs) == 1
50 assert isinstance(outputs[0], ClassificationRequestOutput)
51 assert outputs[0].prompt_token_ids == prompt_token_ids
52 assert len(outputs[0].outputs.probs) == num_labels
53
54
55 @pytest.mark.skip_global_cleanup
56 def test_list_prompts(llm: LLM):
57 prompts: list[PromptType] = [prompt, prompt_token_ids]
58 outputs = llm.classify(prompts, use_tqdm=False)
59 assert len(outputs) == 2
60 for i in range(len(outputs)):
61 assert isinstance(outputs[i], ClassificationRequestOutput)
62 assert outputs[i].prompt_token_ids == prompt_token_ids
63 assert len(outputs[i].outputs.probs) == num_labels
64
65
66 @pytest.mark.skip_global_cleanup
67 def test_pooling_params(llm: LLM):
68 def get_outputs(use_activation):
69 outputs = llm.classify(
70 prompt,
71 pooling_params=PoolingParams(use_activation=use_activation),
72 use_tqdm=False,
73 )
74 return torch.tensor([x.outputs.probs for x in outputs])
75
76 default = get_outputs(use_activation=None)
77 w_activation = get_outputs(use_activation=True)
78 wo_activation = get_outputs(use_activation=False)
79
80 assert torch.allclose(default, w_activation, atol=1e-2), (
81 "Default should use activation."
82 )
83 assert not torch.allclose(w_activation, wo_activation, atol=1e-2), (
84 "wo_activation should not use activation."
85 )
86 assert torch.allclose(softmax(wo_activation), w_activation, atol=1e-2), (
87 "w_activation should be close to activation(wo_activation)."
88 )
89
90
91 @pytest.mark.skip_global_cleanup
92 def test_score_api(llm: LLM):
93 err_msg = "Scoring API is only enabled for num_labels == 1."
94 with pytest.raises(ValueError, match=err_msg):
95 llm.score("ping", "pong", use_tqdm=False)
96
97
98 @pytest.mark.parametrize("task", ["embed", "token_embed", "token_classify", "plugin"])
99 def test_unsupported_tasks(llm: LLM, task: PoolingTask):
100 if task == "plugin":
101 err_msg = "No IOProcessor plugin installed."
102 elif task == "token_classify":
103 err_msg = "Try switching the model's pooling_task via.+"
104 else:
105 err_msg = "Embedding API is not supported by this model.+"
106 with pytest.raises(ValueError, match=err_msg):
107 llm.encode(prompt, pooling_task=task, use_tqdm=False)