main
py 90 lines 2.78 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 from collections.abc import Sequence
4
5 import openai
6 import pytest
7
8 from tests.conftest import HfRunner
9 from tests.models.utils import EmbedModelInfo, check_embeddings_close, matryoshka_fy
10 from vllm.entrypoints.pooling.embed.protocol import EmbeddingResponse
11
12
13 def float_embeddings(response: EmbeddingResponse) -> list[list[float]]:
14 embeddings = []
15 for d in response.data:
16 assert isinstance(d.embedding, list)
17 embeddings.append(d.embedding)
18 return embeddings
19
20
21 def run_embedding_correctness_test(
22 hf_model: "HfRunner",
23 inputs: list[str],
24 vllm_outputs: Sequence[list[float]],
25 dimensions: int | None = None,
26 ):
27 hf_outputs = hf_model.encode(inputs)
28 if dimensions:
29 hf_outputs = matryoshka_fy(hf_outputs, dimensions)
30
31 check_embeddings_close(
32 embeddings_0_lst=hf_outputs,
33 embeddings_1_lst=vllm_outputs,
34 name_0="hf",
35 name_1="vllm",
36 tol=1e-2,
37 )
38
39
40 def correctness_test_embed_models(
41 hf_runner,
42 vllm_runner,
43 model_info: EmbedModelInfo,
44 example_prompts,
45 vllm_extra_kwargs=None,
46 hf_model_callback=None,
47 ):
48 pytest.skip("Debug only, ci prefers to use mteb test.")
49
50 # The example_prompts has ending "\n", for example:
51 # "Write a short story about a robot that dreams for the first time.\n"
52 # sentence_transformers will strip the input texts, see:
53 # https://github.com/UKPLab/sentence-transformers/blob/v3.1.1/sentence_transformers/models/Transformer.py#L159
54 # This makes the input_ids different between hf_model and vllm_model.
55 # So we need to strip the input texts to avoid test failing.
56 example_prompts = [str(s).strip() for s in example_prompts]
57
58 vllm_extra_kwargs = vllm_extra_kwargs or {}
59 vllm_extra_kwargs["dtype"] = model_info.dtype
60
61 if model_info.hf_overrides is not None:
62 vllm_extra_kwargs["hf_overrides"] = model_info.hf_overrides
63
64 with vllm_runner(
65 model_info.name, runner="pooling", max_model_len=None, **vllm_extra_kwargs
66 ) as vllm_model:
67 vllm_outputs = vllm_model.embed(example_prompts)
68
69 with hf_runner(
70 model_info.name,
71 dtype=model_info.hf_dtype,
72 is_sentence_transformer=True,
73 ) as hf_model:
74 if hf_model_callback is not None:
75 hf_model_callback(hf_model)
76
77 run_embedding_correctness_test(hf_model, example_prompts, vllm_outputs)
78
79
80 async def run_client_embeddings(
81 client: openai.AsyncOpenAI,
82 model_name: str,
83 queries: list[str],
84 instruction: str = "",
85 ) -> list[list[float]]:
86 outputs = await client.embeddings.create(
87 model=model_name,
88 input=[instruction + q for q in queries],
89 )
90 return [data.embedding for data in outputs.data]