DeepGPU-LLM作为阿里云开发的一套推理引擎,旨在优化大语言模型在GPU云服务器上的推理过程,为您提供免费的高性能、低延迟推理服务。DeepGPU-LLM提供了一系列的API接口(例如模型加载、模型推理等功能),在GPU云服务器上成功安装DeepGPU-LLM后,您可以调用对应API接口进行模型推理服务,快速提高模型的推理效率和准确性。
DeepGPU-LLM是阿里云研发的基于GPU云服务器的大语言模型(Large Language Model,LLM)推理引擎。更多信息,请参见什么是推理引擎DeepGPU-LLM。
(可选)转换模型格式
使用DeepGPU-LLM时需要将huggingface格式的开源模型(非量化模型)转换为DeepGPU-LLM支持的格式,才能使用DeepGPU-LLM进行模型的推理优化服务。部分大语言模型的格式转换过程对CPU侧内存资源有较高要求,为了避免对CPU内存资源的高需求,您可以提前转换大语言模型格式,或者通过增加CPU内存资源(例如在Docker容器中配置--shm-size参数来增加资源)便于加载模型时自动转换模型格式。
DeepGPU-LLM加载大语言模型时提供了模型自动转换功能,如果模型对CPU侧内存资源没有特别要求,您可以利用DeepGPU-LLM提供的API接口直接加载原始模型来自动转换模型格式。
DeepGPU-LLM提供了统一的模型转换命令huggingface_model_convert,在使用模型转换脚本前,请先了解各参数含义:
|
参数名 |
说明 |
|
|
获得帮助信息。 |
|
|
待转换的原始模型路径(该模型可以从Huggingface或Modelscope平台中下载)。 |
|
|
格式转换后的模型所存放的路径。 |
|
|
期望使用多少个GPU进行推理运算。 |
|
|
模型使用的精度,例如fp16或bf16。 |
|
|
模型自定义的名称,可任意填写。 |
|
|
处理模型转换所使用的vCPU核数。 |
-
示例1:对llama2-7b-chat模型的转换命令
huggingface_model_convert --in_file /mnt/models/Llama-2-7b-chat-hf/ --saved_dir /mnt/models_deepgpu/llama2-7b-chat --weight_data_type fp16 --model_name llama2-7b --infer_gpu_num 1 -
示例2:对千问qwen2-7b-instruct模型的转换命令
huggingface_model_convert --in_file /mnt/models/Qwen2-7B-Instruct --saved_dir /mnt/models_deepgpu/Qwen2-7B-Instruct --weight_data_type fp16 --model_name qwen2-7b --infer_gpu_num 1
如果无法找到huggingface_model_convert命令,说明DeepGPU版本较老,您可以升级当前DeepGPU-LLM版本,具体操作,请参见(可选)升级DeepGPU-LLM;或者根据LLM模型类型,将model字段替换为具体的LLM名称,然后进行模型转换,具体查看help调整相应参数。
DeepGPU-LLM的API接口说明
模型加载函数
DeepGPU-LLM提供统一的模型处理类deepgpu_model,具体接口代码如下。其中,该模型处理类包含模型加载函数__init__函数和from_pretrained函数。
加载函数介绍
class deepgpu_model(torch.nn.Module):
def __init__(self, model_path: str, tensor_para_size: int, precision: int = 0,
kv_cache_quant_level: int = 0,
generation_config: typing.Optional[DeepGPUGenerationConfig] = None,
is_gemm_tuning: bool = False,
load_pretrained: bool = False,
page_size: int = 16,
gpu_utilization: float = 0.9,
max_batch_size : int = 128,
max_context_token_num: int = 8192,
session_len: int = 2048)
@classmethod
def from_pretrained(cls, model_path, tensor_para_size, precision = 0,
kv_cache_quant_level: int = 0,
generation_config: typing.Optional[DeepGPUGenerationConfig] = None,
page_size: int = 16,
gpu_utilization: float = 0.9,
max_batch_size : int = 128,
max_context_token_num: int = 8192,
session_len: int = 2048,
data_set = None)
-
__init__函数:用于加载已转换好格式的模型。具体参数介绍如下:参数名
说明
model_path指向格式已转换好的模型目录。
说明一般为
x-gpu目录,其中x为多少个GPU,模型转换时自动生成的目录。tensor_para_size使用的GPU数量,需要与模型转换设置的GPU数量保持一致。
precision权重量化级别。取值范围:
-
0:表示fp16精度。
-
1:表示int8量化。
-
3:表示int4量化。
-
5:表示fp8精度。
默认值:0。
kv_cache_quant_levelkv_cache量化级别。取值范围:
-
0:表示无量化压缩。
-
1:表示K8_V8量化,推荐值。
-
2:表示K8_V4量化。
-
3:表示K4_V4量化。
默认值:0。
generation_config模型配置参数。更多信息,请参见模型参数类(DeepGPUGenerationConfig)。
说明若不设置该参数,则会加载模型配置文件中的默认参数。
is_gemm_tuning是否优化最佳Kernel,常见GPU的最佳Kernel已优化好并存储于安装包内。取值范围:
-
False:不优化最佳Kernel。
-
True:优化最佳Kernel。
默认值:False。
load_pretrained加载的模型是否为原始模型。取值范围:
-
False:表示加载格式已转换好的模型。
-
True:表示需要加载格式未转换的原始模型,不可直接调用,主要是提供
from_pretrained函数内部调用以实现从原始模型加载的功能。
默认值:False。
page_sizepage attention所使用的内存块大小。
gpu_utilizationGPU显存容量使用比例。
max_batch_size能够同时处理的最大请求数。
说明若资源不足以支持配置的值,系统也会根据GPU显存资源进行调整。
max_context_token_num上下文限制的最大Token数量,该值不能小于
session_len值。session_len对话长度限制,即输入和输出的Tokens数量。
若该值超过
session_len默认值,则需要配置该参数。data_set配置fp8量化使用的标定数据目录。
若不使用fp8精度,则不需要设置该参数。
-
-
from_pretrained函数:直接加载从huggingface和modelscope平台上下载的开源模型,加载过程中支持在线自动转换模型。该函数是一个classmethod类型的函数,会在内部调用
__init__创建一个deepgpu_model类,可以从原始模型目录加载模型,进行模型转换并进行初始化。关于from_pretrained函数的具体参数介绍,请参见上表中的__init__函数具体参数介绍。
加载函数使用说明
-
通过
deepgpu_model类的__init__函数来加载模型。从
deepgpu_llm.deepgpu_model模块中导入deepgpu_model类,然后调用deepgpu_model类进行模型初始化,此时输入的args.model_dir指向格式转换好的模型目录。示例代码如下:from deepgpu_llm.deepgpu_model import deepgpu_model model = deepgpu_model(model_path = args.model_dir, tensor_para_size = args.tpsize, precision = precision, kv_cache_quant_level = args.kv_cache_quant_level, gpu_utilization = args.gpu_utilization, session_len = max_inout_len, max_context_token_num = max_context_token_num) -
通过
deepgpu_model类的from_pretrained函数来创建模型类并加载原始模型。调用
deepgpu_model.from_pretrained函数来创建模型类并加载原始模型,在线转换模型并进行初始化,此时args.model_dir指向huggingface或modelscope的原始模型目录。示例代码如下:from deepgpu_llm.deepgpu_model import deepgpu_model model = deepgpu_model.from_pretrained(model_path = args.model_dir, tensor_para_size = args.tpsize, precision = precision, kv_cache_quant_level = args.kv_cache_quant_level, gpu_utilization = args.gpu_utilization, session_len = max_inout_len, max_context_token_num = max_context_token_num)
模型推理函数
DeepGPU-LLM提供了丰富的推理API接口,您可以根据实际需求选择离线模式(offline)或在线模式(serving)调用API接口。
模型推理离线模式(offline)
推理API函数(offline)分为普通输出函数(一次性输出)和流式输出函数。
-
普通输出函数generate(一次性输出)
普通输出函数直接返回输出结果,输出结果有多层封装,较为复杂,实际使用时建议打印出进行逐层拆解,最终获得需要的输出信息。普通输出函数generate定义如下:
def generate(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)调用
model.generate执行模型推理时,generation_config参数通过模型参数类(DeepGPUGenerationConfig)进行设置,更多信息,请参见常用类介绍。调用generate的代码如下所示:inputs = [] inputs.append(tokenizer(query, return_tensors='pt').input_ids) generation_config = DeepGPUGenerationConfig(max_new_tokens = args.output_tokens, top_k = args.top_k, top_p = args.top_p, temperature = args.temperature, repetition_penalty = args.repetition_penalty) output = model.generate(inputs, generation_config) outputX = output[0].tolist() outputY = outputX[0][0][inputs[0].shape[1]:] response = tokenizer.decode(outputY)参数名
说明
inputs输入参数,是一个
tokenizer转换后的token ids的数组。query为实际输入的文本,若有多个输入,可以对所有输入进行token转换,并添加到
inputs数组中。output输出参数,需要进行多层拆解以获得
outputY为实际输出的token ids,然后调用tokenizer.decode函数解析转换为文本结果。说明若有多个输入,输出也会有多个,您可以通过
outputX[batch_id][0]来定位对应的输出。 -
流式输出函数(stream_generate)
流式输出可以根据实际推理生成进程,实时地将输出的内容展示给用户。流式输出函数stream_generate定义如下:
def stream_generate(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None, skip_inputs = False)stream_generate是各模型类的成员函数,具体参数说明:
参数名
说明
input_ids输入参数,为模型构造输入数据,更多信息,请参见普通输出函数generate(一次性输出)。
generation_config运行参数。具体参数定义,请参见常用类介绍。
skip_inputs用于配置是否在生成的输出中屏蔽输入内容。取值范围:
-
True:屏蔽输出内容。
-
False:显示输出内容。
调用stream_generate的代码如下所示,首先需要调用
DeepGPUStreamer构建一个streamer,然后启动stream_generate函数开始推理,此时程序返回并继续实时监控最新的生成结果,然后进行实时输出。streamer = DeepGPUStreamer(tokenizer, **{'skip_special_tokens':True}) total_len = 0 response = "" for output in model.stream_generate(inputs, generation_config=generation_config, skip_inputs=True): printable_str = streamer.handel_str(output) response = response + printable_str total_len += 1 yield { "text": response, "prompt_tokens": input_echo_len, "completion_tokens": total_len, "total_tokens": total_len, "finish_reason": None, }参数名
说明
printable_str当前时刻生成的token对应的文本。
response将所有前序生成的文本进行归集。
total_len统计实际生成的tokens数。
-
模型推理在线模式(serving)
该模式适用于多用户多请求场景,通过提供3个并发调用函数来适配不同的代码工程场景。其中,并发调用函数包括普通调用函数、async调用函数以及含request_id的async调用函数。
-
普通调用函数(generate_cb)
上层调用函数为普通函数(非async函数)时,可以调用
generate_cb函数。普通调用函数定义如下:def generate_cb(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)参数名
说明
input_ids输入参数,为模型构造输入数据,更多信息,请参见普通输出函数generate(一次性输出)。
generation_config模型推理使用的参数。
调用
generate_cb函数的代码示例。启动model.generate_cb进行模型推理后,程序会返回执行结果,通过监控实时输出的tokens,将当前输出文本printable_str整合成response(即输出文本)。streamer = DeepGPUStreamer(tokenizer, **{'skip_special_tokens':True}) total_len = 0 response = "" results_generator = model.generate_cb(inputs, generation_config=generation_config) for request_output in results_generator: if(request_output==-1): printable_str = streamer.end() else: printable_str = streamer.handel_str(request_output) response = response + printable_str total_len += 1 yield { "text": response, "prompt_tokens": input_echo_len, "completion_tokens": total_len, "total_tokens": total_len, "finish_reason": None, } -
async调用函数(generate_cb_async)
上层调用函数是async函数,可以调用
generate_cb_async,async调用函数定义如下:async def generate_cb_async(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)调用
generate_cb_async函数的代码示例如下所示,该函数与generate_cb函数的用法基本一致,但您需要使用async for进行循环,监控最新结果token的生成。streamer = DeepGPUStreamer(tokenizer, **{'skip_special_tokens':True}) total_len = 0 response = "" results_generator = model.generate_cb_async(inputs, generation_config=generation_config) async for request_output in results_generator: if(request_output==-1): printable_str = streamer.end() else: printable_str = streamer.handel_str(request_output) response = response + printable_str total_len += 1 yield { "text": response, "prompt_tokens": input_echo_len, "completion_tokens": total_len, "total_tokens": total_len, "finish_reason": None, } -
含request_id的async调用函数(generate_cb_async_id)
如果您需要对请求数量和请求ID进行管控,可以调用
generate_cb_async_id函数,该函数的参数与generate_cb_async相似,配置了额外的变量request_id,用于区分不同请求及其结果生成。含request_id的async调用函数定义如下:async def generate_cb_async_id(self, input_ids, request_id: int = 0, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)调用
generate_cb_async_id函数的代码示例如下所示,调用该代码时,请参考请求ID处理类(RequestCounter)的RequestCounter类对request_id进行管理和操纵。from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig,DeepGPUStreamer,RequestCounter counter = RequestCounter() streamer = DeepGPUStreamer(tokenizer, **{'skip_special_tokens':True}) request_id = next(counter) total_len = 0 response = "" results_generator = model.generate_cb_async(inputs, generation_config=generation_config) async for request_output in results_generator: if(request_output==-1): printable_str = streamer.end() else: printable_str = streamer.handel_str(request_output) response = response + printable_str total_len += 1 yield { "text": response, "prompt_tokens": input_echo_len, "completion_tokens": total_len, "total_tokens": total_len, "finish_reason": None, }
常用类介绍
deepgpu_utils.py 通常提供一些实用的函数和工具,以支持DeepGPU-LLM的推理API接口,deepgpu_utils.py定义了一些常用类,例如,模型参数类(DeepGPUGenerationConfig)、并发流处理类(DeepGPUStreamer)以及请求ID处理类(RequestCounter)。这些类可以管理模型的运行环境、处理并发请求以及跟踪请求的执行情况,您可以通过以下代码将这些类导入至deepgpu_utils.py中。
from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig, DeepGPUStreamer, RequestCounter
-
模型参数类(DeepGPUGenerationConfig)
DeepGPUGenerationConfig类主要用于给模型传递推理运行相关参数,详见以下代码。具体参数可以不设置,DeepGPU-LLM会自动从模型配置文件里获取相关初始参数。class DeepGPUGenerationConfig(): def __init__(self, **kwargs): self.max_new_tokens = kwargs.pop("max_new_tokens", 512) self.do_sample = kwargs.pop("do_sample", None) self.num_beams = kwargs.pop("num_beams", None) self.temperature = kwargs.pop("temperature", None) self.top_k = kwargs.pop("top_k", None) self.top_p = kwargs.pop("top_p", None) self.repetition_penalty = kwargs.pop("repetition_penalty", None) self.presence_penalty = kwargs.pop("presence_penalty", None) self.len_penalty = kwargs.pop("len_penalty", None) self.beam_search_diversity_rate = kwargs.pop("beam_search_diversity_rate", None) self.min_tokens = kwargs.pop("min_tokens", 0) -
并发流处理类(DeepGPUStreamer)
DeepGPUStreamer类用于处理大语言模型的流式输出和多请求输出,详见以下代码。class DeepGPUStreamer(): def __init__(self, tokenizer: "AutoTokenizer", skip_prompt: bool = False, print_out: bool = True, **decode_kwargs) def handle_str(self, value) def end(self)函数名
说明
__init__()初始化内部使用到的tokenizer和用于打印的字符串缓存区。
handle_str()接受一个token id,并转换为自然语言文本,然后放入字符串缓存区中,返回字符串缓存区中可以打印的字符串。
end()返回字符串缓存区中剩余的字符串。
-
请求ID处理类(RequestCounter)
RequestCounter类主要用于多请求场景中的request_id管理,详见以下代码。class RequestCounter: def __init__(self, start: int = 0) -> None def __next__(self) -> int def reset(self) -> None def add(self, len: int) -> int def cur(self) -> int函数名
说明
__init__()对
RequestCounter类进行初始化,默认值为0,您也可以通过设置start值对类进行初始化。__next__()获取当前counter值,并对内部的counter累加1。
reset()内部的counter重置为0,以便从头开始生成请求ID。
add()返回内部原始counter值,然后将counter加上len作为新值。
cur()获取当前counter值,不进行其他操作。
DeepGPU-LLM实例代码
本文提供了一系列DeepGPU-LLM的参考代码,帮助您更快速地上手进行编程开发。
离线(offline)代码示例
-
简单Llama模型示例
本示例以llama2-7b-chat模型为例,运行以下deepgpu-llm实例代码前,请确保您已经对lama2-7b-chat模型进行模型转换操作,同时,您也可以根据实际情况调整模型目录、GPU数量、量化精度等参数。
import time from deepgpu_llm.deepgpu_model import deepgpu_model from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig from transformers import LlamaTokenizer model_path = '/mnt/models_deepgpu/llama2-7b-chat' tokenizer = LlamaTokenizer.from_pretrained(model_path) model_path_conv = "/mnt/models_deepgpu/llama2-7b-chat/1-gpu" tensor_para_size = 1 precision = 0 # 0:fp16 mode, 1:int8 mode, 3:int4 mode kv_cache_quant_level = 0 # 0:no quant, 1:K8_V8, 2:K8_v4, 3:K4_V4 generation_config = DeepGPUGenerationConfig(max_new_tokens=512) model = deepgpu_model(model_path_conv, tensor_para_size, precision, kv_cache_quant_level, generation_config=generation_config) payload = "Hi, please introduce the alibaba?" start_ids = [tokenizer(payload, return_tensors="pt").input_ids] print(payload) for i in range(5): s = time.time() output = model.generate(start_ids, generation_config) e = time.time() print("---- time", e - s) tokens = output[0].tolist() for i in range(len(tokens)): print(tokenizer.decode(tokens[i][0]))运行上述实例代码后,显示结果如下所示:
xxx 1u5Z:~/aiacc/test/api_sample# python3 llama_sample.py using KV cache quant level 1 running in fp16 mode, cb is False Keyword arguments {'add_special_tokens': False} not recognized. Hi, please introduce the alibaba? ---- time 4.796230792999268 ---- time 4.656716346740723 ---- time 4.655441284179687 5 ---- time 4.654964208602905 ---- time 4.657361030578613 <s> Hi, please introduce the alibaba? Alibaba Group Holding Limited, commonly known as Alibaba, is a Chinese multinational conglomerate that specializes in e-commerce, retail, Internet, and technology. The company was founded in 1999 by Jack Ma and a group of 18 other people, and it has since grown to become one of the largest and most successful companies in the world. Alibaba is headquartered in Hangzhou, Zhejiang, China, and it operates a number of different businesses through its various subsidiaries. These include: * Alibaba.com, a business-to-business e-commerce platform that connects suppliers in China with buyers around the world. * Taobao Marketplace and Tmall, two of the largest consumer-to-consumer and business-to-consumer e-commerce platforms in China. * Alipay, a leading online payment platform that allows consumers to pay for goods and services online. -
流式输出Qwen模型示例
本示例以单卡GPU上运行qwen-7b模型的实例代码为例,您可以调整代码中
precision量化精度、kv_cache_quant_level量化级别、tp_sizeGPU数量,获得更快的性能和减少GPU显存占用。运行下列代码后将结果流式打印输出,并统计性能。import time from deepgpu_llm.deepgpu_model import deepgpu_model from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig, DeepGPUStreamer from transformers import AutoTokenizer model_path = "/mnt/models_deepgpu/Qwen2-7B-Instruct" tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model_path_conv = "/mnt/models_deepgpu/Qwen2-7B-Instruct/1-gpu" tp_size = 1 # tensor parallel precision = 0 # 0:fp16 mode, 1:int8 mode, 3:int4 mode kv_cache_quant_level = 0 # 0:no quant, 1:K8_V8, 2:K8_v4, 3:K4_V4 generation_config = DeepGPUGenerationConfig(max_new_tokens=512) model = deepgpu_model(model_path_conv, tp_size, precision, kv_cache_quant_level, generation_config=generation_config) print("model init over!") payload = "<|im_start|>user\n 你好,请介绍下杭州的旅游景区? <|im_end|>\n<|im_start|>assistant\n" start_ids = tokenizer(payload, return_tensors="pt").input_ids streamer = DeepGPUStreamer(tokenizer, **{'skip_special_tokens':True}) total_len = 0 response = "" print("response : ") start = time.time() for output in model.stream_generate([start_ids], generation_config=generation_config, skip_inputs=True): printable_str = streamer.handel_str(output[0][0]) #response = response + printable_str total_len += 1 print(printable_str, flush=True, end = "") end = time.time() print() print() print("time : ", (end - start)) print("speed: ", total_len/(end - start), " tokens/s")运行上述实例代码,查看输出结果。问题回复结果是流式输出的,此时您可以体验到DeepGPU-LLM推理速度了。
running in fp16 mode, cb is True model init over! response : ,作为中国浙江省的省会城市,不仅有着丰富的历史文化底蕴,还拥有众多美丽的自然景观和人文景点。以下是一些杭州著名的旅游景区: 1. **西湖**:西湖是中国最著名的湖泊之一,被誉为"人间天堂"。它以其秀美的山水风光、丰富的历史文化和悠久的传说故事而闻名。西湖周边有许多名胜古迹,如断桥、雷峰塔、苏堤春晓等。 2. **西溪国家湿地公园**:位于杭州市区西部,是一个集自然生态、文化遗迹和休闲娱乐于一体的大型湿地公园。在这里,你可以体验到江南水乡的独特风情,同时还能欣赏到各种野生动植物。 3. **宋城**:这是一个以宋代文化为主题的大型主题公园,内部复原了宋代的市井生活场景,通过表演和互动体验让游客感受宋代的历史文化。宋城还有著名的《宋城千古情》演出,是了解宋代文化的绝佳方式。 4. **灵隐寺**:位于西湖以北的飞来峰下,是一座历史悠久的佛教寺庙。灵隐寺周围环境幽静,山清水秀,是参禅悟道、祈福求愿的好去处。 5. **钱塘江潮**:每年农历八月十八日的钱塘江大潮是自然奇观,吸引了大量游客前来观赏。湖水汹涌澎湃,气势磅礴,是大自然赋予杭州的独特魅力。 6. **杭州宋城遗址博物馆**:位于南宋皇城遗址上,展示了南宋时期的政治、经济、文化、社会等方面的历史。博物馆内有丰富的文物展览和多媒体展示,帮助游客深入了解南宋历史。 7. **乌镇**:虽然乌镇位于杭州附近,但其独特的水乡风貌和深厚的文化底蕴使其成为杭州周边不可错过的旅游目的地。乌镇保留了许多明清时期的建筑,展现了典型的江南水乡特色。 8. **西子湖畔的龙井茶园**:在西湖边,你可以参观和体验传统的龙井茶制作工艺,品尝正宗的龙井茶,享受宁静的田园风光。 这些只是杭州众多旅游景点中的一部分,每个地方都有其独特之处,无论是自然风光还是人文历史,都能让你感受到杭州的魅力 time : 5.061952114105225 speed: 90.87403231614961 tokens/s说明如需查看其他类型LLM模型的流式输出实例代码,您可以通过执行以下命令直接查看DeepGPU-LLM的安装目录,找到相应
llama_cli脚本、chatglm_cli脚本、baichuan_cli脚本、qwen_cli脚本或deepgpu_cli脚本(仅24.9及以上版本的DeepGPU-LLM提供),即可查看相应代码。pip show -f deepgpu-llm -
多batch同时输入的示例
针对于多batch场景,关键是处理输入和输出,各类模型输入输出的处理方法,请参见普通输出函数generate(一次性输出)。
import time from deepgpu_llm.deepgpu_model import deepgpu_model from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig from transformers import AutoTokenizer model_path = "/mnt/models_deepgpu/Qwen1.5-72B-Chat" tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model_path_conv = "/mnt/models_deepgpu/Qwen1.5-72B-Chat/4-gpu" tp_size = 4 # tensor parallel precision = 0 # 0:fp16 mode, 1:int8 mode, 3:int4 mode kv_cache_quant_level = 0 # 0:no quant, 1:K8_V8, 2:K8_v4, 3:K4_V4 generation_config = DeepGPUGenerationConfig(max_new_tokens=512) model = deepgpu_model(model_path_conv, tp_size, precision, kv_cache_quant_level, generation_config=generation_config) print("model init over!") prompt =["你好,你是谁?", "你好,请介绍下杭州的旅游景区?", "你好,请介绍下北京的旅游景区?", "你好,请介绍下新疆的旅游景区?", "你好,请介绍下西藏的旅游景区?"] batchsize = len(prompt) start_ids = [] for bs in range(batchsize): payload = "<|im_start|>user\n " + prompt[bs] + "<|im_end|>\n<|im_start|>assistant\n" start_ids.append(tokenizer(payload, return_tensors="pt").input_ids) output = model.generate(start_ids, generation_config) tokens = output[0].tolist() for bs in range(batchsize): response = tokenizer.decode(tokens[bs][0], skip_special_tokens=True) print("response [", bs, "] : ", response.rstrip(tokenizer.decode(0)))运行上述代码,输出结果:
root@xxx:~/aiacc/test/api_sample# python3 qwen_batch_sample.py Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. running in fp16 mode, cb is False model init over! response[0]: user 你好,你是谁? assistant 你好!我是来自阿里云的大模型语言模型,我叫通义千问。作为一个AI助手,我的任务是帮助用户获得准确、有用的信息,解决他们的问题和困惑。你可以问我关于各个领域的知识、技术问题,或者想要了解的任何事情。我会尽我所能提供帮助。有什么我可以为你做的吗? response[1]: user 你好,请介绍下杭州的旅游景区? assistant 你好,杭州是中国著名的旅游城市,有许多著名的景点。比如西湖,它是中国最著名的湖泊,拥有"苏堤春晓"、"曲院风荷"等十景;灵隐寺,是杭州最大的佛教寺院,有着悠久的历史;宋城,是一个以宋代文化为主题的公园,可以体验宋代的生活;西溪国家湿地公园,是集生态保护、休闲观光和文化展示于一体的大型湿地公园;还有六和塔、三潭印月、钱塘江大桥等著名景点。希望你有机会能来自去杭州游览一番。 response[2]: user 你好,请介绍下北京的旅游景区? assistant 北京是中国的首都,拥有众多著名的旅游景点。比如故宫,它是中国历史上最重要的皇家宫殿;长城,世界文化遗产,是古代中国防御工程的杰出代表;颐和园,是一座保存完好的皇家园林;天安门广场,是中华人民共和国的象征;以及南锣鼓巷,是一条充满古老北京风情的胡同。此外,还有北海公园、圆明园、798艺术区等著名景点,都是游客游览北京的必去之地。
在线(serving)代码示例
-
服务端代码示例
执行deepgpu fastapi_server.py脚本文件,实现接收文本生成请求,使用DeepGPU模型进行文本生成,并返回生成的文本。
import argparse import json from typing import AsyncGenerator from fastapi import FastAPI, Request from fastapi.responses import JSONResponse, Response, StreamingResponse import uvicorn from deepgpu_llm.deepgpu_model import deepgpu_model from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig,DeepGPUStreamer,RequestCounter from transformers import AutoTokenizer import time TIMEOUT_KEEP_ALIVE = 5 # seconds. TIMEOUT_TO_PREVENT_DEADLOCK = 1 # seconds. app = FastAPI() engine = None counter = RequestCounter() tokenizer = None @app.get("/health") async def health() -> Response: """Health check.""" return Response(status_code=200) @app.post("/generate") async def generate(request: Request) -> Response: request_dict = await request.json() prompt = request_dict.pop("prompt") max_new_token = request_dict.pop("max_tokens") prompt = [tokenizer(prompt, return_tensors='pt').input_ids] stream = request_dict.pop("stream", True) streamer = DeepGPUStreamer(tokenizer=tokenizer) generation_config = DeepGPUGenerationConfig(max_new_tokens = max_new_token) results_generator = engine.generate_cb_async(prompt,generation_config=generation_config) # Streaming case async def stream_results() -> AsyncGenerator[bytes, None]: # await asyncio.sleep(0) async for request_output in results_generator: if(request_output==-1): printable_str = streamer.end() text_outputs = [ printable_str ] ret = {"text": text_outputs} yield (json.dumps(ret) + "\0").encode("utf-8") break else: printable_str = streamer.handel_str(request_output) text_outputs = [ printable_str ] ret = {"text": text_outputs} yield (json.dumps(ret) + "\0").encode("utf-8") if stream: return StreamingResponse(stream_results()) # Non-streaming case total_str = "" async for request_output in results_generator: if(request_output == -1): total_str += streamer.end() break else: total_str += streamer.handel_str(request_output) ret = {"text": total_str} return JSONResponse(ret) if __name__ == "__main__": parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) parser.add_argument("--host", type=str, default=None) parser.add_argument("--port", type=int, default=8000) parser.add_argument('--model_dir', '-i', type=str, help='converted model dir', required=True) parser.add_argument('--tokenizer_dir', '-t', type=str, help='tokenizer dir', required=False) parser.add_argument('--tp_size', '-tp', type=int, help='tensor para size', required=True) args = parser.parse_args() tokenizer = AutoTokenizer.from_pretrained(args.tokenizer_dir, trust_remote_code=True) model_path = args.model_dir tp_size = args.tp_size precision = 0 # 0:fp16 mode, 1:int8 mode, 3:int4 mode engine = deepgpu_model(model_path, tp_size, precision,is_gemm_tuning=False) uvicorn.run(app, host=args.host, port=args.port, log_level="debug", timeout_keep_alive=TIMEOUT_KEEP_ALIVE)继续运行以下命令,启动服务。
python3 fastapi_server.py -i /mnt/models_deepgpu/Qwen2-7B-Instruct/1-gpu -t /mnt/models_deepgpu/Qwen2-7B-Instruct -tp 1如果显示以下结果,表示该服务搭建成功。
root@xxxkfny1Z:~/deepgpu/test/sample_api# python3 fastapi_server.py -i /mnt/models_deepgpu/Qwen2-7B-Instruct/1-gpu -t /mnt/models_deepgpu/Qwen2-7B-Instruct -tp 1 Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained. running in fp16 mode, cb is True INFO: Started server process [1428285] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)说明DeepGPU兼容vLLM的serving实现,您可以直接使用vLLM的官方代码
benchmark_serving.py作为参考,仅需将其内部的import vllm更改为import deepgpu即可。更多信息,请参见更多示例(将vLLM切换为DeepGPU-LLM推理引擎)。 -
客户端python代码
本示例以一个异步的Python脚本为例,实现向一个HTTP服务发送请求,获取文本生成的流式响应,并打印这些响应的功能。
import requests import json import time import aiohttp import asyncio import random import os url = "http://0.0.0.0:8000/generate" # 普通服务模式 # url = "http://0.0.0.0:8000/v1/completions" # openai接口普通服务模式 headers = {"User-Agent": "Benchmark Client"} # 普通服务模式 # headers = { # "Authorization": f"Bearer {os.environ.get('OPENAI_API_KEY')}" #openai接口普通服务模式 # } async def stream_back(data): async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=json.dumps(data)) as response: if response.status == 200: async for chunk, _ in response.content.iter_chunks(): chunk = chunk.rstrip(b'\x00') decoded_chunk = chunk.decode('utf-8') if(not decoded_chunk.strip()): continue try: data = json.loads(decoded_chunk) text_content = data.get('text', []) for text in text_content: if text: print(text,flush=True,end='') continue except json.JSONDecodeError as e: print("JSON decode error! error code:", e) async def fetch_stream(prompt: str): max_tokens = 512 # open ai服务使用的data # data = { # "model": '/root/models/Llama-2-7b-chat-hf/', # "prompt": prompt, # "temperature": 0.0, # "best_of": 1, # "max_tokens": 512, # "stream": True, # } # 普通服务使用的data print("[prompt]: ", prompt) data = {"prompt": prompt, "max_tokens": max_tokens, "stream": True} async with aiohttp.ClientSession() as session: start_time = time.time() await stream_back(data) # await none_stream_back(data) end_time = time.time() latency = end_time - start_time print() print(f"Latency: {latency} seconds") async def main(prompt_num): prompt =["你好,你是谁?", "请介绍下杭州的旅游景区?", "请介绍下北京的旅游景区?", "请介绍下杭州的历史变迁?", "你知道BAT吗?", "考上大学后,需要如何填报志愿?", "介绍下浙江最好的几所大学?"] tasks = [fetch_stream(prompt[random.randint(0,len(prompt)-1)]) for _ in range(prompt_num)] await asyncio.gather(*tasks) if __name__ == "__main__": asyncio.run(main(1))运行上述代码后,显示结果如下所示:
[prompt]: 你知道BAT吗? 它们是百度、阿里巴巴和腾讯的英文缩写,是中国互联网行业的三大巨头。百度以搜索引擎起家,阿里巴巴则以电子商务闻名,而腾讯则以其社交网络和游戏业务著称。然而,在这三大巨头的背后,还有一个更神秘的组织——"3Q大战"。 2010年,腾讯与360公司爆发了一场激烈的网络大战,这场战争被称为"3Q大战"。在这场战争中,腾讯推出了一个名为QQ医生的软件,旨在清理用户的电脑并保护QQ用户免受病毒和恶意软件的侵害。然而,这个软件却遭到了360公司的强烈反对,认为其侵犯了用户的隐私,并且存在强制安装的问题。随后,360公司推出了一款名为"安全卫士"的软件,与QQ医生进行了直接对抗。这场战争最终导致了两家公司的用户群出现了严重的分化,甚至在某些地区出现了"3Q大战"的口号。这场战争不仅对两家公司造成了巨大的经济损失,也对整个中国互联网行业产生了深远的影响。此后,腾讯和360公司逐渐达成了和解,并开始在一些领域进行合作,但这场战争仍然被视为中国互联网历史上的一次标志性事件。 尽管"3Q大战"已经过去多年,但它留给我们的教训仍然值得深思。首先,竞争并不意味着非得要将对手置于死地,而是应该寻求共赢的局面。其次,尊重用户权益和隐私是任何企业都应该遵守的基本原则。最后,通过对话和协商解决分歧,而不是采取极端手段,是实现长期稳定发展的重要途径。这些经验对于当前以及未来的互联网竞争环境都具有重要的指导意义。因此,无论是在个人层面还是在企业层面,我们都应该从中吸取教训,促进更加健康、和谐的互联网生态建设。 Latency: 4.07001543045043995 seconds -
客户端curl命令
启动服务后,执行以下命令给服务端发送请求,实现一段文本的输出。
curl -X POST "http://0.0.0.0:8000/generate" \ -H "Content-Type: application/json" \ -H "User-Agent: Benchmark Client" \ -d '{"prompt": "请介绍下杭州的历史变迁?", "stream": false, "max_tokens": 128}'说明curl命令交互不支持流式输出,stream只能设置为false。
运行以上命令后,显示结果如下所示:
root@xxxny1Z:~/deepgpu/test/sample_api# curl -X POST "http://0.0.0.0:8000/generate" \ -H "Content-Type: application/json" \ -H "User-Agent: Benchmark Client" \ -d '{"prompt": "请介绍下杭州的历史变迁? ", "stream": false, "max_tokens": 128}' {"text":" 杭州是中国历史文化名城之一,历史悠久,文化底蕴深厚。以下是杭州历史变迁的简要介绍:\n1. 古代时期:杭州地区在新石器时代就有人类活动的痕迹。到了夏商周时期,这里曾是越国的领地。春秋战国时期,吴越争霸,杭州地区属于越国。秦汉时期,杭州属会稽郡。东晋时期,成为江南重要的政治、经济和文化中心。\n2. 唐宋时期:唐朝时期,杭州成为江南最大的商业城市之一。宋代,杭州成"}
更多示例(将vLLM切换为DeepGPU-LLM推理引擎)
DeepGPU-LLM提供了类似vLLM的接口,如果您需要在不改变现有vLLM代码结构的情况下,基于开源vLLM代码切换为DeepGPU-LLM推理引擎,实现DeepGPU-LLM带来的性能提升和功能扩展,请参考以下两种方式的推理示例:
兼容vLLM的DeepGPU-LLM推理示例(offline)
-
获取vLLM的离线推理示例。
offline_inference.py示例如下:
from vllm import LLM, SamplingParams # Sample prompts. prompts = [ "Hello, my name is", "The president of the United States is", "The capital of France is", "The future of AI is", ] # Create a sampling params object. sampling_params = SamplingParams(temperature=0.8, top_p=0.95) # Create an LLM. llm = LLM(model="facebook/opt-125m") # Generate texts from the prompts. The output is a list of RequestOutput objects # that contain the prompt, generated text, and other information. outputs = llm.generate(prompts, sampling_params) # Print the outputs. for output in outputs: prompt = output.prompt generated_text = output.outputs[0].text print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}") -
基于vLLM示例将推理引擎更改为DeepGPU示例。
修改以下代码完成推理引擎切换,即将导入包由
vllm改为deepgpu_llm,模型文件改为转换后的DeepGPU模型文件。# from vllm import LLM, SamplingParams 更改为: from deepgpu_llm import LLM, SamplingParams # llm = LLM(model="facebook/opt-125m") 更改为 llm = LLM("path/to/your/deepgpu_model")
兼容vLLM的DeepGPU-LLM多请求推理示例(serving)
-
在线获取vLLM的推理示例。
获取路径:api_server。
-
基于vLLM示例将推理引擎更改为DeepGPU示例。
修改以下代码,即将
vllm在线代码更改为deepgpu_llm相关示例。# from vllm.engine.arg_utils import AsyncEngineArgs 更改为: from deepgpu_llm.engine.arg_utils import AsyncEngineArgs # from vllm.engine.async_llm_engine import AsyncLLMEngine 更改为: from deepgpu_llm.engine.async_llm_engine import AsyncLLMEngine # from vllm.sampling_params import SamplingParams 更改为: from deepgpu_llm.sampling_params import SamplingParams # from vllm.usage.usage_lib import UsageContext 更改为: from deepgpu_llm.usage.usage_lib import UsageContext # from vllm.utils import random_uuid 更改为: from deepgpu_llm.utils import random_uuid -
启动基于DeepGPU-LLM的API服务器,该服务器可以提供模型推理服务。
# 拉起普通服务: python3 -m deepgpu_llm.entrypoints.api_server \ --model <your model> \ --trust-remote-code \ --tensor-parallel-size tp_tpsize \ --gpu-memory-utilization 0.95 # 拉起openai接口服务 python3 -m deepgpu_llm.entrypoints.openai.api_server \ --model <YOUR_MODEL> \ --trust-remote-code \ --tensor-parallel-size tp_tpsize \ --gpu-memory-utilization 0.95 -
使用
benchmark_serving.py脚本和ShareGPT数据集进行推理性能基准测试。python3 benchmark_serving.py \ --backend vllm \ --model /root/deepgpu/models/qwen1.5-7b \ --tokenizer /root/deepgpu/models/qwen1.5-7b \ --dataset-name sharegpt \ --dataset-path ShareGPT_V3_unfiltered_cleaned_split.json \ --request-rate 30 \ --num-prompts 2000 \ --port 8000