main
py 101 lines 3.46 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 import torch.nn.functional as F
8
9 from vllm import LLM, EmbeddingRequestOutput, PoolingParams
10 from vllm.inputs import PromptType
11 from vllm.tasks import PoolingTask
12
13 MODEL_NAME = "intfloat/multilingual-e5-small"
14
15 prompt = "The chef prepared a delicious meal."
16 prompt_token_ids = [0, 581, 21861, 133888, 10, 8, 150, 60744, 109911, 5, 2]
17 embedding_size = 384
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 assert embedding_size == runner.llm.model_config.embedding_size
33 # pytest caches yielded fixtures until after teardown, so use a proxy to
34 # avoid retaining the LLM while VllmRunner.__exit__ releases ROCm memory.
35 yield weakref.proxy(runner.llm)
36
37
38 @pytest.mark.skip_global_cleanup
39 def test_str_prompts(llm: LLM):
40 outputs = llm.embed(prompt, use_tqdm=False)
41 assert len(outputs) == 1
42 assert isinstance(outputs[0], EmbeddingRequestOutput)
43 assert outputs[0].prompt_token_ids == prompt_token_ids
44 assert len(outputs[0].outputs.embedding) == embedding_size
45
46
47 @pytest.mark.skip_global_cleanup
48 def test_token_ids_prompts(llm: LLM):
49 outputs = llm.embed([prompt_token_ids], use_tqdm=False)
50 assert len(outputs) == 1
51 assert isinstance(outputs[0], EmbeddingRequestOutput)
52 assert outputs[0].prompt_token_ids == prompt_token_ids
53 assert len(outputs[0].outputs.embedding) == embedding_size
54
55
56 @pytest.mark.skip_global_cleanup
57 def test_list_prompts(llm: LLM):
58 prompts: list[PromptType] = [prompt, prompt_token_ids]
59 outputs = llm.embed(prompts, use_tqdm=False)
60 assert len(outputs) == 2
61 for i in range(len(outputs)):
62 assert isinstance(outputs[i], EmbeddingRequestOutput)
63 assert outputs[i].prompt_token_ids == prompt_token_ids
64 assert len(outputs[i].outputs.embedding) == embedding_size
65
66
67 @pytest.mark.skip_global_cleanup
68 def test_pooling_params(llm: LLM):
69 def get_outputs(normalize):
70 outputs = llm.embed(
71 [prompt],
72 pooling_params=PoolingParams(use_activation=normalize),
73 use_tqdm=False,
74 )
75 return torch.tensor([x.outputs.embedding for x in outputs])
76
77 default = get_outputs(normalize=None)
78 w_normal = get_outputs(normalize=True)
79 wo_normal = get_outputs(normalize=False)
80
81 assert torch.allclose(default, w_normal, atol=1e-2), "Default should use normal."
82 assert not torch.allclose(w_normal, wo_normal, atol=1e-2), (
83 "wo_normal should not use normal."
84 )
85 assert torch.allclose(w_normal, F.normalize(wo_normal, p=2, dim=-1), atol=1e-2), (
86 "w_normal should be close to normal(wo_normal)."
87 )
88
89
90 @pytest.mark.parametrize(
91 "task", ["token_classify", "classify", "token_embed", "plugin"]
92 )
93 def test_unsupported_tasks(llm: LLM, task: PoolingTask):
94 if task == "plugin":
95 err_msg = "No IOProcessor plugin installed."
96 elif task == "token_embed":
97 err_msg = "Try switching the model's pooling_task via.+"
98 else:
99 err_msg = "Classification API is not supported by this model.+"
100 with pytest.raises(ValueError, match=err_msg):
101 llm.encode(prompt, pooling_task=task, use_tqdm=False)