vLLM是UC Berkeley开源的大语言模型高速推理框架,其内存管理核心——PagedAttention、内置的加速算法如Continues Batching等,一方面可以提升Yuan2.0模型推理部署时的内存使用效率,另一方面可以大幅提升在实时应用场景下Yuan2.0的吞吐量。
接下来本教程将手把手带大家用vLLM实现yuan2.0大模型的推理部署。
1. 配置vLLM运行环境
vLLM环境配置主要分为以下两步,拉取Nvidia官方的镜像创建docker,以及安装vllm运行环境,具体操作步骤如下:
Step 1. 拉取Nvidia提供的pytorch镜像
1. 拉取Nvidia提供的pytorch镜像
docker pull nvcr.io/nvidia/pytorch:23.07-py3
2. 根据上述镜像创建容器
docker run --gpus all -itd --network=host --cap-add=IPC_LOCK --device=/devinfiniband --privileged --name vLLM-Yuan --ulimit core=0 --ulimit memlock=1 --ulimit stack=68719476736 --shm-size=1000G nvcr.io/nvidia/pytorch:23.07-py3
3. 进入容器
docker exec -it vLLM-Yuan bash
Step 2. 安装vLLM运行环境
1. 进入你的工作目录
cd /your_workspace
2. 拉取我们的项目(Github上Yuan2.0的仓库除了包含Yuan2.0的开源代码外,也包含了Yuan2.0-2B经过适配后的vLLM代码,并置于Yuan-2.0/3rdparty/vllm目录下)
git clone https://github.com/IEIT-Yuan/Yuan-2.0.git
3. 进入vLLM项目
cd Yuan-2.0/3rdparty/vllm
4. 安装依赖
pip install -r requirements.txt
5. 安装vllm
pip install -e .
2. 准备Yuan2.0-2B模型权重文件
1.Yuan2.0-2B模型的下载地址
HuggingFace[VL(1] 模型下载地址
ModelScope模型下载地址
OpenXlab模型下载地址
更多下载地址详情可见
2. 将下载好的Yuan2.0-2B模型的ckpt移动至你的工作目录下
cd /your_workspace #进入你的工作目录 mkdir Yuan2.0-2B #在工作目录下创建Yuan2.0-2B文件夹 cd Yuan2.0-2B#进入Yuan2.0-2B目录 将刚刚下载的权重文件拷贝至此文件夹中
3. 基于Yuan2.0-2B的vllm推理
用vLLM推理测试Yuan2.0-2B模型的脚本为test_yuan_1prompt.py和test_yuan_3prompt.py,分别表示用1个提示词推理输出1条结果和用3个提示词推理输出3条结果。
Option 1. 单个prompt推理
# 1. 编辑test_yuan_1prompt.py vim test_yuan_1prompt.py test_yuan_1prompt.py脚本中需要修改的部分代码如下 ''' prompts = ["如果你是一个算法工程师,让你写一个大模型相关的规划,你应该怎么写?"] sampling_params = SamplingParams(max_tokens=300, temperature=1, top_p=0, top_k=1, min_p=0.0, length_penalty=1.0, repetition_penalty=1.0, stop="<eod>", ) llm = LLM(model="/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus", trust_remote_code=True) ''' # 2. 修改LLM模型路径,将此路径改为/your_workspace/Yuan2.0-2B (必选) # 3. 修改prompts提示词内容,可以替换为你想测试的提示词(可选) # 4. 修改sampling_params参数,修改top_p、top_k等参数调整采用策略(可选)
Option 2. 多个prompt推理
# 1. 编辑test_yuan_3prompt.py vim test_yuan_3prompt.py test_yuan_3prompt.py脚本中需要修改的部分代码如下 [VL(3] ''' prompts = [ "如果你是一个算法工程师,让你写一个大模型相关的规划,你应该怎么写?", "写一些 VR 和健身结合的方案", "世界上最高的山是什么", ] sampling_params = SamplingParams(max_tokens=256, temperature=0.8, top_p=0.95, stop="<eod>") llm = LLM(model="/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus", trust_remote_code=True) ''' # 2. 修改LLM模型路径,将此路径改为/your_workspace/Yuan2.0-2B (必选) # 3. 修改prompts提示词内容或者增加/减少prompts个数(可选) # 4. 修改sampling_params参数,修改top_p、top_k等参数调整采用策略(可选) # 注意:用多个prompt进行推理时,可能由于补padding的操作,和用单个prompt推理时结果不一样
4. 基于api_server部署Yuan2.0-2B
除了通过上述提供prompt的脚本来实现Yuan2.0-2B基于vLLM框架的推理以外,我们还可以借助api_server发起服务和调用服务。其中发起和调用服务的api_server有两种,分别是vllm.entrypoints.api_server和vllm.entrypoints.openai.api_server。
Option 1. 基于vllm.entrypoints.api_server部署Yuan2.0-2B
基于普通的api_server部署Yuan2.0-2B的步骤包括推理服务的发起和调用。其中调用vllm.entrypoints.api_server推理服务有以下两种方式:第一种是通过命令行直接调用;第二种方式是通过运行脚本批量调用。
Step 1. 发起api_server服务
发起服务命令如下,将--model后修改为您的ckpt路径
“/your_workspace/Yuan2.0-2B” python -m vllm.entrypoints.api_server --model=/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus --trust-remote-code 发起服务后,显示结果如下 INFO 03-27 08:35:47 llm_engine.py:73] Initializing an LLM engine with config: model='/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus/', tokenizer='/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus/', tokenizer_mode=auto, revision=None, tokenizer_revision=None, trust_remote_code=True, dtype=torch.bfloat16, max_seq_len=8192, download_dir=None, load_format=auto, tensor_parallel_size=1, quantization=None, enforce_eager=False, seed=0) You are using the default legacy behaviour of the <class 'transformers.models.llama.tokenization_llama.LlamaTokenizer'>. This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thoroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565 INFO 03-27 08:35:53 llm_engine.py:230] # GPU blocks: 11227, # CPU blocks: 780 INFO 03-27 08:35:55 model_runner.py:425] Capturing the model for CUDA graphs. This may lead to unexpected consequences if the model is not static. To run the model in eager mode, set 'enforce_eager=True' or use '--enforce-eager' in the CLI. INFO 03-27 08:35:55 model_runner.py:429] CUDA graphs can take additional 1~3 GiB memory per GPU. If you are running out of memory, consider decreasing `gpu_memory_utilization` or enforcing eager mode. INFO 03-27 08:36:03 model_runner.py:471] Graph capturing finished in 8 secs. INFO: Started server process [1628] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)[VL(4]
Step 2. 基于命令行调用服务
调用服务的命令如下:
curl http://localhost:8000/generate -d '{"prompt": "如果你是一个算法工程师,让你写一个大模型相关的规划,你应该怎么写?", "use_beam_search": false, "n": 1, "temperature": 1, "top_p": 0, "top_k": 1, "max_tokens":256, "stop": "<eod>"}'
Step 3. 运行脚本行调用服务
调用api_server的相关脚本为yuan_api_server.py,部分内容如下
import requests import json outputs = [] with open('/mnt/Yuan-2.0/3rdparty/vllm/humaneval/human-eval-gpt4-translation-fixed5.jsonl', 'r', encoding='utf-8') as file: for line in file: data = json.loads(line) prompt = data.get('prompt') raw_json_data = { "prompt": prompt, "logprobs": 1, "max_tokens": 256, "temperature": 1, "use_beam_search": False, "top_p": 0, "top_k": 1, "stop": "<eod>", } json_data = json.dumps(raw_json_data) headers = { "Content-Type": "application/json", } response = requests.post(f'http://localhost:8000/generate', data=json_data, headers=headers) output = response.text output = json.loads(output) output = output['text'] outputs.append(output[0]) print(outputs) #可以选择打印输出还是储存到新的jsonl文件 # 1. 示例中是读取的中文版本humaneval测试集,通过批量调用推理服务并将结果保存在对应的jsonl文件中 # 2. 您可以将代码中读取的jsonl文件路径替换为您的路径 # 3. 或者在此代码基础上进行修改,例如手动传入多个prompts以批量调用api_server进行推理 # 4. 修改完成后运行以下命令脚本调用推理服务即可 python yuan_api_server.py
Option 2. 基于vllm.entrypoints.openai.api_server部署Yuan2.0-2B
基于openai的api_server部署Yuan2.0-2B的步骤和普通api_server的步骤类似,发起服务和调用服务的方式如下:
Step 1. 发起服务
发起服务的命令如下:
python -m vllm.entrypoints.openai.api_server --model=/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus/ --trust-remote-code
Step 2. 调用服务命令
curl http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{"model": "/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus/", "prompt": "如果你是一个算法工程师,让你写一个大模型相关的规划,你应该怎么写?", "max_tokens": 300, "temperature": 1, "top_p": 0, "top_k": 1, "stop": "<eod>"}'
Step 3. 调用服务脚本
import requests import json outputs = [] with open('/mnt/Yuan-2.0/3rdparty/vllm/humaneval/human-eval-gpt4-translation-fixed5.jsonl', 'r', encoding='utf-8') as file: for line in file: data = json.loads(line) prompt = data.get('prompt') raw_json_data = { "model": "/temp_data/LLM_test/Tensorrt-llm-yuan/yuan2B_Janus/", "prompt": prompt, "max_tokens": 256, "temperature": 1, "use_beam_search": False, "top_p": 0, "top_k": 1, "stop": "<eod>", } json_data = json.dumps(raw_json_data, ensure_ascii=True) headers = { "Content-Type": "application/json", } response = requests.post(f'http://localhost:8000/v1/completions', data=json_data, headers=headers) output = response.text output = json.loads(output) output0 = json_data["choices"][0]['text'] outputs.append(output0) break # 此脚本您需要修改"model"后的ckpt路径,其他修改方式和yuan_api_server.py一致
vLLM VS TensorRT-LLM性能比对
vLLM和TensorRT-LLM推理速度比对结果如下:
从性能提升方面,TensorRT-LLM的提升效果更强,推理速度更快
vLLM运行Yuan2.0-2B模型显存占用如下:
从显存占用方面,vLLM使用了PagedAttention会预先分配KV的显存,实测内存占用约是TensorRT-LLM的2倍以上
从吞吐量方面,vLLM的灵活内存管理方式适合大max_tokens的推理,吞吐量更高,实测单卡(80GB)长文本推理可以达到128K
从易用性方面,vLLM无需像TensorRT-LLM去build engine,转换和调用是合并的过程,操作起来更便捷
总结来说,如果需求是长文本、高吞吐量、操作更便捷,优先选择vLLM;如果想做短文本的推理和推理服务优先选取TensorRT-LLM。
yuan2.0大模型及周边软件将持续更新,欢迎关注Yuan2.0官方Github,及时获取最新进展!
点击即可跳转链接~