老牛同学在前面文章中,介绍了不同大模型的部署和推理方式。有网友给老牛同学留言,希望老牛同学能写一篇使用 vLLM 通过 CPU 和 GPU 推理 Qwen2 等大语言模型的文章,老牛同学决定本期安排起来。
由于vLLM默认并不支持 CPU 部署和推理,为了验证和演示CPU部署和推理过程,老牛同学肝了周六 1 个晚上和周日大半天,目前都成功了。因vLLM通过CPU部署推理的文档少之又少,官网有些地方也不是很明确,导致老牛同学在执行过程中走了不少弯路。因此,老牛同学希望通过本文,能帮助大家避免踩坑和走弯路。
通过本文,老牛同学将介绍vLLM的 3 部分内容:
vLLM 官网源代码地址:https://github.com/vllm-project/vllm
vLLM 支持目前主流大模型,详细列表见官网:https://docs.vllm.ai/en/latest/models/supported_models.html
Qwen2 系列大模型在vLLM支持大模型之列,本文将详细介绍通过vLLM部署和推理Qwen2-0.5B大语言模型(之所以选择0.5B小尺寸模型,纯粹下载更快、演示更方便,其他vLLM所支持的所有大模型,其部署和推理过程完全一样,大家可以根据自己的需要选择不同的模型)
特别注意的是:vLLM目前只支持Linux操作系统(包括Windows WSL子系统),因此环境准备分为 2 部分:
Linux/Windows WSL系统,我们可以通过命令行完成安装:
mkdir -p ~/miniconda3
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh
Shell 上下文激活Miniconda相关命令:
~/miniconda3/bin/conda init bash
~/miniconda3/bin/conda init zsh
source /home/obullxl/.bashrc
source /home/obullxl/.zshrc
配置镜像是为了提升依赖包下载速度,老牛同学强烈建议进行配置。
Miniconda配置文件路径:~/.condarc,一般情况下配置文件不存在,我们可以创建并初始化它:conda config --set show_channel_urls yes
然后打开配置文件,设置依赖包镜像渠道:
show_channel_urls: true
channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- defaults
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
保存配置文件,我可以查看配置是否生效:conda info

接下来,我们通过Minicodan安装 Python 虚拟环境:conda create --name vLLM python=3.10 -y
虚拟环境安装完成之后,我们激活环境:conda activate vLLM
特别注意:Python 版本号建议为3.10,老牛同学刚开始使用3.12后续过程出现不兼容问题!
接下来,我们下载Qwen2大模型权重文件,共有 3 种方式:Git 下载、SDK 下载、命令行下载(推荐:Git方式)
我们将通过Git下载权重文件,因此先检测一下Git是否安装:git
若没有安装,则通过命令进行安装:sudo apt-get install git
如果想更新Git版本,则可执行命令:sudo apt-get update
同时,Qwen2模型权重文件比较大,我们需要用到 Git 大文件系统,因此需要提前安装好:
sudo apt-get install git-lfs
Git准备就绪,我们开始下载模型权重文件到本地(老牛同学目录:/home/obullxl/ModelSpace/Qwen2-0.5B):
# 创建目录
mkdir -p ~/ModelSpace && cd ~/ModelSpace
# 下载文件
git lfs install
git clone https://www.modelscope.cn/qwen/qwen2-0.5b.git Qwen2-0.5B
下载过程中,如果因网络等原因中断,我们可以继续断点下载:
cd ~/ModelSpace/Qwen2-0.5B
git lfs pull`
下载成功之后,我们可以看到Qwen2的模型权重文件列表:

当然,我们还可以通过以下 2 种方式下载模型权重文件:
pip install modelscope
from modelscope import snapshot_download
model_dir = snapshot_download('qwen/qwen2-0.5b')
pip install modelscope
modelscope download --model qwen/qwen2-0.5b
特别注意:vLLM的依赖包默认支持 GPU 部署和推理,如果使用CPU推理,我们需要根据vLLM源代码重新编译打包!
【GPU 部署和推理】比较简单,通过 PIP 直接安装依赖包即可:
pip install vLLM
【CPU 部署和推理】我们需要下载vLLM源代码,自己编译打包和安装:
首先,下载vLLM源代码(老牛同学目录:~/CodeSpace/vllm-project):
mkdir -p ~/CodeSpace
cd ~/CodeSpace
git clone https://github.com/vllm-project/vllm.git vllm-project
然后,我们安装源代码GCC 编译器:
sudo apt-get update -y
sudo apt-get install -y gcc-12 g++-12 libnuma-dev
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 10 --slave /usr/bin/g++ g++ /usr/bin/g++-12
接下来,我们需要安装vLLM便于打包的依赖:
cd ~/CodeSpace/vllm-project
pip install --upgrade pip
pip install wheel packaging ninja "setuptools>=49.4.0" numpy
pip install -v -r requirements-cpu.txt --extra-index-url https://download.pytorch.org/whl/cpu
最后,我们可以进行vLLM打包安装了:
cd ~/CodeSpace/vllm-project
VLLM_TARGET_DEVICE=cpu python setup.py install
vLLM打包安装完成,我们就可以开始对Qwen2大模型进行部署和推理了:
# Qwen2-vLLM-Local.py
import os
from transformers import AutoTokenizer
from vllm import LLM, SamplingParams
# 设置环境变量
os.environ['VLLM_TARGET_DEVICE'] = 'cpu'
# 模型ID:我们下载的模型权重文件目录
model_dir = '/home/obullxl/ModelSpace/Qwen2-0.5B'
# Tokenizer初始化
tokenizer = AutoTokenizer.from_pretrained(
model_dir,
local_files_only=True,
)
# Prompt提示词
messages = [
{'role': 'system', 'content': 'You are a helpful assistant.'},
{'role': 'user', 'content': '天空为什么是蓝色的?'}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
# 初始化大语言模型
llm = LLM(
model=model_dir,
tensor_parallel_size=1, # CPU无需张量并行
device='cpu',
)
# 超参数:最多512个Token
sampling_params = SamplingParams(temperature=0.7, top_p=0.8, repetition_penalty=1.05, max_tokens=512)
# 模型推理输出
outputs = llm.generate([text], sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f'Prompt提示词: {prompt!r}, 大模型推理输出: {generated_text!r}')

本地部署推理只能在一台服务器完成,我们也通过vLLM把本地大模型部署成 OpenAI API 服务:
python -m vllm.entrypoints.openai.api_server --model ~/ModelSpace/Qwen2-0.5B
默认情况下,API 服务端口为8000,我们可通过 --port 参数设置服务端口;同时,可通过--host 参数设置服务地址:
python -m vllm.entrypoints.openai.api_server --model /home/obullxl/ModelSpace/Qwen2-0.5B --port 8000 --host 0.0.0.0
API 服务部署成功之后,可以通过 CURL 命令验证服务:
# Qwen2-vLLM-CURL.py
curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "/home/obullxl/ModelSpace/Qwen2-0.5B",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "天空为什么是蓝色的?"}
],
"temperature": 0.7,
"top_p": 0.8,
"repetition_penalty": 1.05,
"max_tokens": 512
}'

或者,我们可以通过 Python 客户端调用API 访问服务:
若没有安装openai依赖包,需要提前安装一下:pip install openai
# Qwen2-vLLM-OpenAI.py
from openai import OpenAI
# OpenAI初始化
client = OpenAI(
api_key='EMPTY',
base_url='http://localhost:8000/v1',
)
chat_response = client.chat.completions.create(
model='/home/obullxl/ModelSpace/Qwen2-0.5B',
messages=[
{'role': 'system', 'content': 'You are a helpful assistant.'},
{'role': 'user', 'content': '天空为什么是蓝色的?'},
],
temperature=0.7,
top_p=0.8,
max_tokens=512,
)
print('Qwen2推理结果:', chat_response)

我们还可以通过 WebUI 访问我们部署的 API 服务:
pip install gradio
# Qwen2-vLLM-WebUI.py
import argparse
import json
import gradio as gr
import requests
def http_bot(prompt):
headers = {"User-Agent": "vLLM Client"}
pload = {
"prompt": prompt,
"stream": True,
"max_tokens": 128,
}
response = requests.post(args.model_url,
headers=headers,
json=pload,
stream=True)
for chunk in response.iter_lines(chunk_size=8192,
decode_unicode=False,
delimiter=b"
登录查看全部
参与评论
手机查看
返回顶部