← 返回首页
vLLM推理加速优化
发表时间:2025-05-04 10:35:10
vLLM推理加速优化

1.vLLM简介

‌vLLM(Very Large Language Model)是一个专为大语言模型(LLM)设计的开源框架,旨在优化推理速度、内存效率和吞吐量‌。vLLM由加州大学伯克利分校的Sky Computing Lab开发,采用了一种称为PagedAttention的创新机制,优化了kv-cache,大幅提高大模型的吞吐量,能够在多GPU环境下高效执行推理任务‌。

链接:https://docs.vllm.ai/en/latest/getting_started/quickstart.html

2.vLLM安装

pip install vllm==0.6.3.post1 -i https://pypi.tuna.tsinghua.edu.cn/simple

3.离线部署

默认情况下,vLLM 从 HuggingFace 下载模型。如果要使用 ModelScope 中的模型,请在初始化引擎之前设置环境变量。VLLM_USE_MODELSCOPE。

export VLLM_USE_MODELSCOPE=True
from vllm import LLM, SamplingParams
from transformers import AutoTokenizer
import time

# 实例化一个分词对象
tokenizer = AutoTokenizer.from_pretrained("models/Qwen/Qwen2___5-0___5B-Instruct", trust_remote_code=True)

# 定义文本输出的参数
sp = SamplingParams(temperature=0.5, top_p=0.5, repetition_penalty=1.05, max_tokens=4096)

# 实例化大模型
llm = LLM(model="models/Qwen/Qwen2___5-0___5B-Instruct", trust_remote_code=True)

prompt = "请讲一下周幽王烽火戏诸侯的故事。"
# 定义messages
messages = [
    {"role": "system", "content": "你是一个有用的助手。"},
    {"role": "user", "content": prompt}
    ]

# 使用分词器进行应用对话模板
text = tokenizer.apply_chat_template(
    messages, 
    tokenize=False,
    add_generation_prompt=True
)

# 记录开始时间
start_time = time.time()

outputs = llm.generate([text], sampling_params=sp)

# 记录结束时间
end_time = time.time()
# 计算生成时间
generate_time = end_time - start_time

for output in outputs:
    print(output.outputs[0].text)

# 计算每秒生成tokens的数量
generate_text= output.outputs[0].text
generate_tokens_num = len(tokenizer.tokenize(generate_text))
tokens_per_second = generate_tokens_num / generate_time

print(f"tokens per second: {tokens_per_second}")

运行效果:

Processed prompts: 100%|███████████████████████████████████████████████| 1/1 [00:00<00:00,  2.77it/s, est. speed input: 83.03 toks/s, output: 243.54 toks/s]
《周幽王烽火戏诸侯》是西汉时期刘向编著的《战国策·秦策一》中的一个故事,讲述了西周时期周幽王为了庆祝自己的胜利,下令烽火戏诸侯,诸侯们纷纷前来观看,结果导致了诸侯国之间的战争。这个故事反映了西周时期诸侯之间的矛盾和冲突,以及周幽王对诸侯的不信任和偏见。
tokens per second: 238.84025976916098

4.token生成速度对比

4.1 使用Transformers库进行模型部署与推理

import torch
import time
# 导入transformers库中的AutoModelForCausalLM(用于因果语言模型)和AutoTokenizer(自动化的分词工具)。
from transformers import AutoModelForCausalLM, AutoTokenizer

# 检查是否有可用的CUDA设备(即NVIDIA GPU),如果有,则设置为使用GPU,否则使用CPU。
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
# 使用预训练模型Qwen2.5-7B的分词器实例化tokenizer对象。
tokenizer = AutoTokenizer.from_pretrained("models/Qwen/Qwen2___5-0___5B-Instruct")
# 实例化一个预训练的因果语言模型,并将其移动到指定的device上执行。
model = AutoModelForCausalLM.from_pretrained("models/Qwen/Qwen2___5-0___5B-Instruct", torch_dtype=torch.float16).to(device)
# 设置对话的提示词。
prompt = "讲下周幽王烽火戏诸侯的故事"
# 定义对话历史,包括系统信息(指示助手的角色)和用户输入的提示。
messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt}
]
# 使用分词器将对话历史转换为适用于模型输入的格式,并添加生成提示。
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)

# 对输入文本进行分词处理,并转换为PyTorch张量格式,然后移动到指定的device上执行。
model_inputs = tokenizer([text], return_tensors="pt").to(device)

# 记录开始时间
start_time = time.time()

# 使用模型生成新的token序列,最大生成新的token数量为512。
generated_ids = model.generate(
    model_inputs.input_ids,
    max_new_tokens=4096,
)
# 记录结束时间
end_time = time.time()

# 计算生成时间
generate_time = end_time - start_time

# 截取生成的token序列,去除原始输入的部分。
generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]

# 计算生成的token的数量
generate_token_num = sum(len(ids) for ids in generated_ids)
# 计算每秒生成的token数量
token_per_second = generate_token_num / generate_time

# 将生成的token序列解码回文本,并忽略特殊token。
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

# 输出生成的响应文本。
print(response)
# 输出每秒生成token数量的结果
print(f"tokens per second: {token_per_second}")

运行效果:

在《三国演义》中,周瑜与诸葛亮一起参与了著名的“烽火戏诸侯”事件。这个故事发生在东汉末年,当时刘备、孙权和曹操都是主要的诸侯国。
具体来说,在一次战役中,刘备派出了一个名为周瑜的将领,率领自己的军队攻打曹军。然而,曹军却派出了一支精锐部队来阻止刘备的军队前进。在这一过程中,周瑜发现了一些埋伏,于是他命令士兵们用箭矢攻击这些敌人,但并没有射中他们的目标。结果,周瑜被箭矢射中,并因此而死于阵前。
这次事件成为了三国时期的一个重要转折点,它标志着刘备和诸葛亮之间的竞争更加激烈,也反映了他们在军事上的实力差距。
tokens per second: 45.731358394919724

5. OpenAI 兼容服务器部署

vLLM 可以部署为实现 OpenAI API 协议的服务器。这使得 vLLM 可以用作使用OpenAI API 的应用程序的直接替代品。 默认情况下,它在 启动服务器。您可以使用和 arguments 指定地址。该服务器目前一次托管一个模型,并实现列表模型、创建聊天完成和创建完成终端节点等终端节点。http://localhost:10222 --host --port。执行以下命令,启动模型为 Qwen2.5-7B-Instruct 的 vLLM 服务器。在家目录下,命令行输入。启动vllm服务,端口号默认为 10222。如果要后台,那么在命令行最后加上 &。

启动服务器命令:

python -m vllm.entrypoints.openai.api_server --port 10222 --model /root/autodl-tmp/DeployModelDemo/models/Qwen/Qwen2___5-0___5B-Instruct --served-model-name Qwen2___5-0___5B-Instruct

后台启动服务器命令:

python -m vllm.entrypoints.openai.api_server --port 10222 --model /root/autodl-tmp/DeployModelDemo/models/Qwen/Qwen2___5-0___5B-Instruct --served-model-name Qwen2___5-0___5B-Instruct &

出现以下界面说明,vLLM 推理服务器启动成功。

INFO:     Started server process [1521]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on socket ('0.0.0.0', 10222) (Press CTRL+C to quit)

参数详解:

  1. python -m vllm.entrypoints.openai.api_server python -m : 这是一个标准的 Python 命令,用于运行模块作为脚本。 -m 表示运行一个模块。 vllm.entrypoints.openai.api_server : 这是指定要运行的模块路径。vllm.entrypoints.openai.api_server 是 vllm 库中的一个模块,用于 启动一个 OpenAI API 服务器。
  2. --port 10222 --port : 这个参数用于指定服务器监听的端口号。 10222 : 这是你选择的端口号。客户端可以通过这个端口与服务器进行通信。例如,客户端可以发送 HTTP 请求到 http://localhost:10222。
  3. --model /root/autodl-tmp/DeployModelDemo/models/Qwen/Qwen25-05B-Instruct --model : 这个参数用于指定模型的路径。/root/autodl-tmp/DeployModelDemo/models/Qwen/Qwen25-05B-Instruct : 这是你本地存储的模型路径。服务器会加载这个路径下的模型进行推理。
  4. --served-model-name Qwen25-05B-Instruc --served-model-name : 这个参数用于指定模型在 API 中的名称。 Qwen25-05B-Instruc : 这是你给模型起的名字。当客户端通过 API 发送请求时,可以使用这个名字来指定要使用的模型。例如,客户端可以在请求中包含 "model": "Qwen25-05B-Instruc" 来指定使用这个模型。

用OpenAI接口脚本请求:

from openai import OpenAI

# API密钥,基础的URL
api_key = "EMPTY"
base_url = "http://127.0.0.1:10222/v1"

# 将上面定义的内容创建openai实例
client = OpenAI(api_key=api_key, base_url=base_url)

# 发送请求,流式输出
response = client.chat.completions.create(
    model="Qwen2___5-0___5B-Instruct",
    messages=[
        {"role": "system", "content": "你是一个有用的助手。"},
        {"role": "user", "content": "讲一个小红帽的故事。"}
    ],
    max_tokens=4096,
    temperature=0.5, 
    top_p=0.5,
    stream=True
)

for chunk in response:
    print(chunk.choices[0].delta.content,end='')

运行效果:

(AI_env) root@autodl-container-5fd24885db-13f1ee09:~/autodl-tmp/DeployModelDemo# python client.py
小红帽的故事是童话中的经典之一,讲述了一个勇敢的少女——小红帽,她为了保护自己的朋友,勇敢地去面对困难和危险。故事中,小红帽在森林中遇到了各种各样的困难,但她没有放弃,而是勇敢地面对,最终成功地保护了她的朋友。这个故事告诉我们,无论遇到什么困难,只要我们勇敢地面对,就一定能够成功。

如何杀死vllm进程?如果使用 & 了后台启动服务器,可以使用kill命令杀掉vllm进程,查看vllm的进程。

(AI_env) root@autodl-container/DeployModelDemo# ps -ef|grep vllm
root       1521   1331  6 19:43 pts/3    00:00:06 python -m vllm.entrypoints.openai.api_server --port 10222 --model /root/autodl-tmp/DeployModelDemo/models/Qwen/Qwen2___5-0___5B-Instruct --served-model-name Qwen2___5-0___5B-Instruct
root       2174   1824  0 19:44 pts/4    00:00:00 grep --color=auto vllm

杀死进程。

kill 1521