一、环境部署

创建虚拟环境

conda create -n AI_env python=3.11.9

激活环境 

conda activate AI_env

安装依赖包  

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install vllm==0.6.3.post1 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install modelscope
pip install transformers

二、vllm进行推理加速优化

2.1、vllm介绍

        vllm是开源的大模型高速推理框架,引入了全新的的注意力算法PagedAttention, 优化了kv-cache,大幅提高大模型的吞吐量。

地址:Quickstart - vLLM

2.2、下载模型

魔塔社区:通义千问2.5-7B-Instruct · 模型库

#模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct')

默认安装在/root/.cache/modelscope/hub/models/Qwen/Qwen2.5-7B-Instruct

from modelscope.hub.snapshot_download import snapshot_download
llm_model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct',cache_dir='models')

 安装在当前目录下

1.3、离线部署 

导入模块包

from vllm import LLM,SamplingParams
from transformers import AutoTokenizer

 实例化一个分词对象

tokenizer=AutoTokenizer.from_pretrained('models/Qwen/Qwen2.5-7B-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-7B-Instruct',trust_remote_code=True)

 定义messages

prompt='请讲述一个周幽王的故事'

messages=[
    {'role':'system','content':'你是一个有用的助手'},
    {'role':'user','content':prompt}
]

 使用分词器进行应用对话模板

text=tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)

输出 

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

 打印结果

for output in outputs:
    print(output.outputs[0].text)
RequestOutput(request_id=0, prompt='<|im_start|>system\n你是一个有用的助手<|im_end|>\n<|im_start|>user\n请讲述一个周幽王的故事<|im_end|>\n<|im_start|>assistant\n', prompt_token_ids=[151644, 8948, 198, 56568, 101909, 115405, 110498, 151645, 198, 151644, 872, 198, 14880, 102881, 46944, 40542, 102517, 99445, 104413, 151645, 198, 151644, 77091, 198], encoder_prompt=None, encoder_prompt_token_ids=None, prompt_logprobs=None, outputs=[CompletionOutput(index=0, text='周幽王是西周的最后一个君主,他的统治时期被《史记》等历史文献记载为昏庸无道。下面是一个与周幽王有关的著名故事:\n\n周幽王有一个宠妃名叫褒姒,她美丽但性格冷酷。为了博得褒姒一笑,周幽王想出了一个办法。他下令在都城镐京(今陕西西安)设立烽火台,平时用来报警,一旦有敌情,就会点燃烽火,诸侯们会率领军队前来救援。然而,周幽王却在没有敌人入侵的情况下,多次点燃烽火,只为博取褒姒一笑。\n\n这个故事最著名的版本来自于《国语·周语上》,原文如下:“昔周之兴也,卜世三十,卜年七百。及幽王之世,荒淫无道,烽燧不修,戎狄内侵,四夷交攻,中国不绝若线。幽王之末,厉王之子宣王白于骊山之下,而秦人救之,因大兴师以伐戎狄,遂定天下。” \n\n这个故事后来演变成成语“烽火戏诸侯”,用来形容为了个人私欲而滥用权力、欺骗他人,最终导致国家或集体利益受损的行为。这个故事反映了周幽王的荒淫无度和对国家事务的忽视,最终导致了西周的灭亡。', token_ids=(40542, 102517, 99445, 20412, 60686, 40542, 9370, 113223, 101956, 35568, 3837, 100648, 107632, 100728, 99250, 26940, 99497, 40814, 25067, 49567, 100022, 108067, 105636, 17714, 101616, 110097, 42192, 44793, 1773, 100431, 101909, 57218, 40542, 102517, 99445, 101063, 9370, 102280, 101108, 48443, 40542, 102517, 99445, 104133, 101532, 106456, 109641, 119095, 119781, 3837, 99517, 101280, 77288, 102625, 99476, 102382, 1773, 100012, 99394, 49828, 119095, 119781, 107319, 3837, 40542, 102517, 99445, 99172, 100195, 46944, 100241, 1773, 42411, 115566, 18493, 71268, 59074, 119488, 46553, 9909, 36171, 104803, 102178, 7552, 102116, 118750, 79599, 53938, 3837, 104325, 102688, 106125, 3837, 104110, 18830, 101271, 39374, 3837, 103939, 111678, 118750, 79599, 3837, 116451, 79478, 36993, 108795, 105591, 105719, 105868, 1773, 103968, 3837, 40542, 102517, 99445, 99786, 18493, 80443, 105076, 110540, 104248, 3837, 104183, 111678, 118750, 79599, 3837, 112035, 99394, 18158, 119095, 119781, 107319, 3407, 99487, 101108, 31235, 105891, 71109, 107936, 26940, 28404, 72881, 13935, 40542, 72881, 17447, 87243, 103283, 104506, 36987, 103435, 40542, 53930, 99355, 74763, 3837, 101755, 99244, 105134, 3837, 101755, 7948, 99612, 99271, 1773, 81217, 102517, 99445, 53930, 99244, 3837, 101293, 108673, 42192, 44793, 3837, 118750, 121829, 16530, 23081, 3837, 117369, 110698, 31843, 99873, 3837, 63703, 109379, 38109, 99546, 3837, 58695, 16530, 99631, 100155, 43268, 1773, 102517, 99445, 53930, 100072, 3837, 100895, 99445, 53930, 44729, 99576, 99445, 99243, 34204, 120542, 57811, 102250, 3837, 68536, 101141, 17340, 99509, 53930, 3837, 62112, 26288, 99355, 99235, 23031, 101657, 117369, 110698, 3837, 105858, 22382, 104128, 32945, 4710, 99487, 101108, 103957, 99312, 104286, 115040, 2073, 118750, 79599, 99293, 116451, 33590, 102688, 103196, 100012, 99605, 85027, 101188, 68536, 114499, 105430, 5373, 110806, 104287, 3837, 103941, 100673, 99599, 57191, 102168, 101996, 109684, 104796, 1773, 99487, 101108, 112009, 40542, 102517, 99445, 9370, 101293, 108673, 42192, 26381, 33108, 32664, 99599, 101436, 9370, 107419, 3837, 103941, 100673, 34187, 60686, 40542, 9370, 118973, 1773, 151645), cumulative_logprob=None, logprobs=None, finish_reason=stop, stop_reason=None)], finished=True, metrics=RequestMetrics(arrival_time=1751870100.149281, last_token_time=1751870100.149281, first_scheduled_time=1751870100.1547663, first_token_time=1751870100.2247133, time_in_queue=0.0054852962493896484, finished_time=1751870105.1529133, scheduler_time=0.0169716477394104, model_forward_time=None, model_execute_time=None), lora_request=None)

完整代码 

from vllm import LLM, SamplingParams
from transformers import AutoTokenizer
import time


# 实例化一个分词对象
tokenizer = AutoTokenizer.from_pretrained("models/Qwen/Qwen2.5-7B-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-7B-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}")


三、OpenAI 兼容服务器部署

3.1、创建服务器

        vLLM 可以部署为实现 OpenAI API 协议的服务器。这使得 vLLM 可以用作使用 OpenAI API 的应用程序的直接替代品。 默认情况下,它在 启动服务器。可以使用 和 arguments 指定地址。

执行以下命令,启动模型为 Qwen2.5-7B-Instruct 的 vLLM 服务器。

python -m vllm.entrypoints.openai.api_server --port 10222 --model /home/AI_big_model/models/Qwen/Qwen2.5-7B-Instruct --served-model-name Qwen2.5-7B-Instruct
参数/命令 说明 示例/值 用途
python -m vllm.entrypoints.openai.api_server 标准的Python命令,用于运行模块作为脚本 vllm.entrypoints.openai.api_server 启动一个OpenAI API兼容的服务器
--port 指定服务器监听的端口号 10222 客户端通过此端口与服务器通信(如http://localhost:10222
--model 指定本地模型存储的路径 ~/workdir/models/Qwen/Qwen2___5-7B-Instruct 服务器加载该路径下的模型进行推理
--served-model-name 指定模型在API中的标识名称 Qwen2___5-7B-Instruct 客户端请求时通过此名称选择模型(如"model": "Qwen2___5-7B-Instruct"

3.2、使用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-7B-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)

流式输出 

当然
,
这是一个
非常
经典
的故事
,
我
将
为您
讲述
一个
简
短
版本
的小
红
帽
的故事
。


从前
,
有一个
可爱
的小
女孩
,
她的
名字
叫
小
红
帽
。
她的
妈妈
让她
给
住在
森林
深处
的
奶奶
送
一
篮
子
食物
。
小
红
帽
出发
了
,
走
着
走
着
,
她
遇到了
一只
狼
。


狼
问
小
红
帽
要去
哪里
,
小
红
帽
告诉
了
狼
她
要去
给
奶奶
送
食物
。
狼
说
:“
我
也是
,
我
也是
,
我
也是
。”
然后
狼
跑
到了
奶奶
家
,
吃
掉了
奶奶
。


当
小
红
帽
到达
奶奶
家
时
,
发现
奶奶
不见了
,
她
开始
四处
寻找
。
最终
,
她
找到了
狼
,
小
红
帽
勇敢
地
与
狼
搏
斗
,
最后
她
和
奶奶
一起
战胜
了
狼
。


他们
一起
逃
了出来
,
小
红
帽
的
妈妈
也
及时
赶到
,
他们
一起
把
狼
杀
死了
。
从此
以后
,
小
红
帽
和
她的
家人
过
上了
幸福
快乐
的生活
。


这个
故事
告诉我们
,
要
警惕
陌生人
,
不要
轻易
相信
别人
,
同时
也要
勇敢
地
面对
困难
和
挑战
。

如果使用 & 了后台启动服务器,可以使用命令杀掉vllm进程,

查看vllm的进程。

ps -ef | grep vllm

杀死进程。

kill 进程id
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐