☰
VLLM部署Qwen与GLM大模型:从环境配置到推理调优全攻略
2026/10/21 14:18:45 网站建设 项目流程

最近在折腾大模型本地部署,前后试了好几套推理框架,最后稳稳落在一套组合上:用VLLM作为推理后端,部署Qwen、GLM这几个开源大模型。这篇文章就是把这段时间踩过的坑、调过的参、验证过的方案,一次性整理出来。

如果你正准备在自己的服务器上跑一个能对外提供API服务的开源大模型,或者想搞清楚VLLM到底怎么用、为什么社区里这么多人推它,那这篇应该能帮你省掉不少弯路。我尽量把从环境准备、模型选型、启动配置到性能调优、问题排障的完整链路讲清楚,适合有一定Linux和Python基础、但对大模型推理部署还不太熟的开发者参考。

1. 部署方案与模型选型思路

1.1 推理框架选型:为什么最后选了VLLM

大模型推理框架目前可选的不算少,比如最常见的HuggingFace Transformers原生加载、FasterTransformer、TGI(Text Generation Inference)、TensorRT-LLM,以及后来居上的VLLM。如果只是追求“能跑起来”,用Transformers写个脚本其实几分钟就能出demo,但问题在于它吃显存太狠、并发能力太弱。一次推理占满整卡,请求一多就排队,在实际工程场景里基本不可用。

VLLM的核心优势在于两件事:PagedAttention和Continuous Batching。PagedAttention借鉴了操作系统虚拟内存的分页思想,把KV Cache拆成固定大小的块来管理,减少显存碎片,理论上能把显存利用率拉高很多。Continuous Batching则解决了传统静态批处理“一个批次必须全部完成后才能处理下一批”的低效问题,让请求动态进出批次,吞吐量提升非常明显。实测下来,同样一张卡,用Transformers可能只能同时处理几个请求,换成VLLM之后并发稳定到几十路没有太大压力。

另外,VLLM的安装和部署足够简单。它提供了一个OpenAI兼容的API服务,起一个服务端,业务侧几乎照抄OpenAI SDK就能接入,不用为每个模型写一套推理代码。这种“低改造迁移”的特性,是选它的一个重要加分项。

1.2 模型选择维度的拆解

部署目标如果是给业务提供通用对话能力,Qwen和GLM都是很合适的选择。它们官方提供了多种参数规模的版本,从几十亿参数到几百亿参数的都有。选型主要看三个维度。

第一是效果底线。中文场景下,Qwen和GLM都是国内开源社区里中文能力表现靠前的模型,日常问答、信息抽取、文本改写这类任务完全能胜任。

第二是硬件边界。这部分是最实际的约束,显存大小直接决定了你能跑什么参数量的模型。一张24G显存的卡,跑7B~14B量级、4bit量化后的模型比较舒服;如果要上70B量级模型,基本得考虑多卡张量并行。

第三是推理效率。同参数量下,不同系列的模型结构有差异,实际吞吐量也会有明显区别。这也解释了为什么部署时要先测模型、再定框架,而不是反过来。

为了便于决策,我习惯把模型、显存、精度粗略对应起来,如下表所示(这是常见经验的参考值,具体以实测为准)。

参数量级精度预计显存占用可运行的典型情况
7B~8BBF1616G~18G24G单卡可跑,留余量给KV Cache
7B~8BAWQ 4bit6G~8G20G以上显存均可流畅运行
14BBF1628G~32G32G单卡勉强,建议多卡
14BAWQ 4bit10G~12G24G单卡比较充裕
32B~72BAWQ 4bit24G~40G+建议双卡或以上张量并行

注意:显存占用不仅包括模型权重,还包括推理过程中动态增长的KV Cache。部署时不能只算权重大小,否则一跑长文本就直接OOM。

2. 环境准备与依赖安装

2.1 GPU驱动与基础环境的检查清单

在安装VLLM之前,先确认一下机器的基础环境。这步看似简单,但很多人装了半天装不上,最后发现是CUDA版本和驱动对不上。

建议按顺序检查:

  1. 操作系统版本。Ubuntu 20.04和22.04是我用得比较稳的。CentOS和Debian也能装,但会遇到一些系统库缺失的额外问题。
  2. GPU驱动。执行nvidia-smi确认驱动已安装,且版本不能太老。
  3. CUDA版本。VLLM依赖PyTorch的CUDA运行时。不需要单独装完整CUDA Toolkit,但如果有独立安装的CUDA,务必让nvcc -V和nvidia-smi里的驱动版本文档能够相互兼容。
  4. Python版本。3.10是目前兼容性最稳的选择。

如果跑nvidia-smi正常但VLLM启动时提示找不到CUDA,大概率是PyTorch的CUDA版本和驱动不匹配,优先升级驱动而不是去折腾旧的运行库了。

2.2 VLLM安装与多版本兼容问题的规避方式

VLLM的版本更新速度很快,不同版本对CUDA、PyTorch甚至GPU架构的适配要求都不一样。最省事的方式是创建一个干净的conda环境,然后用pip按版本安装。

实际用下来,这类部署最稳的组合是:

conda create -n vllm python=3.10 -y conda activate vllm # 安装指定版本的vllm pip install vllm==0.6.3

为什么强调指定版本?因为直接pip install vllm拉最新版,往往需要配套更新PyTorch、transformers等一堆依赖库,容易把环境搞乱。毕竟部署环境里往往还跑着其他训练任务,贸然升级全局的PyTorch会让项目间互相打架。就我个人而言,用固定版本号加独立conda环境,出问题的概率小很多。

装完之后,先跑一次Python导入验证,避免用起来才发现问题:

python -c "import vllm; print(vllm.__version__)"

如果报缺少libcuda.so之类的错误,一般路径是确认CUDA运行库和驱动版本,而不是重装VLLM本身。

2.3 模型权重获取与本地化存储

模型下载是部署流程里最容易被忽视的一环。Qwen和GLM系列模型体积都不小,7B级别的模型光权重就有十几个G,下载时间取决于带宽。

下载时有几个建议:

  • 优先从国内可稳定访问的模型仓库下载,选国内镜像渠道(modelscope是个比较省心的选择)。
  • 把模型统一放在一个独立的模型目录里,比如/data/models,方便后续多个服务复用。
  • 下载完成后,确认目录里包含config.json、tokenizer.json和权重文件。如果权重文件不完整,VLLM启动时会直接报错。

以Qwen为例,下载后目录结构大致如下:

/data/models/Qwen2.5-7B-Instruct ├── config.json ├── generation_config.json ├── merges.txt ├── model-00001-of-00002.safetensors ├── model-00002-of-00002.safetensors ├── model.safetensors.index.json ├── tokenizer.json ├── tokenizer_config.json └── vocab.json

提示:不同模型仓库拉下来的文件可能略有差异,但只要包含config.json、tokenizer文件、权重文件这三类核心文件,一般都能正常加载。

3. VLLM核心配置与服务启动

3.1 OpenAI兼容API服务启动参数解析

VLLM用得最多的方式就是启动OpenAI兼容的API Server。一条命令把服务端跑起来,业务侧就可以像调用OpenAI接口一样调用本地模型。下面这条命令是我常用的基础启动模版:

python -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen2.5-7B-Instruct \ --served-model-name qwen7b \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.9 \ --max-model-len 32768 \ --dtype bfloat16 \ --host 0.0.0.0 \ --port 8000

这里面的几个参数非常关键。

--model指定模型路径。可以传本地路径,也可以传模型仓库的模型ID。传本地路径的优点是不依赖网络,启动更快更稳定。

--served-model-name用来给本地模型起一个对外名称。这个名称会出现在API的model字段里。业务侧请求时可以自由选择,起到别名的作用,很实用。

--tensor-parallel-size是张量并行数。单卡设为1,多卡设为卡数。设置为2时会自动做跨卡模型切分,显存和计算压力分摊到两张卡上。这里要注意的是,并行数必须能被模型注意力头数等结构整除,否则启动会阶段性地报维度错误。

--gpu-memory-utilization是显存利用率上限。设成0.9意味着允许VLLM最多占用90%的显存,留出一部分余量给模型加载和其他进程。对于24G单卡跑7B模型,建议设为0.9或0.95,既保证KV Cache空间,又不至于完全打满导致其他任务OOM。

--max-model-len是模型支持的最大上下文长度。这个参数直接影响KV Cache的预分配策略。设得越大,显存预留越多,能处理的超长文本也越多。但如果设得超过模型本身训练长度,超出部分生成的文本质量会急剧下降,这需要额外留意。一般按模型原生的上下文长度设置即可。

--dtype bfloat16表示用BF16精度推理。现在主流新显卡对BF16支持很好,数值稳定性比FP16更好。如果是老显卡不支持BF16,可以改成--dtype float16。

3.2 并发和性能关键参数的配置经验

除了启动基本参数,还有几个和并发性能直接相关的参数,实际调整时很考验经验。

--max-num-seqs是单个批次最多容纳的序列数。PagedAttention和Continuous Batching让多个请求共享同一个批次,这样可以尽可能占满算力。设得太小,并发提升不上去;设得太大,大批次下每个请求的响应时延会明显上升。对于7B模型配24G显存,我通常设在64到128之间。

--max-num-batched-tokens控制每个批次最多的tokens数量。VLLM每步推理前会从等待队列里取出符合条件的请求来组batch,这个参数限制了单步送入GPU的最大总token数。设得过大可能超显存,设得过小吞吐上不去。参考策略是先保持默认真跑几个压测请求,再根据显存余量和响应延迟微调。

--kv-cache-dtype在某些新版本里可以设成fp8,能进一步省显存。但对未经过充分验证的模型,精度上可能存在波动,谨慎开启。

另外一个容易被忽略的参数是--trust-remote-code。部分模型架构需要加载模块来自定义代码,没有这个参数启动时会出现加载中断这类问题。如果模型仓库里带了非标准Python类的建模文件,启动命令里记得加上:

--trust-remote-code

3.3 多卡部署时的并行策略调优

当单卡显存放不下模型时,就需要多卡部署,这时候部署思路会发生一点变化。

多卡部署主要分张量并行和流水线并行两种。VLLM目前用得最多的还是张量并行--tensor-parallel-size。它的核心是把模型的层内计算拆到多张卡上同时做。以一张14B模型为例,如果2张24G卡跑BF16精度,权重部分大约需要28G~32G。用2卡张量并行后,单卡只承担约一半权重,再叠加推理时的KV Cache,总体压力就降下来了。

多卡环境下要注意两点:

第一,卡与卡之间的通信延迟影响很大。建议先看看机器里的GPU拓扑。如果两张卡不是走独立的PCIe通道或NVLink直连,通信会成为瓶颈,吞吐量可能不升反降。机器上的nvidia-smi topo -m命令可以直接看出来。

第二,gpu-memory-utilization参数在多卡下仍然按整卡算,不要单卡留太少。比如2张24G卡,各设0.92,实际可用就是22G左右每张,对KV Cache更友好。

4. 模型精度选择与显存优化

4.1 BF16、FP16还是量化

推理精度直接影响显存占用和效果,需要结合实际场景做取舍。

FP16和BF16都可以作为常规默认选项。BF16的指数位更多,数值表示范围更大,训练和推理中梯度以及中间激活值不容易溢出,所以如果显卡支持,我基本都先试BF16。

量化能显著降低显存和计算压力。当前主流方法是AWQ和GPTQ。以7B模型为例,BF16权重大约占14G,4bit量化后权重可压缩至5G左右,直接让24G卡变得非常宽裕。

但有一点要注意:量化后的模型输出质量会有轻微波动。在数学推理、代码生成这类对精确度敏感的任务上,差异可能比较明显。如果业务对生成质量要求高,建议保留一个BF16版本和一个量化版本分别压测对比。

4.2 KV Cache的显存分配逻辑

KV Cache是我觉得VLLM部署里最值得下功夫理解的概念。

大模型生成时,每生成一个token,都需要把之前所有token对应的Key和Value信息缓存下来。模型不是从头重新计算一遍历史内容,而是依赖这些缓存。也就是说,并发请求越多、上下文越长,KV Cache占的显存越大。

VLLM通过PagedAttention把KV Cache按固定大小分块,按需分配。同时显存利用率参数gpu-memory-utilization决定了VLLM把多大比例的显存预留给模型和KV Cache。如果模型权重占了许多空间,留给KV Cache的就少,并发和长文本能力就受影响。反过来,如果模型权重本身很小,KV Cache空间充足,就能开更高并发、支持更长的上下文。

启动时VLLM日志会打印KV Cache的当前分配情况,比如下面这样:

(GPUCacheManager) GPU available memory: 22.3 GiB (GPUCacheManager) Maximum KV cache size: 17.8 GiB

如果KV Cache过小导致并发上不去,可行的解决路径是:

  • 降模型精度,比如从BF16切换到4bit量化,给KV Cache腾地方。
  • 升gpu-memory-utilization。
  • 限制max-model-len,减少长上下文场景下的缓存压力。

4.3 实测显存配置参考

这里整理一份我在不同显存条件下跑7B模型的常用启动参数组合,供参考。

显存精度gpu-memory-utilizationmax-model-len备注
12GAWQ 4bit0.958192显存紧张,长文本受限
24GBF160.932768日常推荐组合
24GAWQ 4bit0.9565536长文本场景更充裕
32GBF160.965536更宽裕,适合大并发

这些组合能用,但不代表最优。最终还是要结合自己的请求长度、并发量、响应时间要求来调整。

5. 客户端调用与业务接入

5.1 用标准OpenAI SDK完成接入

VLLM的API Server启动后,默认在8000端口提供/v1路径的接口,完全兼容OpenAI接口规范。官方服务起来后,业务侧改动极小。以Python为例,只需要把base_url指向本地服务就行。

from openai import OpenAI client = OpenAI( api_key="EMPTY", base_url="http://127.0.0.1:8000/v1" ) response = client.chat.completions.create( model="qwen7b", messages=[ {"role": "system", "content": "你是一个专业的文字助理。"}, {"role": "user", "content": "请帮我整理一份本周工作总结提纲。"} ], temperature=0.7, max_tokens=1024, stream=False ) print(response.choices[0].message.content)

这里有几个小细节要说一下。

api_key随便填一个字符串就行。因为VLLM本地服务默认不做鉴权,只要非空即可,比如"EMPTY"。

model传的值必须和启动时--served-model-name保持一致。如果启动时没设这个参数,默认就是--model路径对应的模型名称。

stream参数可以按需开启。开启流式之后,用同一个客户端直接处理增量返回即可,响应体验更接近ChatGPT的打字机效果。对内部系统来说,流式和非流式都是值得做好的能力,不少业务场景其实偏好流式输出。

5.2 并发请求与流式输出的工程化体验

实际生产环境中,往往不会一个一个请求地串行访问。服务端一旦起了并发,就需要在客户端侧处理好连接池和超时参数。

OpenAI SDK本身支持多线程调用。高并发时建议复用同一个client对象,而不是每次请求新建一个连接。也可以配合HTTPClient自定义连接池大小。

流式输出的代码改动也很小:

stream = client.chat.completions.create( model="qwen7b", messages=messages, stream=True ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True)

实际使用中发现,VLLM在处理流式请求时首token延迟普遍较低。要注意的是,max_tokens一定要设置,防止模型生成陷入无限循环。对于本地部署模型,建议同时设置业务层的超时时间,这样接口出现异常时可以快速失败。

5.3 多模型共存的Namespace配置

VLLM支持在同一个服务里部署多个模型,通过--model参数传多个模型路径即可。这样一个服务可以对外提供Qwen、GLM等多个模型接口,业务侧按model字段自由选择,非常灵活。

python -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen2.5-7B-Instruct \ --model /data/models/GLM-4-9B-Chat \ --served-model-name qwen7b glm4-9b \ --tensor-parallel-size 1

不过要注意显存规划。多模型同时加载到显存,KV Cache的空间会被进一步压缩。如果请求并发较高,建议还是分开两个服务进程部署,避免互相争抢显卡资源。

6. 性能摸底与调优实战

6.1 吞吐指标怎么看

部署完成只是第一步,更重要的是确认服务能不能扛住业务流量。性能摸底我比较关注几个指标:

  • 吞吐量(Tokens/s):每秒生成的token数。这个数值直接反映整体处理能力。
  • 首Token延迟(TTFT):从请求发出到返回第一个token的时间。流式交互场景很看重这个。
  • 并发能力:同时稳定处理的请求数。

VLLM启动日志里自带了一些统计信息,调用接口之后也会输出模型的全部指标到日志。如果想要更精细的指标,可以用Prometheus+Grafana监控,也可以写一段压测脚本统计响应时延。

6.2 基于压测数据的参数调整流程

压测时我习惯用并发脚本模拟真实请求:不设固定QPS,而是同时发起N个请求,统计整体平均延迟和生成速度。之后根据结果调整参数。

如果发现某个压测结果吞吐量上不去,可调整项优先级一般是:

  1. 增大max-num-seqs,让单批次容纳更多请求。
  2. 提高gpu-memory-utilization,给KV Cache更多空间。
  3. 检查max-model-len是否远超实际请求长度,过大意味着KV Cache预分配浪费。
  4. 看请求数据里是否包含大量system提示词,这些也会占用上下文长度。
  5. 如果单卡仍然受限,考虑张量并行扩展到多卡。

实测中最容易忽略的是max-model-len。很多人启动时习惯把它设到模型支持的最大值,但业务场景往往只有几百到几千token。如果设为32768,每个请求KV Cache可能预留一大块空间,并发稍高就显存紧张。建议先根据业务实际请求长度设置,再动态调整。

6.3 生产可用性的经验清单

经过多次部署实验,我整理了一份面向生产环境的配置和经验清单:

  • 服务通过systemd进程守护托管,设置自动重启。
  • 启动命令保存在独立的配置文件中,避免人为修改和误操作。
  • 客户端设置连接超时和读超时,避免服务异常时业务侧长时间阻塞。
  • GPU卡上留足显存余量,不要gpu-memory-utilization=1.0,否则偶发的显存峰值会直接OOM。
  • 定期观察nvidia-smi的显存占用和温度。

7. 常见问题与排障实录

7.1 启动阶段典型报错排查

启动时的报错大多是环境或参数配置的问题,把最常见的列成了一个速查表。

报错现象常见原因解决办法
CUDA error: out of memory显存不足降低gpu-memory-utilization、缩小max-model-len、用量化模型
ValueError: tensor parallel size ...张量并行数不匹配模型结构调整并行数为模型可整除的数值
ModuleNotFoundError自定义模型代码未加载加--trust-remote-code
KeyError: 'qwen2'VLLM版本过旧,不支持新架构升级VLLM版本
启动后无法访问8000端口防火墙或绑定了127.0.0.1启动时--host 0.0.0.0,并检查防火墙端口

其中比较隐蔽的是第二种情况。不同模型的注意力头数不一样,把7B模型用--tensor-parallel-size 2跑在两张卡上,某些结构下会直接在启动时报错。建议多卡前先查清楚模型的head数目与并行数的整除关系。

7.2 运行期稳定性和显存泄漏排查

运行期最痛苦的问题是长时间服务后显存逐步增长,最终OOM或者请求变慢。遇到这类问题,我的排查步骤是:

先通过nvidia-smi观察显存曲线。如果VLLM进程的显存占用持续上涨,优先检查PyTorch缓存机制。正常情况下VLLM会复用显存,但如果某个请求走了不同的执行路径,可能触发新的显存分配。

再检查日志里是否有异常请求。某些超长文本请求可能触发了高显存水位,虽然不是泄漏,但会让显存占用看起来很高。

如果一切正常但显存仍持续上升,建议在显卡驱动和VLLM版本上寻找已知问题,并升级到相对较新的稳定版本。

7.3 输出质量异常的原因分析

有几次部署完发现生成内容明显变差:回答重复、逻辑混乱、甚至出现非中文乱码。排查下来主要有几个原因。

一是量化精度损失。AWQ/GPTQ这类4bit量化对敏感任务影响大,建议保留BF16版本做对比。

二是temperature等参数设置问题。本地模型和模型版本对参数敏感程度不一样,较低温度对于事实性任务更合适,过高的temperature会导致发散。

三是上下文窗口超限。如果max-model-len设得超过模型原生长度,模型虽然在窗内仍然能输出,但注意力可能严重失效,生成内容前后矛盾。

7.4 两个觉得特别值得说的细节

这些细节第一次部署时挺容易忽略,但影响又不小。

第一,模型目录里不要放多余的非模型文件。比如把下载脚本、说明文档和权重文件混在一个目录。VLLM加载时有时会自动扫描目录,多余文件可能导致加载失败或行为异常。

第二,served-model-name在模型启动时只需要写一次,客户端每次请求都要带着匹配的名称。如果启动后改了几次名称,各种旧客户端有可能会请求失败并残留内存,排查起来很头疼,不如一开始就定好命名规范。

8. 从单卡到多服务的扩展方向

部署跑通之后,通常很快会遇到扩容需求。这里分享几种扩展方向。

单卡升级是第一步。如果当前用24G卡跑7B模型,优先考虑换40G以上显存的卡或加卡做张量并行,能明显提升并发和上下文处理能力。

业务侧引入模型路由。现在很多团队在网关层维护一个模型注册表,把不同任务路由到不同模型。比如代码任务走Qwen,普通问答走GLM,控制成本的同时也能兼顾效果。

引入缓存层。对于高频常见问题,可以在服务和模型之间加一层语义缓存。相同或相似问题直接返回缓存结果,在大流量场景下能减少GPU压力的同时大幅降低响应延迟,是很实用的优化手段。

我的总体体验是:VLLM配合Qwen、GLM这套开源模型,基本上能以较低的成本构建一个稳定、可扩展的本地模型推理服务。任何部署都不是参数抄一遍就能收工的,建议拿到生产环境后,以自己的业务数据为样本,反复压测并观察显存和时延数据。部署踩坑不可怕,只要环境分明、参数可查、日志在案,问题基本都是可以被定位和解决的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询