多模态模型与嵌入模型
vLLM 不仅支持文本生成模型,还支持多模态模型(视觉语言模型)和嵌入模型。本章介绍如何使用这些模型进行推理和服务。
多模态模型概述
vLLM 支持多种视觉语言模型(Vision Language Models, VLM),能够处理图像和文本的混合输入。这对于图像描述、视觉问答、文档理解等应用场景非常有用。
支持的多模态模型
vLLM 原生支持多种视觉语言模型架构:
| 架构 | 代表模型 |
|---|---|
LlavaForConditionalGeneration | LLaVA 系列 |
Qwen2VLForConditionalGeneration | Qwen2-VL、Qwen2.5-VL |
Llama4ForConditionalGeneration | Llama 4 |
InternVLForConditionalGeneration | InternVL 系列 |
PixtralForConditionalGeneration | Pixtral |
Phi3VForCausalLM | Phi-3-Vision |
Gemma3ForConditionalGeneration | Gemma 3(多模态版本) |
DeepseekVLForCausalLM | DeepSeek-VL |
MolmoForCausalLM | Molmo |
通过 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 系统等场景中非常有用。
什么是嵌入模型
嵌入模型将文本转换为高维向量,使得语义相似的文本在向量空间中距离更近。与生成模型不同,嵌入模型不产生文本输出,而是输出固定维度的向量。
支持的嵌入模型
| 架构 | 代表模型 |
|---|---|
BertModel | BAAI/bge-base-en-v1.5、Snowflake/snowflake-arctic-embed-xs |
Gemma2Model | BAAI/bge-multilingual-gemma2 |
GteModel | Snowflake/snowflake-arctic-embed-m-v2.0 |
NomicBertModel | nomic-ai/nomic-embed-text-v1 |
LlamaModel | intfloat/e5-mistral-7b-instruct |
Qwen2Model | Alibaba-NLP/gte-Qwen2-7B-instruct |
Qwen3Model | Qwen/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
}'
最佳实践
多模态模型
- 图像预处理:确保图像尺寸和格式符合模型要求,避免过大的图像导致显存溢出
- 批量处理:对于多个图像处理请求,使用批处理提高吞吐量
- 限制图像数量:通过
--limit-mm-per-prompt防止资源耗尽
vllm serve Qwen/Qwen2-VL-7B-Instruct \
--limit-mm-per-prompt image=5 \
--max-model-len 8192
嵌入模型
- 选择合适的模型:根据任务需求选择嵌入维度和语言支持
- 批量推理:利用 vLLM 的批处理能力提高吞吐量
- 归一化处理:在计算相似度前对嵌入向量进行归一化
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 对多模态模型和嵌入模型的支持:
- 多模态模型:支持视觉语言模型进行图像理解
- 嵌入模型:生成文本的向量表示,用于语义搜索和相似度计算
- Rerank 模型:对搜索结果进行重新排序
- API 兼容:支持 OpenAI 兼容的 API 接口
这些功能扩展了 vLLM 的应用场景,使其能够处理更广泛的 AI 任务。