跳到主要内容

多模态模型与嵌入模型

vLLM 不仅支持文本生成模型,还支持多模态模型(视觉语言模型)和嵌入模型。本章介绍如何使用这些模型进行推理和服务。

多模态模型概述

vLLM 支持多种视觉语言模型(Vision Language Models, VLM),能够处理图像和文本的混合输入。这对于图像描述、视觉问答、文档理解等应用场景非常有用。

支持的多模态模型

vLLM 原生支持多种视觉语言模型架构:

架构代表模型
LlavaForConditionalGenerationLLaVA 系列
Qwen2VLForConditionalGenerationQwen2-VL、Qwen2.5-VL
Llama4ForConditionalGenerationLlama 4
InternVLForConditionalGenerationInternVL 系列
PixtralForConditionalGenerationPixtral
Phi3VForCausalLMPhi-3-Vision
Gemma3ForConditionalGenerationGemma 3(多模态版本)
DeepseekVLForCausalLMDeepSeek-VL
MolmoForCausalLMMolmo

通过 Transformers 后端支持

除了原生支持的模型,vLLM 还可以通过 Transformers 建模后端运行 Hugging Face Transformers 支持的任何视觉语言模型。这种方式性能通常在原生实现的 5% 以内。

检查是否使用 Transformers 后端

from vllm import LLM

llm = LLM(model="your-model-name")
llm.apply_model(lambda model: print(type(model)))

# 如果输出以 "Transformers..." 开头,则使用的是 Transformers 实现

强制使用 Transformers 实现:

llm = LLM(
model="your-model-name",
model_impl="transformers"
)

多模态模型推理

离线推理

from vllm import LLM, SamplingParams
from vllm.assets.image import ImageAsset

# 加载视觉语言模型
llm = LLM(model="Qwen/Qwen2-VL-7B-Instruct")

# 准备图像
image = ImageAsset("cherry_blossom").pil_image

# 构建消息
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "请描述这张图片"},
{"type": "image_url", "image_url": {"url": image}}
]
}
]

# 生成
sampling_params = SamplingParams(temperature=0.7, max_tokens=200)
outputs = llm.chat(messages, sampling_params)

print(outputs[0].outputs[0].text)

使用本地图像文件

from vllm import LLM, SamplingParams

llm = LLM(model="Qwen/Qwen2-VL-7B-Instruct")

# 从本地文件加载图像
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "这张图片展示了什么?"},
{"type": "image_url", "image_url": {"url": "file:///path/to/image.jpg"}}
]
}
]

outputs = llm.chat(messages, SamplingParams(temperature=0.7, max_tokens=200))
print(outputs[0].outputs[0].text)

使用图像 URL

messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "描述这张图片的内容"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
]
}
]

outputs = llm.chat(messages, SamplingParams(temperature=0.7))

Base64 编码图像

import base64
from vllm import LLM, SamplingParams

# 读取图像并编码为 Base64
with open("image.jpg", "rb") as f:
image_base64 = base64.b64encode(f.read()).decode("utf-8")

messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "图片中有什么?"},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_base64}"
}
}
]
}
]

outputs = llm.chat(messages, SamplingParams(temperature=0.7))

多模态 API 服务

启动服务

vllm serve Qwen/Qwen2-VL-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096 \
--limit-mm-per-prompt image=5 # 限制每个请求最多 5 张图片

API 调用示例

使用 OpenAI SDK

from openai import OpenAI

client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed"
)

# 使用图像 URL
response = client.chat.completions.create(
model="Qwen/Qwen2-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "描述这张图片"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
]
}
],
max_tokens=200
)

print(response.choices[0].message.content)

使用 curl

curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2-VL-7B-Instruct",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "图片中是什么?"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
]
}
],
"max_tokens": 200
}'

多图像输入

某些模型支持同时处理多张图像:

response = client.chat.completions.create(
model="Qwen/Qwen2-VL-7B-Instruct",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "比较这两张图片的差异"},
{"type": "image_url", "image_url": {"url": "https://example.com/image1.jpg"}},
{"type": "image_url", "image_url": {"url": "https://example.com/image2.jpg"}}
]
}
],
max_tokens=500
)

图像输入限制

通过 --limit-mm-per-prompt 参数控制每个请求中每种模态的最大数量:

# 每个请求最多 5 张图片
vllm serve Qwen/Qwen2-VL-7B-Instruct \
--limit-mm-per-prompt image=5

嵌入模型

vLLM 支持嵌入模型(Embedding Models),用于生成文本的向量表示。这在语义搜索、文本相似度计算、RAG 系统等场景中非常有用。

什么是嵌入模型

嵌入模型将文本转换为高维向量,使得语义相似的文本在向量空间中距离更近。与生成模型不同,嵌入模型不产生文本输出,而是输出固定维度的向量。

支持的嵌入模型

架构代表模型
BertModelBAAI/bge-base-en-v1.5、Snowflake/snowflake-arctic-embed-xs
Gemma2ModelBAAI/bge-multilingual-gemma2
GteModelSnowflake/snowflake-arctic-embed-m-v2.0
NomicBertModelnomic-ai/nomic-embed-text-v1
LlamaModelintfloat/e5-mistral-7b-instruct
Qwen2ModelAlibaba-NLP/gte-Qwen2-7B-instruct
Qwen3ModelQwen/Qwen3-Embedding-0.6B

离线嵌入推理

from vllm import LLM

# 加载嵌入模型,指定 runner 为 pooling
llm = LLM(
model="BAAI/bge-base-en-v1.5",
runner="pooling" # 重要:指定为池化模式
)

# 生成嵌入向量
texts = [
"什么是机器学习?",
"深度学习是机器学习的一个分支。",
"今天天气真好。"
]

outputs = llm.embed(texts)

for i, output in enumerate(outputs):
embedding = output.outputs.embedding
print(f"文本 {i+1}: {texts[i]}")
print(f"嵌入维度: {len(embedding)}")
print(f"向量前5个值: {embedding[:5]}")
print()

嵌入 API 服务

启动服务

vllm serve BAAI/bge-base-en-v1.5 \
--runner pooling \
--host 0.0.0.0 \
--port 8000

使用 OpenAI SDK 调用

from openai import OpenAI

client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed"
)

# 创建嵌入
response = client.embeddings.create(
model="BAAI/bge-base-en-v1.5",
input="什么是人工智能?"
)

embedding = response.data[0].embedding
print(f"嵌入维度: {len(embedding)}")
print(f"向量: {embedding[:10]}...")

批量嵌入

response = client.embeddings.create(
model="BAAI/bge-base-en-v1.5",
input=[
"机器学习是人工智能的一个分支。",
"深度学习使用神经网络。",
"自然语言处理处理人类语言。"
]
)

for i, item in enumerate(response.data):
print(f"嵌入 {i+1} 维度: {len(item.embedding)}")

使用 curl 调用

curl http://localhost:8000/v1/embeddings \
-H "Content-Type: application/json" \
-d '{
"model": "BAAI/bge-base-en-v1.5",
"input": "什么是机器学习?"
}'

将生成模型转换为嵌入模型

某些生成模型可以通过 --convert embed 参数转换为嵌入模型:

vllm serve intfloat/e5-mistral-7b-instruct \
--runner pooling \
--convert embed
from vllm import LLM

llm = LLM(
model="intfloat/e5-mistral-7b-instruct",
runner="pooling",
convert="embed"
)

outputs = llm.embed(["测试文本"])

池化配置

嵌入模型支持不同的池化策略来聚合 token 级别的嵌入:

from vllm import LLM

# 配置池化策略
llm = LLM(
model="your-embedding-model",
runner="pooling",
pooler_config={
"pooling_type": "MEAN" # 平均池化
}
)

支持的池化类型:

池化类型说明
MEAN平均池化,对序列中所有 token 的嵌入取平均
CLS使用 [CLS] token 的嵌入作为序列表示
LAST使用最后一个 token 的嵌入
STEP步进池化

语义相似度计算

使用嵌入向量计算文本相似度:

import numpy as np
from vllm import LLM

llm = LLM(model="BAAI/bge-base-en-v1.5", runner="pooling")

def cosine_similarity(a, b):
"""计算余弦相似度"""
a = np.array(a)
b = np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 待比较的文本
texts = [
"机器学习是人工智能的核心技术",
"深度学习是机器学习的重要分支",
"今天中午吃什么?"
]

# 生成嵌入
outputs = llm.embed(texts)
embeddings = [o.outputs.embedding for o in outputs]

# 计算相似度矩阵
print("语义相似度矩阵:")
print("-" * 50)
for i, text1 in enumerate(texts):
for j, text2 in enumerate(texts):
sim = cosine_similarity(embeddings[i], embeddings[j])
print(f"文本{i+1} vs 文本{j+1}: {sim:.4f}")
print()

Rerank 模型

vLLM 支持重排序(Rerank)模型,用于对搜索结果进行重新排序:

from vllm import LLM

llm = LLM(
model="BAAI/bge-reranker-base",
runner="pooling"
)

query = "什么是机器学习?"
documents = [
"机器学习是人工智能的一个分支,它使计算机能够从数据中学习。",
"今天天气非常好,适合户外运动。",
"深度学习使用多层神经网络进行特征学习。"
]

# 重排序
outputs = llm.rerank(query, documents)

for output in outputs:
print(f"文档: {output.text[:50]}...")
print(f"相关性得分: {output.outputs.score:.4f}")
print()

Rerank API 服务

curl http://localhost:8000/rerank \
-H "Content-Type: application/json" \
-d '{
"model": "BAAI/bge-reranker-base",
"query": "什么是机器学习?",
"documents": [
"机器学习是人工智能的一个分支。",
"今天天气很好。",
"深度学习是机器学习的子领域。"
],
"top_n": 2
}'

最佳实践

多模态模型

  1. 图像预处理:确保图像尺寸和格式符合模型要求,避免过大的图像导致显存溢出
  2. 批量处理:对于多个图像处理请求,使用批处理提高吞吐量
  3. 限制图像数量:通过 --limit-mm-per-prompt 防止资源耗尽
vllm serve Qwen/Qwen2-VL-7B-Instruct \
--limit-mm-per-prompt image=5 \
--max-model-len 8192

嵌入模型

  1. 选择合适的模型:根据任务需求选择嵌入维度和语言支持
  2. 批量推理:利用 vLLM 的批处理能力提高吞吐量
  3. 归一化处理:在计算相似度前对嵌入向量进行归一化
import numpy as np
from vllm import LLM

llm = LLM(model="BAAI/bge-base-en-v1.5", runner="pooling")

# 批量嵌入
texts = [f"文档 {i}" for i in range(100)]
outputs = llm.embed(texts)

# 归一化嵌入向量
embeddings = [np.array(o.outputs.embedding) for o in outputs]
normalized = [e / np.linalg.norm(e) for e in embeddings]

小结

本章介绍了 vLLM 对多模态模型和嵌入模型的支持:

  1. 多模态模型:支持视觉语言模型进行图像理解
  2. 嵌入模型:生成文本的向量表示,用于语义搜索和相似度计算
  3. Rerank 模型:对搜索结果进行重新排序
  4. API 兼容:支持 OpenAI 兼容的 API 接口

这些功能扩展了 vLLM 的应用场景,使其能够处理更广泛的 AI 任务。

参考资料