Embedding Usages¶
嵌入模型是一类机器学习模型,旨在将非结构化数据(如文本、图像或音频)转换为结构化的数值表示,即嵌入。
摘要¶
- Model Usage: (sequence) embedding
- Pooling Task:
embed - 离线 API
LLM.embed(...)LLM.encode(..., pooling_task="embed")LLM.score(...)
- 在线 API
- Cohere Embed API (
/v2/embed) - OpenAI 兼容嵌入 API (
/v1/embeddings) - 池化 API (
/pooling)
- Cohere Embed API (
(序列)嵌入与 Token 嵌入的主要区别在于输出粒度:(序列)嵌入为整个输入序列生成一个嵌入向量,而 Token 嵌入则为序列中的每个单独 Token 生成一个嵌入。
许多嵌入模型同时支持(序列)嵌入和 Token 嵌入。关于 Token 嵌入的更多详细信息,请参考此页面。
典型用例¶
Embedding¶
嵌入模型最基础的用例是对输入进行嵌入,例如用于 RAG(检索增强生成)。
Pairwise Similarity¶
您可以使用 Score API 计算成对相似度分数,以构建相似度矩阵。
支持的模型¶
纯文本模型¶
| 架构 | 模型 | 示例 HF 模型 | LoRA | PP |
|---|---|---|---|---|
BertModel | 基于 BERT | BAAI/bge-base-en-v1.5, Snowflake/snowflake-arctic-embed-xs 等。 | ||
BertSpladeSparseEmbeddingModel | SPLADE | naver/splade-v3 | ||
ErnieModel | 基于 BERT 的中文 ERNIE | shibing624/text2vec-base-chinese-sentence | ||
Gemma2ModelC | 基于 Gemma 2 | BAAI/bge-multilingual-gemma2 等。 | ✅︎ | ✅︎ |
Gemma3TextModelC | 基于 Gemma 3 | google/embeddinggemma-300m 等。 | ✅︎ | ✅︎ |
GritLM | GritLM | parasail-ai/GritLM-7B-vllm. | ✅︎ | ✅︎ |
GteModel | Arctic-Embed-2.0-M | Snowflake/snowflake-arctic-embed-m-v2.0. | ||
GteNewModel | mGTE-TRM(见说明) | Alibaba-NLP/gte-multilingual-base 等。 | ||
LlamaBidirectionalModelC | 基于 Llama,带双向注意力 | nvidia/llama-nemotron-embed-1b-v2 等。 | ✅︎ | ✅︎ |
LlamaModelC, LlamaForCausalLMC, MistralModelC 等。 | 基于 Llama | intfloat/e5-mistral-7b-instruct 等。 | ✅︎ | ✅︎ |
ModernBertModel | 基于 ModernBERT | Alibaba-NLP/gte-modernbert-base 等。 | ||
NomicBertModel | Nomic BERT | nomic-ai/nomic-embed-text-v1, nomic-ai/nomic-embed-text-v2-moe, Snowflake/snowflake-arctic-embed-m-long 等。 | ||
Qwen2ModelC, Qwen2ForCausalLMC | 基于 Qwen2 | ssmits/Qwen2-7B-Instruct-embed-base (见说明), Alibaba-NLP/gte-Qwen2-7B-instruct (见说明) 等。 | ✅︎ | ✅︎ |
Qwen3ModelC, Qwen3ForCausalLMC | 基于 Qwen3 | Qwen/Qwen3-Embedding-0.6B 等。 | ✅︎ | ✅︎ |
RobertaModel, RobertaForMaskedLM | 基于 RoBERTa | sentence-transformers/all-roberta-large-v1 等。 | ||
VoyageQwen3BidirectionalEmbedModelC | 基于 Voyage Qwen3,具有双向注意力机制 | voyageai/voyage-4-nano 等。 | ✅︎ | ✅︎ |
XLMRobertaModel | 基于 XLMRobertaModel | BAAI/bge-m3 (见说明), intfloat/multilingual-e5-base, jinaai/jina-embeddings-v3 (见说明) 等。 | ||
*ModelC, *ForCausalLMC 等 | 生成式模型 | 不适用 | * | * |
注意
第二代 GTE 模型 (mGTE-TRM) 被命名为 NewModel。由于 NewModel 这个名称太通用,您应设置 --hf-overrides '{"architectures": ["GteNewModel"]}' 来指定使用 GteNewModel 架构。
注意
ssmits/Qwen2-7B-Instruct-embed-base 的 Sentence Transformers 配置定义不当。您需要通过传递 --pooler-config '{"pooling_type": "MEAN"}' 来手动设置平均池化 (mean pooling)。
注意
对于 Alibaba-NLP/gte-Qwen2-*,您需要启用 --trust-remote-code 以便加载正确的 tokenizer。详情请参阅 HF Transformers 上的相关议题。
注意
BAAI/bge-m3 模型带有用于稀疏 (sparse) 和 Colbert 嵌入的额外权重,请参阅 此页面 获取更多信息。
注意
jinaai/jina-embeddings-v3 通过 LoRA 支持多种任务,而 vLLM 目前仅通过合并 LoRA 权重支持文本匹配任务。
多模态模型¶
注意
有关多模态模型输入的更多信息,请参阅此页面。
| 架构 | 模型 | 输入 | 示例 HF 模型 | LoRA | PP |
|---|---|---|---|---|---|
CLIPModel | CLIP | T / I | openai/clip-vit-base-patch32, openai/clip-vit-large-patch14 等。 | ||
LlamaNemotronVLModel | Llama Nemotron Embedding + SigLIP | T + I | nvidia/llama-nemotron-embed-vl-1b-v2 | ||
LlavaNextForConditionalGenerationC | 基于 LLaVA-NeXT | T / I | royokong/e5-v | ✅︎ | |
Phi3VForCausalLMC | 基于 Phi-3-Vision | T + I | TIGER-Lab/VLM2Vec-Full | ✅︎ | |
Qwen3VLForConditionalGenerationC | Qwen3-VL | T + I + V | Qwen/Qwen3-VL-Embedding-2B 等。 | ✅︎ | ✅︎ |
SiglipModel | SigLIP, SigLIP2 | T / I | google/siglip-base-patch16-224, google/siglip2-base-patch16-224 | ||
*ForConditionalGenerationC, *ForCausalLMC 等 | 生成式模型 | * | 不适用 | * | * |
C 通过 --convert embed 自动转换为嵌入模型。(详细信息)
* 功能支持与原始模型相同。
如果您的模型不在上述列表中,我们将尝试使用 as_embedding_model 自动转换模型。默认情况下,整个提示词的嵌入是从对应于最后一个 token 的归一化隐藏状态中提取的。
注意
尽管 vLLM 支持通过 --convert embed 自动将任何架构的模型转换为嵌入模型,但为了获得最佳结果,您应该使用专门为此训练的池化模型。
离线推理¶
池化参数¶
支持以下池化参数。
LLM.embed¶
embed 方法会为每个提示词输出一个嵌入向量。
from vllm import LLM
llm = LLM(model="intfloat/e5-small", runner="pooling")
(output,) = llm.embed("Hello, my name is")
embeds = output.outputs.embedding
print(f"Embeddings: {embeds!r} (size={len(embeds)})")
代码示例请查看此处: examples/basic/offline_inference/embed.py
LLM.encode¶
encode 方法适用于 vLLM 中的所有池化模型。
在使用 LLM.encode 处理嵌入模型时,请设置 pooling_task="embed"
from vllm import LLM
llm = LLM(model="intfloat/e5-small", runner="pooling")
(output,) = llm.encode("Hello, my name is", pooling_task="embed")
data = output.outputs.data
print(f"Data: {data!r}")
LLM.score¶
score 方法输出句子对之间的相似度得分。
所有支持嵌入任务的模型也支持使用 Score API,通过计算两个输入提示词嵌入之间的余弦相似度来计算相似度得分。
from vllm import LLM
llm = LLM(model="intfloat/e5-small", runner="pooling")
(output,) = llm.score(
"What is the capital of France?",
"The capital of Brazil is Brasilia.",
)
score = output.outputs.score
print(f"Score: {score}")
在线服务¶
OpenAI-Compatible Embeddings API¶
我们的 Embeddings API 与 OpenAI 的 Embeddings API 兼容;您可以使用 官方 OpenAI Python 客户端 与其交互。
代码示例: examples/pooling/embed/openai_embedding_client.py
Completion Parameters¶
支持以下分类 API 参数
代码
支持以下额外参数
代码
truncate_prompt_tokens: Annotated[int, Field(ge=-1)] | None = None
truncation_side: Literal["left", "right"] | None = Field(
default=None,
description=(
"Which side to truncate from when truncate_prompt_tokens is active. "
"'right' keeps the first N tokens. "
"'left' keeps the last N tokens."
),
)
request_id: str = Field(
default_factory=random_uuid,
description=(
"The request_id related to this request. If the caller does "
"not set it, a random_uuid will be generated. This id is used "
"through out the inference process and return in response."
),
)
priority: int = Field(
default=0,
ge=-(2**63),
le=2**63 - 1,
description=(
"The priority of the request (lower means earlier handling; "
"default: 0). Any priority other than 0 will raise an error "
"if the served model does not use priority scheduling."
),
)
mm_processor_kwargs: dict[str, Any] | None = Field(
default=None,
description="Additional kwargs to pass to the HF processor.",
)
cache_salt: str | None = Field(
default=None,
description=(
"If specified, the prefix cache will be salted with the provided "
"string to prevent an attacker to guess prompts in multi-user "
"environments. The salt should be random, protected from "
"access by 3rd parties, and long enough to be "
"unpredictable (e.g., 43 characters base64-encoded, corresponding "
"to 256 bit)."
),
)
add_special_tokens: bool = Field(
default=True,
description=(
"If true (the default), special tokens (e.g. BOS) will be added to "
"the prompt."
),
)
embed_dtype: EmbedDType = Field(
default="float32",
description=(
"What dtype to use for encoding. Default to using float32 for base64 "
"encoding to match the OpenAI python client behavior. "
"This parameter will affect base64 and binary_response."
),
)
endianness: Endianness = Field(
default="native",
description=(
"What endianness to use for encoding. Default to using native for "
"base64 encoding to match the OpenAI python client behavior."
"This parameter will affect base64 and binary_response."
),
)
use_activation: bool | None = Field(
default=None,
description="Whether to use activation for the pooler outputs. "
"`None` uses the pooler's default, which is `True` in most cases.",
)
Chat Parameters¶
对于类聊天输入(即传递了 messages),支持以下参数
代码
反而支持这些额外参数
代码
truncate_prompt_tokens: Annotated[int, Field(ge=-1)] | None = None
truncation_side: Literal["left", "right"] | None = Field(
default=None,
description=(
"Which side to truncate from when truncate_prompt_tokens is active. "
"'right' keeps the first N tokens. "
"'left' keeps the last N tokens."
),
)
request_id: str = Field(
default_factory=random_uuid,
description=(
"The request_id related to this request. If the caller does "
"not set it, a random_uuid will be generated. This id is used "
"through out the inference process and return in response."
),
)
priority: int = Field(
default=0,
ge=-(2**63),
le=2**63 - 1,
description=(
"The priority of the request (lower means earlier handling; "
"default: 0). Any priority other than 0 will raise an error "
"if the served model does not use priority scheduling."
),
)
mm_processor_kwargs: dict[str, Any] | None = Field(
default=None,
description="Additional kwargs to pass to the HF processor.",
)
cache_salt: str | None = Field(
default=None,
description=(
"If specified, the prefix cache will be salted with the provided "
"string to prevent an attacker to guess prompts in multi-user "
"environments. The salt should be random, protected from "
"access by 3rd parties, and long enough to be "
"unpredictable (e.g., 43 characters base64-encoded, corresponding "
"to 256 bit)."
),
)
add_generation_prompt: bool = Field(
default=False,
description=(
"If true, the generation prompt will be added to the chat template. "
"This is a parameter used by chat template in tokenizer config of the "
"model."
),
)
continue_final_message: bool = Field(
default=False,
description=(
"If this is set, the chat will be formatted so that the final "
"message in the chat is open-ended, without any EOS tokens. The "
"model will continue this message rather than starting a new one. "
'This allows you to "prefill" part of the model\'s response for it. '
"Cannot be used at the same time as `add_generation_prompt`."
),
)
add_special_tokens: bool = Field(
default=False,
description=(
"If true, special tokens (e.g. BOS) will be added to the prompt "
"on top of what is added by the chat template. "
"For most models, the chat template takes care of adding the "
"special tokens so this should be set to false (as is the "
"default)."
),
)
chat_template: str | None = Field(
default=None,
description=(
"A Jinja template to use for this conversion. "
"As of transformers v4.44, default chat template is no longer "
"allowed, so you must provide a chat template if the tokenizer "
"does not define one."
),
)
chat_template_kwargs: dict[str, Any] | None = Field(
default=None,
description=(
"Additional keyword args to pass to the template renderer. "
"Will be accessible by the chat template."
),
)
media_io_kwargs: dict[str, dict[str, Any]] | None = Field(
default=None,
description=(
"Additional kwargs to pass to the media IO connectors, "
"keyed by modality. Merged with engine-level media_io_kwargs."
),
)
embed_dtype: EmbedDType = Field(
default="float32",
description=(
"What dtype to use for encoding. Default to using float32 for base64 "
"encoding to match the OpenAI python client behavior. "
"This parameter will affect base64 and binary_response."
),
)
endianness: Endianness = Field(
default="native",
description=(
"What endianness to use for encoding. Default to using native for "
"base64 encoding to match the OpenAI python client behavior."
"This parameter will affect base64 and binary_response."
),
)
use_activation: bool | None = Field(
default=None,
description="Whether to use activation for the pooler outputs. "
"`None` uses the pooler's default, which is `True` in most cases.",
)
示例¶
如果模型具有聊天模板,您可以使用 messages 列表(与 Chat API 具有相同的模式)替换 inputs,这将作为单个提示词处理给模型。以下是一个在保留 OpenAI 类型注解的同时调用 API 的便捷函数
代码
from openai import OpenAI
from openai._types import NOT_GIVEN, NotGiven
from openai.types.chat import ChatCompletionMessageParam
from openai.types.create_embedding_response import CreateEmbeddingResponse
def create_chat_embeddings(
client: OpenAI,
*,
messages: list[ChatCompletionMessageParam],
model: str,
encoding_format: Union[Literal["base64", "float"], NotGiven] = NOT_GIVEN,
) -> CreateEmbeddingResponse:
return client.post(
"/embeddings",
cast_to=CreateEmbeddingResponse,
body={"messages": messages, "model": model, "encoding_format": encoding_format},
)
Multi-modal inputs¶
您可以通过为服务器定义自定义聊天模板并在请求中传递 messages 列表,将多模态输入传递给嵌入模型。请参考下方的示例说明。
服务模型
vllm serve TIGER-Lab/VLM2Vec-Full --runner pooling \
--trust-remote-code \
--max-model-len 4096 \
--chat-template examples/pooling/embed/template/vlm2vec_phi3v.jinja
重要
由于 VLM2Vec 与 Phi-3.5-Vision 具有相同的模型架构,我们必须显式传递 --runner pooling 以在嵌入模式而非文本生成模式下运行此模型。
此模型的自定义聊天模板与原始模板完全不同,可以在此处找到: examples/pooling/embed/template/vlm2vec_phi3v.jinja
由于请求模式未由 OpenAI 客户端定义,我们使用底层 requests 库向服务器发送请求
代码
from openai import OpenAI
client = OpenAI(
base_url="https://:8000/v1",
api_key="EMPTY",
)
image_url = "https://vllm-public-assets.s3.us-west-2.amazonaws.com/vision_model_images/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
response = create_chat_embeddings(
client,
model="TIGER-Lab/VLM2Vec-Full",
messages=[
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": image_url}},
{"type": "text", "text": "Represent the given image."},
],
}
],
encoding_format="float",
)
print("Image embedding output:", response.data[0].embedding)
服务模型
vllm serve MrLight/dse-qwen2-2b-mrl-v1 --runner pooling \
--trust-remote-code \
--max-model-len 8192 \
--chat-template examples/pooling/embed/template/dse_qwen2_vl.jinja
重要
与 VLM2Vec 一样,我们必须显式传递 --runner pooling。
此外,MrLight/dse-qwen2-2b-mrl-v1 需要 EOS token 进行嵌入,这由自定义聊天模板处理: examples/pooling/embed/template/dse_qwen2_vl.jinja
重要
MrLight/dse-qwen2-2b-mrl-v1 需要一个最小图像尺寸的占位符图像用于文本查询嵌入。详细信息请参阅下方的完整代码示例。
完整示例: examples/pooling/embed/vision_embedding_online.py
Cohere Embed API¶
我们的 API 也兼容 Cohere 的 Embed v2 API,该 API 增加了对一些现代嵌入功能的支持,例如截断、输出维度、嵌入类型和输入类型。此端点适用于任何嵌入模型(包括多模态模型)。
Cohere Embed API 请求参数¶
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
model | string | 必填 | 模型名称 |
input_type | string | 否 | 提示词前缀键(依赖于模型,见下文) |
texts | list[string] | 否 | 文本输入(使用 texts, images 或 inputs 其中之一) |
images | list[string] | 否 | Base64 数据 URI 图像 |
inputs | list[object] | 否 | 混合文本与图像内容对象 |
embedding_types | list[string] | 否 | 输出类型(默认: ["float"]) |
output_dimension | int | 否 | 将嵌入截断至此维度 (Matryoshka) |
truncate | string | 否 | END, START 或 NONE (默认: END) |
Text embedding¶
curl -X POST "https://:8000/v2/embed" \
-H "Content-Type: application/json" \
-d '{
"model": "Snowflake/snowflake-arctic-embed-m-v1.5",
"input_type": "query",
"texts": ["Hello world", "How are you?"],
"embedding_types": ["float"]
}'
响应
Mixed text and image inputs¶
对于多模态模型,您可以通过传递 base64 数据 URI 来嵌入图像。inputs 字段接受包含文本和图像混合内容的对象列表。
curl -X POST "https://:8000/v2/embed" \
-H "Content-Type: application/json" \
-d '{
"model": "google/siglip-so400m-patch14-384",
"inputs": [
{
"content": [
{"type": "text", "text": "A photo of a cat"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBOR..."}}
]
}
],
"embedding_types": ["float"]
}'
Embedding types¶
embedding_types 参数控制输出格式。可以在单个调用中请求多种类型
| 类型 | 描述 |
|---|---|
float | 原始 float32 嵌入(默认) |
binary | 位压缩有符号二进制 |
ubinary | 位压缩无符号二进制 |
base64 | 编码为 base64 的小端 float32 |
curl -X POST "https://:8000/v2/embed" \
-H "Content-Type: application/json" \
-d '{
"model": "Snowflake/snowflake-arctic-embed-m-v1.5",
"input_type": "query",
"texts": ["What is machine learning?"],
"embedding_types": ["float", "binary"]
}'
响应
Truncation¶
truncate 参数控制处理超过模型最大序列长度的输入的方式
| 值(Value) | 行为 |
|---|---|
END (默认) | 保留前部分 token,丢弃尾部 |
START | 保留后部分 token,丢弃头部 |
NONE | 如果输入过长,返回错误 |
Input type and prompt prefixes¶
input_type 字段选择要在每个文本输入前添加的提示词前缀。可用值取决于模型
- 在
config.json中具有task_instructions的模型:task_instructions字典中的键是有效的input_type值,相应的值会添加到每个文本前。 - 带有
config_sentence_transformers.json提示词的模型:prompts字典中的键是有效的input_type值。例如,Snowflake/snowflake-arctic-embed-xs定义了"query",因此设置input_type: "query"会添加"Represent this sentence for searching relevant passages: "。 - 其他模型:不支持
input_type,如果传递将引发验证错误。
更多示例¶
更多示例可以在此处找到: examples/pooling/embed
支持的功能¶
Enable/disable normalize¶
您可以通过 use_activation 启用或禁用归一化。
Matryoshka Embeddings¶
Matryoshka 嵌入 或 Matryoshka 表示学习 (MRL) 是一种用于训练嵌入模型的技术。它允许用户在性能和成本之间进行权衡。
警告
并非所有嵌入模型都使用 Matryoshka 表示学习训练。为避免滥用 dimensions 参数,vLLM 对于尝试更改不支持 Matryoshka 嵌入的模型输出维度的请求,会返回错误。
例如,在使用 BAAI/bge-m3 模型时设置 dimensions 参数将导致以下错误。
Manually enable Matryoshka Embeddings¶
目前没有官方接口用于指定对 Matryoshka 嵌入的支持。在 vLLM 中,如果 config.json 中 is_matryoshka 为 True,您可以将输出维度更改为任意值。使用 matryoshka_dimensions 控制允许的输出维度。
对于支持 Matryoshka 嵌入但未被 vLLM 识别的模型,请使用 hf_overrides={"is_matryoshka": True} 或 hf_overrides={"matryoshka_dimensions": [<allowed output dimensions>]} (离线) 手动覆盖配置,或使用 --hf-overrides '{"is_matryoshka": true}' 或 --hf-overrides '{"matryoshka_dimensions": [<allowed output dimensions>]}' (在线)。
以下是启用 Matryoshka 嵌入的服务模型示例。
离线推理¶
您可以通过使用 PoolingParams 中的 dimensions 参数,来更改支持 Matryoshka 嵌入的嵌入模型的输出维度。
from vllm import LLM, PoolingParams
llm = LLM(
model="jinaai/jina-embeddings-v3",
runner="pooling",
trust_remote_code=True,
)
outputs = llm.embed(
["Follow the white rabbit."],
pooling_params=PoolingParams(dimensions=32),
)
print(outputs[0].outputs)
代码示例请查看此处: examples/pooling/embed/embed_matryoshka_fy_offline.py
Online Inference (在线推理)¶
使用以下命令启动 vLLM 服务器。
您可以通过使用 dimensions 参数来更改支持 Matryoshka 嵌入的嵌入模型的输出维度。
curl http://127.0.0.1:8000/v1/embeddings \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"input": "Follow the white rabbit.",
"model": "jinaai/jina-embeddings-v3",
"encoding_format": "float",
"dimensions": 32
}'
预期输出
{"id":"embd-5c21fc9a5c9d4384a1b021daccaf9f64","object":"list","created":1745476417,"model":"jinaai/jina-embeddings-v3","data":[{"index":0,"object":"embedding","embedding":[-0.3828125,-0.1357421875,0.03759765625,0.125,0.21875,0.09521484375,-0.003662109375,0.1591796875,-0.130859375,-0.0869140625,-0.1982421875,0.1689453125,-0.220703125,0.1728515625,-0.2275390625,-0.0712890625,-0.162109375,-0.283203125,-0.055419921875,-0.0693359375,0.031982421875,-0.04052734375,-0.2734375,0.1826171875,-0.091796875,0.220703125,0.37890625,-0.0888671875,-0.12890625,-0.021484375,-0.0091552734375,0.23046875]}],"usage":{"prompt_tokens":8,"total_tokens":8,"completion_tokens":0,"prompt_tokens_details":null}}
OpenAI 客户端示例请查看此处: examples/pooling/embed/openai_embedding_matryoshka_fy_client.py
已移除的功能¶
Remove normalize from PoolingParams¶
我们已从 PoolingParams 中移除 normalize,请改用 use_activation。