安装
下面的内容由 vLLM-Ascend 的文档整理而来。
物理机安装
物理机安装需要先安装驱动和 CANN,详细安装教程请见。
因为 torch-NPU 托管在华为云,所以我们需要增加额外的 pip 源:
pip config set global.extra-index-url "https://download.pytorch.org/whl/cpu/ https://mirrors.huaweicloud.com/ascend/repos/pypi"我们需要依次安装 vLLM 和 vLLM-Ascend,建议从源码安装:
# 安装 vLLM
git clone --depth 1 --branch v0.11.0rc3 https://github.com/vllm-project/vllm
VLLM_TARGET_DEVICE=empty pip install -v -e vllm
# 安装 vLLM-Ascend
pip install vllm-ascend==0.11.0rc0容器安装
如果觉得物理机安装太麻烦,可以使用构建好的容器。
虽然已有打包好的镜像可供使用,但如果想知道容器内包含什么内容,详细容器构建命令可见:
git clone https://github.com/vllm-project/vllm-ascend.git cd vllm-ascend docker build -t vllm-ascend-dev-image:latest -f ./Dockerfile .
可以使用下面的命令拉起容器:
export IMAGE=quay.io/ascend/vLLM-Ascend:v0.11.0rc0
export CONTAINER_NAME=vllm-test
docker run \
--name $CONTAINER_NAME \
--shm-size=128g \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /root/.cache:/root/.cache \
-it $IMAGE bash进入容器后,基本上不需要再做操作,如果运行的模型较新容器内 vLLM 版本不支持,可以先卸载 vLLM 和 vLLM-Ascend,然后再安装最新版本。
模型下载
可以从 Hugging Face、ModelScope 和 Modelers 获取模型。
在容器化环境中,系统默认将模型文件下载至 $HOME/.cache 目录。若 Docker 根目录分区存储容量不足,可能导致模型下载失败或容器运行异常。因此,强烈建议在下载前预先规划并指定专用的模型存储路径,确保系统稳定性和可维护性。
如使用 ModelScope 下载 Qwen/Qwen3-0.6B 模型到 /home/model_weights/Qwen3-0.6B:
modelscope download --model Qwen/Qwen3-0.6B --local_dir /home/model_weights/Qwen3-0.6B如使用 Hugging Face 下载 Qwen/Qwen3-0.6B 模型到 /home/model_weights/Qwen3-0.6B:
huggingface-cli download Qwen/Qwen3-0.6B --local-dir /home/model_weights/Qwen3-0.6B开始推理
vLLM 推理分离线推理和在线推理。
离线推理是指一次性处理输入数据,不需要保持与服务器的持久连接。这种方式通常用于批处理任务。
在线推理需要启动一个持续运行的服务端。服务端启动后,客户端可以通过 HTTP 请求(如 curl 或其他网络工具)发送推理请求并获取结果。
我们这里使用在线推理做演示。
API 格式支持
vLLM 支持多种 API 服务格式,其中最常用的是 OpenAI 兼容的 API 格式,便于与现有应用生态集成。
下面我们以最广泛使用的 OpenAI API 格式为例进行说明。
启动 API 服务器
使用以下命令启动最简的 API 服务:
vllm serve /home/model_weights/Qwen3-0.6B \
--served-model-name qwen \
--port 8002参数说明:
--served-model-name qwen: 设置服务暴露的模型名称--port 8002: 指定服务监听端口(默认 8000)
客户端调用示例
服务启动后,可以通过以下方式发送请求:
curl "http://localhost:8002/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen",
"messages": [{"role": "user", "content": "Hello, how are you?"}],
"temperature": 0.7,
"top_p": 0.9
}'下面对请求做一些说明:
API 端点类型
vLLM 提供了多种 OpenAI 兼容的 API 端点来满足不同的使用场景。我们这里主要使用聊天对话端点 /v1/chat/completions,这是最推荐的交互方式,因为它专门为对话场景设计,能够很好地处理上下文和角色扮演。
除此之外,vLLM 还提供了其他几个常用的端点:
- 补全端点 (
/v1/completions): 这是传统的文本生成方式,适合简单的文本续写任务; - 嵌入端点 (
/v1/embeddings): 拉起 embedding 模型后,用于将文本转换为向量表示,常用于语义搜索和相似度计算; - 模型端点 (
/v1/models): 可以查询当前服务加载了哪些模型。
Messages 格式
消息数组的设计使得我们可以轻松实现多轮对话。每个消息都包含一个角色(role)和内容(content),通过不同角色的组合,模型能够理解对话的上下文。
系统首先会看到 system 角色的消息,这相当于给模型设定一个角色或行为准则。然后模型会按照时间顺序阅读用户和助手的历史对话,最后根据最新的用户消息生成回复。这种设计让对话更加自然和连贯。
角色类型说明:
user代表用户的输入,这是模型需要回应的内容assistant记录模型之前的回复,帮助模型保持对话的一致性system用于设置系统级的指令,比如要求模型扮演特定角色或遵循某种回答风格
多轮对话示例:
"messages": [
{"role": "system", "content": "你是一个有帮助的助手"},
{"role": "user", "content": "请介绍一下人工智能"},
{"role": "assistant", "content": "人工智能是..."},
{"role": "user", "content": "能详细说说机器学习吗?"}
]常用参数
通过调整各种参数,我们可以精确控制模型生成文本的行为和风格。这些参数主要分为几类:
生成控制参数影响文本的生成过程和输出方式:
max_tokens限制生成文本的长度,防止输出过长temperature控制文本的创造性,温度越高输出越随机多变top_p采用核采样策略,只在概率最高的词中选择,平衡创造性和连贯性stream决定是否实时流式返回结果,提升用户体验
内容控制参数用于调整生成内容的特点:
frequency_penalty减少重复词语的出现,让文本更加丰富多样presence_penalty鼓励模型谈论新的话题,增加内容的广度stop设置停止词,让模型在特定位置停止生成,便于控制输出格式
性能和精度测试
现在市面上有多种多样的测试工具,vLLM 也有自己的 benchmark,我们这里使用 aisbench 来作性能和精度测试。
测试前准备
安装 aisbench
aisbench 使用源码安装的方式进行安装:
git clone https://gitee.com/aisbench/benchmark.git
cd benchmark/
pip3 install -e ./ --use-pep517下载 GSM8K 数据集
GSM8K 数据集可以使用 opencompass 提供的版本。
cd ais_bench/datasets
wget https://opencompass.oss-cn-shanghai.aliyuncs.com/datasets/data/gsm8k.zip
unzip gsm8k.zip性能测试
性能测试的关键在于对数据集长度的精确控制。
根据不同的测试需求,有时需要模拟固定长度的输入输出场景来测试模型的稳定性,有时则需要模拟可变长度的场景来验证模型的适应性。通过结合不同的并发请求数,我们可以全面评估模型在各种负载条件下的性能表现。
下面我们以固定 3500 输入,1500 输出,并发 32 作样例拉起性能测试。
制作定长数据集
由于现有的主流数据集输入长度不一,为了进行精确的性能测试,我们需要对这些原始数据进行预处理,通过截断的方式构建固定长度的测试数据集。
下面提供了一个实用的脚本来帮助您制作定长数据集。在使用时,请根据实际情况配置模型路径(脚本需要借助模型的分词器来精确计算 token 数量)以及所需的输入长度参数 input_len 还有数据集路径 dataset_path。注意,运行请备份原始 jsonl:
import json
from transformers import AutoTokenizer
# 使用实际的模型分词器
tokenizer = AutoTokenizer.from_pretrained(
"/home/model_weights/Qwen3-0.6B/"
)
batch_size = 2000 # 测试数据条数
input_len = 3500
dataset_path = "./ais_bench/datasets/gsm8k/test.jsonl" # 使用GSM8K测试集
dataset = []
with open(dataset_path, "r", encoding="utf-8") as f:
for line in f:
data = json.loads(line)
dataset.append(data["question"])
# repeat input_len
dataset_2k = []
for sentence in dataset:
words = tokenizer.tokenize(sentence)
print(len(words))
len_num = len(words) // input_len
if len_num == 0:
multiplier = (input_len // len(words)) + 1
repeated_len = words * multiplier
words = repeated_len[:input_len]
decoded_text = tokenizer.convert_tokens_to_string(words)
print(len(words))
dataset_2k.append(decoded_text)
# else:
# words = words[:input_len]
# merged_sentence = " ".join(words) # 合并
# print(len(words))
# dataset_2k.append(merged_sentence)
# repeat to batch_size
batch_num = len(dataset_2k) // batch_size
if batch_num == 0:
multiplier = (batch_size // len(dataset_2k)) + 1
repeated_batch = dataset_2k * multiplier
dataset_2k = repeated_batch[:batch_size]
else:
dataset_2k = dataset_2k[:batch_size]
print(len(dataset_2k))
json_str = json.dumps(dataset_2k, ensure_ascii=False, indent=4)
with open(f"GSM8K-in{input_len}-bs{batch_size}.jsonl", "w", encoding="utf-8") as f:
for i in range(len(dataset_2k)):
f.write(
json.dumps(
{"question": dataset_2k[i], "answer": "none"}, ensure_ascii=False
)
)
f.write("\n")同时需要确保模型配置文件正确(在 benchmark/ais_bench/benchmark/configs/models/vllm_api/vllm_api_stream_chat.py):
from ais_bench.benchmark.models import VLLMCustomAPIChatStream
from ais_bench.benchmark.utils.model_postprocessors import extract_non_reasoning_content
models = [
dict(
attr="service",
type=VLLMCustomAPIChatStream,
abbr='vllm-api-stream-chat',
path="/home/model_weights/Qwen3-0.6B", # 模型位置
model="qwen", # 拉起时的模型别名
request_rate = 0,
retry = 2,
host_ip = "localhost",
host_port = 8002, # 拉起时的端口
max_out_len = 1500, # 输出长度
batch_size=32, # 并发数
trust_remote_code=False,
generation_kwargs = dict(
temperature = 0.5,
top_k = 10,
top_p = 0.95,
seed = None,
repetition_penalty = 1.03,
),
pred_postprocessor=dict(type=extract_non_reasoning_content)
)
]vLLM 服务拉起后,可以用下面的命令发起性能测试:
ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str_perf --debug -m perf
精度测试
理论上,配置文件修改过后,可以直接用下面的命令拉起精度测试,但注意,数据集要用原始的 GSM8K 数据集,不要用我们前面测试性能的截断的数据集:
ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str --debug