跳到内容

Embedding Usages

嵌入模型是一类机器学习模型,旨在将非结构化数据(如文本、图像或音频)转换为结构化的数值表示,即嵌入。

摘要

  • Model Usage: (sequence) embedding
  • Pooling Task: embed
  • 离线 API
    • LLM.embed(...)
    • LLM.encode(..., pooling_task="embed")
    • LLM.score(...)
  • 在线 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 自动将任何架构的模型转换为嵌入模型,但为了获得最佳结果,您应该使用专门为此训练的池化模型。

离线推理

池化参数

支持以下池化参数

    use_activation: bool | None = None
    dimensions: int | None = None

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 参数

代码
    model: str | None = None
    user: str | None = None
    input: list[int] | list[list[int]] | str | list[str]
    encoding_format: EncodingFormat = "float"
    dimensions: int | None = None

支持以下额外参数

代码
    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),支持以下参数

代码
    model: str | None = None
    user: str | None = None
    messages: list[ChatCompletionMessageParam]
    encoding_format: EncodingFormat = "float"
    dimensions: int | None = None

反而支持这些额外参数

代码
    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, imagesinputs 其中之一)
images list[string] Base64 数据 URI 图像
inputs list[object] 混合文本与图像内容对象
embedding_types list[string] 输出类型(默认: ["float"]
output_dimension int 将嵌入截断至此维度 (Matryoshka)
truncate string END, STARTNONE (默认: 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"]
  }'
响应
{
  "id": "embd-...",
  "embeddings": {
    "float": [
      [0.012, -0.034, ...],
      [0.056, 0.078, ...]
    ]
  },
  "texts": ["Hello world", "How are you?"],
  "meta": {
    "api_version": {"version": "2"},
    "billed_units": {"input_tokens": 12}
  }
}

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"]
  }'
响应
{
  "id": "embd-...",
  "embeddings": {
    "float": [[0.012, -0.034, ...]],
    "binary": [[42, -117, ...]]
  },
  "texts": ["What is machine learning?"],
  "meta": {
    "api_version": {"version": "2"},
    "billed_units": {"input_tokens": 8}
  }
}

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 参数将导致以下错误。

{"object":"error","message":"Model \"BAAI/bge-m3\" does not support matryoshka representation, changing output dimensions will lead to poor results.","type":"BadRequestError","param":null,"code":400}

Manually enable Matryoshka Embeddings

目前没有官方接口用于指定对 Matryoshka 嵌入的支持。在 vLLM 中,如果 config.jsonis_matryoshkaTrue,您可以将输出维度更改为任意值。使用 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 嵌入的服务模型示例。

vllm serve Snowflake/snowflake-arctic-embed-m-v1.5 --hf-overrides '{"matryoshka_dimensions":[256]}'

离线推理

您可以通过使用 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 服务器。

vllm serve jinaai/jina-embeddings-v3 --trust-remote-code

您可以通过使用 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