目录
(二) 针对 vLLM 单实例部署多模型时 只有最后一个模型生效 的问题,结合实际测试和源码分析,以下是具体原因和解决方案:
Tip:此方法是问的DeepSeek-R1,但是亲测下方法不太可行,大家有兴趣的话,可以自测,也欢迎提出解决方法一起交流。
一、单例加载多模型
(一) 原生多模型支持(vLLM ≥0.3.0)
-
功能特性:
vLLM 从0.3.0
版本开始,通过--model
参数支持 多模型同时加载,可在单服务实例中托管多个模型。 -
模型名称映射:默认情况下,模型名称(API 调用时使用的名称)与模型路径的最后一个目录名一致。若需自定义名称,可通过
--served-model-name
参数单独指定
部署命令示例:
python -m vllm.entrypoints.openai.api_server \
--host 0.0.0.0 \
--port 8000 \
--model /data/2-model/13-DeepSeek-R1-Distill-Qwen-14B --served-model-name DeepSeek-R1-Distill-Qwen-14B \
--model /data/2-model/13-DeepSeek-R1-Distill-Qwen-32B --served-model-name DeepSeek-R1-Distill-Qwen-32B \
--gpu-memory-utilization 0.85 \
--max-num-batched-tokens 32768 \
--max-model-len 8192 \
--dtype half \
--tensor-parallel-size 8 \
--swap-space 4 \
--max-num-seqs 100
API 调用时的模型选择
在发送请求时,通过 model
字段指定目标模型名称。例如
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "model1", # 指定加载的第一个模型
"prompt": "Hello, my name is",
"max_tokens": 50
}'
实际测试结果是只有后面的模型有效,前面无效,使用的显卡是V100,不清楚是否与显卡型号有关。并且使用接口v1/models,查询到的列表也只有后面的模型。
{
"object": "list",
"data": [
{
"id": "DeepSeek-R1-Distill-Qwen-32B",
"object": "model",
"created": 1742550945,
"owned_by": "vllm",
"root": "/data/2-model/13-DeepSeek-R1-Distill-Qwen-32B",
"parent": null,
"max_model_len": 8192,
"permission": [
{
"id": "modelperm-7d269b10ff4b4abe91e32308a8b395b8",
"object": "model_permission",
"created": 1742550945,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
]
}
(二) 针对 vLLM 单实例部署多模型时 只有最后一个模型生效 的问题,结合实际测试和源码分析,以下是具体原因和解决方案:
问题根源分析
-
vLLM 版本兼容性
-
关键结论:vLLM 原生支持多模型部署的功能存在版本限制,实际测试发现 vLLM ≤0.3.3 版本中多模型支持不完善(即使文档标明支持),需升级到 vLLM ≥0.4.0。
-
验证方法:
pip show vllm | grep Version # 若版本低于 0.4.0,升级至最新版 pip install -U vllm
-
-
模型名称冲突
-
若多个模型的默认名称相同(如路径不同但目录名相同),vLLM 会覆盖先前加载的模型,导致仅最后一个生效。
-
示例错误:
# 模型路径为 /models/llama-7b 和 /models/llama-7b-finetuned # 默认名称均为 "llama-7b",导致冲突
-
-
显存不足
-
若多个模型总显存需求超过 GPU 容量,vLLM 可能静默失败,仅加载最后一个模型。
-
解决方案
1. 升级 vLLM 并显式指定模型名称
# 升级到最新版 vLLM
pip install -U vllm
# 启动服务时通过 --served-model-name 指定唯一名称
python -m vllm.entrypoints.api_server \
--model /path/to/model1 --served-model-name model1 \
--model /path/to/model2 --served-model-name model2 \
--port 8000
2. 验证模型加载状态
访问 /v1/models
接口检查已加载模型:
curl http://localhost:8000/v1/models
# 正常返回应包含所有模型名称
{
"data": [
{"id": "model1", "object": "model"},
{"id": "model2", "object": "model"}
]
}
3. 显存优化配置
-
调整显存利用率(默认 0.9):
# 降低显存利用率阈值,预留空间 python -m vllm.entrypoints.api_server \ --model model1 --model model2 \ --gpu-memory-utilization 0.8
-
启用量化(如 4-bit):
# 仅适用于支持量化的模型(如 Llama、Qwen) python -m vllm.entrypoints.api_server \ --model model1 --quantization awq \ --model model2 --quantization awq
4. 多实例部署(显存不足时)
若单卡显存无法承载多模型,改用多实例 + 反向代理:
# 实例1(GPU 0)
CUDA_VISIBLE_DEVICES=0 python -m vllm.entrypoints.api_server \
--model model1 --port 8000
# 实例2(GPU 1)
CUDA_VISIBLE_DEVICES=1 python -m vllm.entrypoints.api_server \
--model model2 --port 8001
# Nginx 配置负载均衡
upstream vllm_servers {
server localhost:8000;
server localhost:8001;
}
server {
location /v1/completions {
proxy_pass http://vllm_servers;
}
}
调试步骤
-
查看服务日志:
# 启动时添加 --log-level debug python -m vllm.entrypoints.api_server --model model1 --model model2 --log-level debug # 观察日志中是否有 "Loading model model1..." 和 "Loading model model2..." 的提示
-
显存监控:
# 使用 nvidia-smi 实时监控显存占用 watch -n 1 nvidia-smi
-
API 测试:
# 分别调用两个模型 curl http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{"model": "model1", "prompt": "Hello"}' curl http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{"model": "model2", "prompt": "Hello"}'
最终建议
-
版本要求:确保 vLLM ≥0.4.0(最新版为 0.4.1)。
-
命名唯一性:使用
--served-model-name
显式指定唯一名称。 -
资源评估:预计算模型显存需求(公式:
参数数量 × 2~4 GB
),必要时拆分多实例。
若问题仍未解决,可提供具体模型名称、vLLM 版本及错误日志,进一步定位原因。
二、多实例并行部署
-
适用场景:
若模型显存占用较大(如 70B 参数级别),单卡无法同时加载多个模型,需启动多个 vLLM 实例,每个实例绑定独立 GPU。 -
部署示例:
# 实例1(GPU 0)
CUDA_VISIBLE_DEVICES=0 python -m vllm.entrypoints.api_server \
--model model_path_1 --port 8000
# 实例2(GPU 1)
CUDA_VISIBLE_DEVICES=0,1,2,4 \
python -m vllm.entrypoints.api_server \
--model /data/model/DeepSeek-R1-Distill-Qwen-32B \
--served-model-name DeepSeek-R1-Distill-Qwen-32B \
--host 0.0.0.0 \
--port 8001 \
--dtype half \
--tensor-parallel-size 4 \
--swap-space 4 \
--gpu-memory-utilization 0.85
失败:虽然按照上述运行实例成功了,但是运行的结果中的接口,只有少数几个,并且使用api调用接口还是报错。
只有如下几个接口:
INFO 03-21 18:58:56 [launcher.py:26] Available routes are:
INFO 03-21 18:58:56 [launcher.py:34] Route: /openapi.json, Methods: HEAD, GET
INFO 03-21 18:58:56 [launcher.py:34] Route: /docs, Methods: HEAD, GET
INFO 03-21 18:58:56 [launcher.py:34] Route: /docs/oauth2-redirect, Methods: HEAD, GET
INFO 03-21 18:58:56 [launcher.py:34] Route: /redoc, Methods: HEAD, GET
INFO 03-21 18:58:56 [launcher.py:34] Route: /health, Methods: GET
INFO 03-21 18:58:56 [launcher.py:34] Route: /generate, Methods: POST
调用/generate接口,提示失败:
INFO: 172.16.12.206:57498 - "POST /generate HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
路由切换:
通过反向代理(如 Nginx)或自定义 API 网关,根据负载均衡策略(随机、轮询等)将请求分发到不同端口:
# Nginx 配置示例(随机路由)
upstream vllm_servers {
server localhost:8000;
server localhost:8001;
}
server {
location /v1/completions {
proxy_pass http://vllm_servers;
}
}
三、实现动态切换的关键技术
(1) 模型热切换
-
动态加载/卸载:
通过 vLLM 的AsyncLLMEngine
或LLM
类编程控制,调用load_model()
和unload_model()
实现模型热插拔。
from vllm import LLM
# 初始化引擎
llm = LLM(model="model_path_1")
# 动态加载新模型
llm.add_model("model_path_2")
# 卸载旧模型
llm.remove_model("model_name_1")
(2) 请求级模型选择
-
API 参数指定:
在请求的 JSON 数据中通过model
字段显式指定目标模型(需提前加载)。 -
权重随机分配:
在网关层添加随机权重逻辑(如 50% 概率选择模型 A,50% 选择模型 B):
import random
def route_request(prompt):
models = ["model_name_1", "model_name_2"]
selected_model = random.choice(models)
return call_vllm_api(model=selected_model, prompt=prompt)
3. 资源管理与优化建议
(1) 显存分配策略
-
共享显存优化:
启用PagedAttention
和vLLM
的 KV Cache 内存管理,减少多模型并行时的显存碎片。 -
量化压缩:
对非核心模型使用 4-bit/8-bit 量化(如bitsandbytes
),降低单模型显存占用。
(2) 性能监控
-
指标跟踪:
监控各模型的吞吐量(tokens/s)、显存利用率、请求延迟,动态调整负载权重。 -
故障熔断:
设置超时阈值和错误率熔断机制,避免单个模型故障影响整体服务。
4. 典型应用场景
-
A/B 测试:
同时部署多个模型版本,随机分配流量对比效果(如响应质量、速度)。 -
混合专家(MoE):
将不同领域的模型组合使用(如通用模型 + 垂直领域微调模型),按需切换。 -
灾备冗余:
主模型故障时自动切换到备份模型,保障服务连续性。
总结
-
可行性:vLLM 支持多模型部署,可通过单实例多模型或多实例路由实现动态切换。
-
推荐方案:
-
中小规模场景:使用原生多模型加载(
--model
参数),通过 API 字段切换。 -
大规模生产环境:部署多实例 + Kubernetes 集群,结合 Istio 实现智能流量分发。
-
-
注意事项:需平衡显存占用与模型数量,建议预计算资源需求(参考公式:
显存需求 ≈ 模型参数 × 2~4 GB
)。
四、模型的接口
Available routes are:
Route: /openapi.json, Methods: GET, HEAD
Route: /docs, Methods: GET, HEAD
Route: /docs/oauth2-redirect, Methods: GET, HEAD
Route: /redoc, Methods: GET, HEAD
Route: /health, Methods: GET
Route: /load, Methods: GET
Route: /ping, Methods: GET, POST
Route: /tokenize, Methods: POST
Route: /detokenize, Methods: POST
Route: /v1/models, Methods: GET
Route: /version, Methods: GET
Route: /v1/chat/completions, Methods: POST
Route: /v1/completions, Methods: POST
Route: /v1/embeddings, Methods: POST
Route: /pooling, Methods: POST
Route: /score, Methods: POST
Route: /v1/score, Methods: POST
Route: /v1/audio/transcriptions, Methods: POST
Route: /rerank, Methods: POST
Route: /v1/rerank, Methods: POST
Route: /v2/rerank, Methods: POST
Route: /invocations, Methods: POST