目录
环境
qwen2.5-1.5b-instruct
模型下载
vllm 安装
验证安装
vllm 启动
查看当前模型列表
OpenAI Completions API(文本生成)
OpenAI Chat Completions API(chat 对话)
vllm 进程查看,kill
llama3
deepseek-蒸馏版 qwen
环境
Name: vllm
Version: 0.7.3
Name: torch
Version: 2.5.1
Name: transformers
Version: 4.49.0
cuda:V100-32GB
Version:12.1
qwen2.5-1.5b-instruct
模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen2.5-1.5B-Instruct', cache_dir='/root/autodl-tmp/')
cache_dir 保存路径
vllm 安装
直接 pip 即可
pip install vllm
验证安装
安装好 vllm,下载好模型后,可以用以下代码试下 vllm 推理,如果正常会有运行结果
import os
import warnings
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
warnings.filterwarnings('ignore')from transformers import AutoTokenizer
from vllm import LLM, SamplingParams
import pandas as pd
import timeclass vllmModel():def __init__(self, model_path, temperature=0.1, max_tokens=4096, tp_size=1):"""model_path: 模型路径temperature: 温度max_tokens: 模型最大输出 tokentp_size: gpu 数量,可以为 1 张卡卡,多余一张卡,必须是双数,如 2,4,6"""print(f'加载本地模型:{model_path}')self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)self.llm = LLM(model=model_path,tensor_parallel_size=tp_size,max_model_len=4096,trust_remote_code=True,enforce_eager=True,dtype="float16",# 如果遇见 OOM 现象,建议开启下述参数# enable_chunked_prefill=True,# max_num_batched_tokens=8192)self.sampling_params = SamplingParams(temperature=temperature, max_tokens=max_tokens)print("模型加载完毕")def infer(self, prompts):"""prompts: prompt 列表"""prompts = [{"role": "user", "content": prompt} for prompt in prompts]inputs = []for prompt in prompts:_input = self.tokenizer.apply_chat_template([prompt], tokenize=False, add_generation_prompt=True)inputs.append(_input)outputs = self.llm.generate(prompts=inputs, sampling_params=self.sampling_params)result = []for output in outputs:text = output.outputs[0].textresult.append(text)return result# 加载模型
model_path = "/root/autodl-tmp/Qwen/Qwen2___5-1___5B-Instruct/"
llm = vllmModel(model_path)# infer
print(llm.infer(['你好', '你能做什么?']))
vllm 启动
qwen2.5 兼容 openai 的 api 服务,可以用一下命令启动:
VLLM_WORKER_MULTIPROC_METHOD=spawn \
vllm serve /root/autodl-tmp/Qwen/Qwen2___5-1___5B-Instruct \
--trust-remote-code \
--served-model-name qwen2_5_1_5 \
--gpu-memory-utilization 0.2 \
--tensor-parallel-size 1 \
--port 8000 \
--dtype=half
--dtype=half 跟 gpu 有关,因为我报错了,提示加这参数,是精度
--port 8000 开启端口为 8000
--trust-remote-code 允许执行远程代码
--served-model-name qwen2_5_1_5 模型名称定义,不是模型路径
--gpu-memory-utilization 0.2 gpu 显存占用,如果太高,我最开始 0.98,调用会崩掉
--tensor-parallel-size 1 使用 gpu 的数量
serve /root/autodl-tmp/Qwen/Qwen2___5-1___5B-Instruct 模型加载路径
--quantization awq 如果部署量化模型,即模型后缀为 AWQ,需要加上
vllm_use_v1=1 写在最开头,代表境变量为 1
,表示你希望使用 vLLM 的 V1 API 版本。这通常涉及到API的设计,这个参数加上了,我这里不仅掉不通,一调就挂了,或者没多久也会自己挂,所以去掉
VLLM_WORKER_MULTIPROC_METHOD=spawn 写在最开头
这个变量指定在多进程模式下,worker(工作进程)启动的方法。在这个例子中,值被设置为 spawn
。在Python的multiprocessing模块中有多种方法可以创建新进程,其中包括fork
、spawn
和forkserver
。spawn
方法意味着每个新的进程都是通过启动一个全新的Python解释器实例来创建的。这种方法相较于fork
更加安全,尤其是在使用非Unix平台(如Windows)时,因为fork
可能会导致一些问题,比如子进程继承了父进程的所有资源,可能导致死锁或其他意外行为。
--max_model_len 4096 模型能够处理的最大序列长度(以token为单位),显存不够报错了,可以调小
CUDA_VISIBLE_DEVICES=0,2 写在最开头,指定使用哪张 gpu,这里是第 1,3 卡
启动成功会显示如下:
查看当前模型列表
curl http://localhost:8000/v1/models
{"object": "list","data": [{"id": "qwen2_5_1_5","object": "model","created": 1740235117,"owned_by": "vllm","root": "/root/autodl-tmp/Qwen/Qwen2___5-1___5B-Instruct","parent": null,"max_model_len": 32768,"permission": [{"id": "modelperm-514811fdf7464bc9bbd72db39850ef49","object": "model_permission","created": 1740235117,"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}]}]
}
OpenAI Completions API(文本生成)
一般指文本生成类的使用,非 chat,即非对话的使用方式
curl http://localhost:8000/v1/completions \-H "Content-Type: application/json" \-d '{"model": "qwen2_5_1_5","prompt": "你好,你是?","max_tokens": 2048,"temperature": 0.7,"top_p": 0.8,"repetition_penalty": 1.05}'
加 repetition_penalty 之前,会有很多重复:
加之后:
"max_tokens": 2048, 生成文本的最大长度(以token为单位)
"temperature": 0.7, 生成文本的随机性,值越小,创造能力越强,输出更加多样,适合创造场景
"top_p": 0.8, 核采样,类似温度,
"repetition_penalty": 1.05 用来减少重复词语出现的一个调节器。当其值大于1时(例如这里的 repetition_penalty: 1.05
),会降低之前已经出现在生成文本中的词语被再次选中的概率。这有助于提高生成文本的新颖性,避免不必要的重复
{"id": "cmpl-adb0ffa50a1142a1880620126e341a70","object": "text_completion","created": 1740236869,"model": "qwen2_5_1_5","choices": [{"index": 0,"text": " 答案:我是小明。 A. 错误 B. 正确\nA. 错误\n\n解析:\"我是小明\"是一个常见的自我介绍,但它并不一定正确,因为每个人在回答\"你是谁\"的问题时,通常会提供自己真实的姓名或名字。\"小明\"可能是一个昵称或别名,这取决。。。。。。。。。。。。。。。。。。。","logprobs": null,"finish_reason": "length","stop_reason": null,"prompt_logprobs": null}],"usage": {"prompt_tokens": 4,"total_tokens": 2052,"completion_tokens": 2048,"prompt_tokens_details": null}
}
python openai 接口:
from openai import OpenAI# 设置 OpenAI 的 API key 和 API base 来使用 vLLM 的 API server.
openai_api_key = "EMPTY" # 如果不需要 API key,可以留空或设置为 "EMPTY"
openai_api_base = "http://localhost:8000/v1"client = OpenAI(api_key=openai_api_key,base_url=openai_api_base,
)# 创建 Completion 请求
completion_response = client.completions.create(model="qwen2_5_1_5",prompt="你好,你是?",max_tokens=2048,temperature=0.7,top_p=0.8,# 注意:OpenAI Python 客户端可能不直接支持 repetition_penalty,需要确认服务是否接受额外参数extra_body={"repetition_penalty": 1.05},
)# 检查响应并打印结果
if hasattr(completion_response, 'choices') and len(completion_response.choices) > 0:print("成功获取数据:")print(completion_response.choices[0].text)
else:print(f"请求失败,响应内容:{completion_response}")
python vllm 接口
import requests
import json# 设置请求的URL
url = "http://localhost:8000/v1/completions"# 设置请求头部
headers = {"Content-Type": "application/json"
}# 准备请求数据
data = {"model": "qwen2_5_1_5","prompt": "你好,你是?","max_tokens": 2048,"temperature": 0.7,"top_p": 0.8,"repetition_penalty": 1.05
}# 发送POST请求
response = requests.post(url, headers=headers, data=json.dumps(data))# 检查响应状态并打印结果
if response.status_code == 200:try:# 尝试解析响应中的 'choices' 字段,并获取生成的文本choices = response.json().get('choices', [])if choices:print("成功获取数据:")# 注意这里的 'text' 字段可能需要根据实际API响应结构调整print(choices[0].get('text', ''))else:print("没有获取到任何选择结果")except json.JSONDecodeError:print("无法解析JSON响应")
else:print(f"请求失败,状态码:{response.status_code}, 响应内容:{response.text}")
OpenAI Chat Completions API(chat 对话)
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "qwen2_5_1_5","messages": [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "你好,你是?"}],"temperature": 0.7,"top_p": 0.8,"repetition_penalty": 1.05,"max_tokens": 2048
}'
{"id": "chatcmpl-189df22813aa4b358e795596f0e2c420","object": "chat.completion","created": 1740238345,"model": "qwen2_5_1_5","choices": [{"index": 0,"message": {"role": "assistant","reasoning_content": null,"content": "你好!我是阿里云开发的一款语言模型,我叫通义千问。","tool_calls": []},"logprobs": null,"finish_reason": "stop","stop_reason": null}],"usage": {"prompt_tokens": 33,"total_tokens": 51,"completion_tokens": 18,"prompt_tokens_details": null},"prompt_logprobs": null
}
python 代码 openai 接口
from openai import OpenAI# 设置 OpenAI 的 API key 和 API base 来使用 vLLM 的 API server.
openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8000/v1"client = OpenAI(api_key=openai_api_key,base_url=openai_api_base,
)chat_response = client.chat.completions.create(model="qwen2_5_1_5",messages=[{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "你是谁?"},],temperature=0.7,top_p=0.8,max_tokens=512,extra_body={"repetition_penalty": 1.05,},
)# 直接访问响应对象的属性,而不是尝试调用 .json()
print("Chat response:", chat_response.choices[0].message.content)
python vllm 接口
import requests
import json# 设置API的基本URL和端点
base_url = "http://localhost:8000/v1"
endpoint = "/chat/completions"url = base_url + endpoint# 设置请求头部
headers = {"Content-Type": "application/json",
}# 准备请求数据
data = {"model": "qwen2_5_1_5","messages": [{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},{"role": "user", "content": "你是谁?"},],"temperature": 0.7,"top_p": 0.8,"max_tokens": 512,"repetition_penalty": 1.05, # 直接包含在请求体中
}# 发送POST请求
response = requests.post(url, headers=headers, data=json.dumps(data))# 检查响应状态并打印结果
if response.status_code == 200:print("Chat response:", response.json()['choices'][0]['message'])
else:print(f"请求失败,状态码:{response.status_code}, 响应内容:{response.text}")
vllm 进程查看,kill
ps aux | grep vllm
kill -9 6947
服务杀死了,但显存没释放
llama3
跟 qwen2.5 一样
deepseek-蒸馏版 qwen
vllm 启动需要加个参数 --enforce-eager
始终使用急切模式PyTorch,如果为False,则在混合模式下使用急切模式和CUDA图以获得最大性能和灵活性
vllm serve /root/autodl-tmp/deepseek-ai/DeepSeek-R1-Distill-Qwen-1___5B/ \
--trust-remote-code \
--served-model-name qwen2_5_1_5 \
--gpu-memory-utilization 0.7 \
--tensor-parallel-size 1 \
--max-model-len 32768 \
--dtype=half \
--enforce-eager
参数说明:VLLM参数解释-中文表格形式-CSDN博客
参考:
https://github.com/datawhalechina/self-llm/blob/master/models/Qwen2.5/03-Qwen2.5-7B-Instruct%20vLLM%20%E9%83%A8%E7%BD%B2%E8%B0%83%E7%94%A8.md
使用vLLM部署Qwen2.5-VL-7B-Instruct模型的详细指南_vllm qwen2.5-vl-CSDN博客
vLLM - Qwen