Advanced DeepGPU-LLM API and examples
DeepGPU-LLM, an inference engine from Alibaba Cloud, optimizes the inference process for large language models on GPU cloud servers. It provides a free, high-performance, low-latency inference service. DeepGPU-LLM provides APIs for model loading and model inference. After installing DeepGPU-LLM on a GPU cloud server, use its APIs to run model inference for improved efficiency and accuracy.
DeepGPU-LLM is a large language model (LLM) inference engine developed by Alibaba Cloud for GPU instances. To learn more, see What is the DeepGPU-LLM inference engine.
(Optional) Convert model format
To use DeepGPU-LLM for inference optimization, convert an open-source, non-quantized model from the Hugging Face format to a DeepGPU-LLM-compatible format. Converting some large language models requires substantial CPU memory. To address this, you can either convert the model in advance or increase CPU memory. For example, you can set the --shm-size parameter in a Docker container to automatically convert the model format upon loading.
DeepGPU-LLM automatically converts large language models as they are loaded. If your model does not have strict CPU memory requirements, you can use the DeepGPU-LLM API to load the original model directly.
DeepGPU-LLM provides a unified model conversion command, huggingface_model_convert. Before running the model conversion script, review the following parameters:
|
Parameter |
Description |
|
|
Displays help information. |
|
|
Specifies the path to the original model to convert. The model can be downloaded from Hugging Face or ModelScope. |
|
|
Specifies the output directory for the converted model. |
|
|
Specifies the number of GPUs to use for inference. |
|
|
Specifies the precision for the model weights, such as fp16 or bf16. |
|
|
Specifies a custom name for the model. |
|
|
Specifies the vCPU core count to use for model conversion. |
-
Example 1: Llama 2-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 -
Example 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
If the huggingface_model_convert command is not found, your DeepGPU version is outdated. You can upgrade your DeepGPU-LLM version. For instructions, see (Optional) Upgrade DeepGPU-LLM. Alternatively, depending on the LLM model type, you can replace the model field with the specific LLM name and then convert the model. Check the help output to adjust the corresponding parameters.
DeepGPU-LLM API
Model loading functions
DeepGPU-LLM provides deepgpu_model, a unified model processing class with two model loading functions: __init__ and from_pretrained.
Loading functions
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)
-
The
__init__function loads a pre-converted model. The following table describes its parameters.Parameter
Description
model_pathPath to the pre-converted model directory.
NoteThis is typically an
x-gpudirectory, wherexis the number of GPUs. This directory is automatically generated during the model conversion process.tensor_para_sizeSpecifies the number of GPUs to use. This value must be consistent with the number of GPUs set during model conversion.
precisionThe weight quantization level. Valid values:
-
0: FP16 precision.
-
1: INT8 quantization.
-
3: INT4 quantization.
-
5: FP8 precision.
Default: 0.
kv_cache_quant_levelThe KV cache quantization level. Valid values:
-
0: No quantization.
-
1: K8_V8 quantization (recommended).
-
2: K8_V4 quantization.
-
3: K4_V4 quantization.
Default: 0.
generation_configModel configuration parameters. For more information, see Model parameter class (DeepGPUGenerationConfig).
NoteIf this parameter is not set, the default parameters in the model's configuration file are used.
is_gemm_tuningSpecifies whether to tune for the optimal kernel. Optimal kernels for common GPUs are pre-optimized and included in the installation package. Valid values:
-
False: Does not tune for the optimal kernel.
-
True: Tunes for the optimal kernel.
Default: False.
load_pretrainedSpecifies whether the model being loaded is an original model. Valid values:
-
False: Loads a model whose format has already been converted.
-
True: Loads an original model whose format has not been converted. This option is not intended for direct use and is called internally by the
from_pretrainedfunction to load original models.
Default: False.
page_sizeSpecifies the size of the memory block used by PagedAttention.
gpu_utilizationSpecifies the proportion of GPU memory to use.
max_batch_sizeSpecifies the maximum number of requests that can be processed concurrently.
NoteIf the available GPU memory is insufficient to support the configured value, the system automatically adjusts this value.
max_context_token_numSpecifies the maximum number of tokens in the context. This value cannot be less than the value of
session_len.session_lenSpecifies the session length limit, which is the total number of input and output tokens.
Set this parameter if the required session length exceeds the default value.
data_setSpecifies the directory of the calibration data for FP8 quantization.
This parameter is only required when using FP8 precision.
-
-
The
from_pretrainedfunction loads open-source models from Hugging Face or ModelScope and automatically converts them on the fly.This class method calls
__init__to create adeepgpu_modelinstance. It loads an original model, converts it, and then initializes it. For parameter details, see the__init__function's table above.
Using loading functions
-
Load a model by using the
__init__function of thedeepgpu_modelclass.Import the
deepgpu_modelclass from thedeepgpu_llm.deepgpu_modelmodule, and then instantiate it to initialize the model. In this case,args.model_dirmust point to the pre-converted model directory. The following code provides an example: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) -
Load an original model by using the
from_pretrainedfunction of thedeepgpu_modelclass.Call the
deepgpu_model.from_pretrainedfunction to load an original model, which performs on-the-fly conversion and initialization. In this case,args.model_dirpoints to the directory of the original model from Hugging Face or ModelScope. The following is a code sample: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)
Model inference functions
DeepGPU-LLM provides several inference APIs. You can call these APIs in either offline mode or serving mode, depending on your needs.
Model inference in offline mode
The offline mode inference APIs include a standard output function (one-time output) and a streaming output function.
-
Standard output function (generate)
The standard output function returns the complete result at once. The output is nested within multiple layers and can be complex. To extract the required information, unpack the output layer by layer. The
generatefunction is defined as follows:def generate(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)When calling
model.generateto perform model inference, set thegeneration_configparameter using theDeepGPUGenerationConfigclass. For more information, see Common classes. The following code shows how to callgenerate: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)Parameter
Description
inputsAn array of token IDs generated by the
tokenizer.The
queryis the actual input text. For multiple inputs, tokenize each input and add the resulting token IDs to theinputsarray.outputThis is a nested object that you must unpack to get
outputY, which contains the actual output token IDs. Call thetokenizer.decodefunction to convert the IDs to text.NoteIf there are multiple inputs, there will be multiple corresponding outputs. You can locate the output for a specific batch item using
outputX[batch_id][0]. -
Streaming output function (stream_generate)
Streaming output allows you to display the generated content to the user in real-time as the inference progresses. The
stream_generatefunction is defined as follows:def stream_generate(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None, skip_inputs = False)stream_generateis a member function of the model class. The following table describes its parameters:Parameter
Description
input_idsThe input parameter that provides input data for the model. For more information, see Standard output function (generate).
generation_configRuntime parameters. For parameter definitions, see Common classes.
skip_inputsSpecifies whether to exclude the input from the generated output. Valid values:
-
True: Excludes the input content.
-
False: Includes the input content.
The following is a code sample for calling
stream_generate. First, create astreamerinstance by callingDeepGPUStreamer. Then, call thestream_generatefunction to start the inference. The function returns a generator that you can iterate over for real-time results.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, }Parameter
Description
printable_strThe text corresponding to the token generated in the current step.
responseThe aggregated text from all preceding generation steps.
total_lenThe total number of tokens generated so far.
-
Model inference in serving mode
This mode is designed for multi-user, multi-request scenarios. DeepGPU-LLM provides three concurrent invocation functions to fit different codebases: a standard function, an async function, and an async function with a request ID.
-
Standard invocation function (generate_cb)
For standard (non-async) callers, use the
generate_cbfunction. It is defined as follows:def generate_cb(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)Parameter
Description
input_idsThe input parameter that provides input data for the model. For more information, see Standard output function (generate).
generation_configThe parameters used for model inference.
Calling
generate_cbstarts the model inference and returns a generator. You can then iterate over this generator to get real-time output. In each iteration, append the current output textprintable_strto build the completeresponse.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 invocation function (generate_cb_async)
For async callers, use
generate_cb_async. The async invocation function is defined as follows:async def generate_cb_async(self, input_ids, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)The usage of this function is nearly identical to that of
generate_cb, but you must use anasync forloop to iterate over the results.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, } -
Async invocation function with request ID (generate_cb_async_id)
If you need to manage multiple concurrent requests by their request IDs, call the
generate_cb_async_idfunction. Its parameters are similar to those ofgenerate_cb_async, but it includes an additionalrequest_idparameter to distinguish between different requests and their corresponding results. The function is defined as follows:async def generate_cb_async_id(self, input_ids, request_id: int = 0, generation_config: typing.Optional[DeepGPUGenerationConfig] = None)When calling this function, use the
RequestCounterclass from the Request ID handler class (RequestCounter) to manage therequest_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_id(inputs, request_id=request_id, 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, }
Common classes
The deepgpu_utils.py module provides utilities for the DeepGPU-LLM inference API. deepgpu_utils.py defines several common classes, such as DeepGPUGenerationConfig, DeepGPUStreamer, and RequestCounter. These classes manage the model's runtime environment, handle concurrent requests, and track request execution. You can import these classes from deepgpu_utils.py with the following code.
from deepgpu_llm.deepgpu_utils import DeepGPUGenerationConfig, DeepGPUStreamer, RequestCounter
-
DeepGPUGenerationConfig
The
DeepGPUGenerationConfigclass configures inference parameters for the model. These parameters are optional; if omitted, DeepGPU-LLM automatically loads the initial parameters from the model configuration file.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
The
DeepGPUStreamerclass handles streaming output and outputs from concurrent requests for a large language model.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)Function name
Description
__init__()Initializes the internal tokenizer and the string buffer used for printing.
handle_str()Takes a token ID, converts it to natural language text, places it in the string buffer, and returns the printable text from the buffer.
end()Returns any remaining text in the string buffer.
-
RequestCounter
The
RequestCounterclass manages request IDs in multi-request scenarios.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) -> intFunction name
Description
__init__()Initializes the counter. The starting value defaults to 0 but can be customized with the
startparameter.__next__()Returns the current counter value and then increments the internal counter by 1.
reset()Resets the internal counter to 0.
add()Returns the current counter value and then adds len to it.
cur()Returns the current counter value.
DeepGPU-LLM code examples
This topic provides DeepGPU-LLM code examples to help you get started.
Offline code examples
-
Simple Llama model example
This example uses the llama2-7b-chat model. Before running the code, ensure you have converted the model. You can also adjust parameters such as the model directory, number of GPUs, and quantization precision as needed.
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 quantization, 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]))The code produces the following output:
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 streaming output example
This example shows how to run a Qwen-7B model on a single GPU. You can adjust the
precision(quantization precision),kv_cache_quant_level, andtp_size(number of GPUs) for faster performance and reduced GPU memory usage. The following code streams the output and measures performance.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 quantization, 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\nHi, could you introduce the tourist attractions in Hangzhou?<|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")Run the code to view the streamed response and experience the inference speed of DeepGPU-LLM.
running in fp16 mode, cb is True model init over! response : As the capital city of China's Zhejiang province, Hangzhou has a rich historical and cultural heritage, as well as many beautiful natural landscapes and cultural attractions. Here are some of Hangzhou's famous tourist attractions: 1. **West Lake**: West Lake is one of the most famous lakes in China, praised as a "paradise on earth." It is renowned for its beautiful scenery, rich history, and ancient legends. There are many famous sites around the lake, such as Broken Bridge, Leifeng Pagoda, and Dawn on the Su Causeway in Spring. 2. **Xixi National Wetland Park**: Located in the western part of Hangzhou, this is a large wetland park that combines natural ecology, cultural relics, and leisure activities. Here, you can experience the unique charm of a Jiangnan water town and see a variety of wildlife. 3. **Songcheng Park**: This is a large theme park centered on the culture of the Song Dynasty. It recreates the street life of the Song Dynasty, allowing visitors to experience its history and culture through performances and interactive experiences. The park also features the famous show "The Romance of the Song Dynasty," which is an excellent way to learn about the era. 4. **Lingyin Temple**: Located at the foot of Feilai Peak, north of West Lake, this is a Buddhist temple with a long history. The temple is surrounded by a tranquil environment with beautiful mountains and clear water, making it an ideal place for meditation and prayer. 5. **Qiantang River Tidal Bore**: The massive tidal bore on the Qiantang River, which occurs on the 18th day of the eighth lunar month, is a natural wonder that attracts many tourists. The surging tide is a powerful and unique spectacle endowed by nature to Hangzhou. 6. **Hangzhou Songcheng Site Museum**: Located on the site of the Southern Song Imperial City, this museum showcases the history of the Southern Song Dynasty's politics, economy, culture, and society. The museum has a rich collection of artifacts and multimedia displays to help visitors gain a deeper understanding of Southern Song history. 7. **Wuzhen**: Although Wuzhen is near Hangzhou, its unique water town scenery and deep cultural heritage make it a must-see destination. Wuzhen preserves many buildings from the Ming and Qing dynasties, showcasing the classic features of a Jiangnan water town. 8. **Longjing Tea Plantations by West Lake**: Near West Lake, you can visit and experience the traditional process of making Longjing tea, taste authentic Longjing tea, and enjoy the peaceful rural landscape. These are just a few of the many attractions in Hangzhou. Each place has its own unique charm, whether it is natural scenery or cultural history, allowing you to experience the beauty of Hangzhou. time : 5.061952114105225 speed: 90.87403231614961 tokens/sNoteTo view streaming output examples for other LLM models, run the following command to find the DeepGPU-LLM installation directory. You can then view the code in the corresponding
llama_cli,chatglm_cli,baichuan_cli,qwen_cli, ordeepgpu_cliscripts. Note that thedeepgpu_cliscript is only available in DeepGPU-LLM versions 24.9 and later.pip show -f deepgpu-llm -
Multi-batch input example
In multi-batch scenarios, properly handling input and output is crucial. For information about how different models handle input and output, see Standard Output Function generate (One-time Output).
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 quantization, 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 =["Hello, who are you?", "Hello, please introduce the tourist attractions in Hangzhou.", "Hello, please introduce the tourist attractions in Beijing.", "Hello, please introduce the tourist attractions in Xinjiang.", "Hello, please introduce the tourist attractions in Tibet."] 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)))The code produces the following output:
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 Hello, who are you? assistant Hello! I am a large language model from Alibaba Cloud, and my name is Qwen. As an AI assistant, my mission is to help users get accurate and useful information and to solve their problems and questions. You can ask me about various fields of knowledge, technical issues, or anything you want to know. I will do my best to help. What can I do for you? response[ 1 ] : user Hello, please introduce the tourist attractions in Hangzhou. assistant Hello, Hangzhou is a famous tourist city in China with many well-known attractions. For example, West Lake, which is the most famous lake in China, features ten scenic spots like "Dawn on the Su Causeway in Spring" and "Breeze-Ruffled Lotuses at Quyuan Garden". There's also Lingyin Temple, the largest Buddhist monastery in Hangzhou with a long history; Songcheng Park, a theme park based on the culture of the Song Dynasty where you can experience life from that era; Xixi National Wetland Park, a large wetland park that integrates ecological protection, leisure tourism, and cultural exhibition; and other famous attractions like the Liuhe Pagoda, Three Pools Mirroring the Moon, and the Qiantang River Bridge. I hope you get a chance to visit Hangzhou. response[ 2 ] : user Hello, please introduce the tourist attractions in Beijing. assistant Beijing is the capital of China and has numerous famous tourist attractions. For example, the Forbidden City, which is the most important imperial palace in Chinese history; the Great Wall, a UNESCO World Heritage site and an outstanding example of ancient Chinese defensive engineering; the Summer Palace, a well-preserved royal garden; Tiananmen Square, a symbol of the People's Republic of China; and Nanluoguxiang, a hutong (alley) full of old Beijing charm. Additionally, there are other famous spots like Beihai Park, the Old Summer Palace (Yuanmingyuan), and the 798 Art District, which are must-visit places for tourists in Beijing.
Serving code examples
-
Server code example
Run the
fastapi_server.pyscript to receive text generation requests, process them with the DeepGPU model, and return the results.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)Run the following command to start the service.
python3 fastapi_server.py -i /mnt/models_deepgpu/Qwen2-7B-Instruct/1-gpu -t /mnt/models_deepgpu/Qwen2-7B-Instruct -tp 1The following output indicates that the service started successfully.
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)NoteYou can refer to vLLM's official
benchmark_serving.pycode. Simply replaceimport vllmwithimport deepgpu. For more information, see More examples (Switch vLLM to the DeepGPU-LLM inference engine). -
Client Python code
This example provides an asynchronous Python script that sends a request to an HTTP service and receives a streaming response for text generation.
import requests import json import time import aiohttp import asyncio import random import os url = "http://0.0.0.0:8000/generate" # Normal service mode # url = "http://0.0.0.0:8000/v1/completions" # OpenAI API-compatible service mode headers = {"User-Agent": "Benchmark Client"} # Normal service mode # headers = { # "Authorization": f"Bearer {os.environ.get('OPENAI_API_KEY')}" # OpenAI API-compatible service mode # } 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 # Data for the OpenAI-compatible service # data = { # "model": '/root/models/Llama-2-7b-chat-hf/', # "prompt": prompt, # "temperature": 0.0, # "best_of": 1, # "max_tokens": 512, # "stream": True, # } # Data for the normal service 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 =["Hello, who are you?", "Please introduce the tourist attractions in Hangzhou.", "Please introduce the tourist attractions in Beijing.", "Please describe the historical changes of Hangzhou.", "Do you know what BAT stands for?", "How do I choose a major after being admitted to a university?", "What are some of the best universities in Zhejiang?"] 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))The code produces the following output:
[prompt]: Do you know what BAT stands for? It is an acronym for Baidu, Alibaba, and Tencent, the three giants of China's internet industry. Baidu started with its search engine, Alibaba is famous for e-commerce, and Tencent is known for its social networking and gaming businesses. However, behind these three giants, there was a more mysterious event: the "3Q War". In 2010, a fierce online battle broke out between Tencent and Qihoo 360, which became known as the "3Q War". During this conflict, Tencent launched a software called QQ Doctor, designed to clean users' computers and protect QQ users from viruses and malware. However, this software was strongly opposed by Qihoo 360, which argued that it violated user privacy and involved forced installation. Subsequently, Qihoo 360 released a software called "360 Safeguard" to directly compete with QQ Doctor. This war eventually led to a severe division among the user bases of the two companies, with slogans related to the "3Q War" even appearing in some regions. The conflict not only caused huge financial losses for both companies but also had a profound impact on the entire Chinese internet industry. Since then, Tencent and Qihoo 360 have gradually reconciled and started to cooperate in some areas, but the war is still considered a landmark event in the history of China's internet. Although many years have passed since the "3Q War," the lessons it taught are still worth considering. First, competition does not have to mean destroying the opponent; instead, a win-win situation should be sought. Second, respecting user rights and privacy is a fundamental principle that any company should follow. Finally, resolving disputes through dialogue and negotiation, rather than extreme measures, is an important path to long-term stable development. These lessons provide important guidance for the current and future internet competition landscape. Therefore, whether at the individual or corporate level, we should learn from these experiences to promote a healthier and more harmonious internet ecosystem. Latency: 4.07001543045043995 seconds -
Client curl command
After the service starts, run the following command to request text generation from the server.
curl -X POST "http://0.0.0.0:8000/generate" \ -H "Content-Type: application/json" \ -H "User-Agent: Benchmark Client" \ -d '{"prompt": "Please describe the historical changes of Hangzhou.", "stream": false, "max_tokens": 128}'NoteBecause
curldoes not support streaming output, thestreamparameter must be set tofalse.The command produces the following output:
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": "Please describe the historical changes of Hangzhou. ", "stream": false, "max_tokens": 128}' {"text":" Hangzhou is one of China's famous historical and cultural cities, with a long history and deep cultural heritage. Here is a brief introduction to the historical changes of Hangzhou:\n1. Ancient period: Traces of human activity in the Hangzhou area date back to the Neolithic Age. During the Xia, Shang, and Zhou dynasties, this area was the territory of the Yue state. During the Spring and Autumn and Warring States periods, with the rivalry between the Wu and Yue states, the Hangzhou area belonged to Yue. In the Qin and Han dynasties, Hangzhou was part of the Kuaiji Commandery. During the Eastern Jin dynasty, it became an important political, economic, and cultural center in the Jiangnan region.\n2. Tang and Song dynasties: During the Tang Dynasty, Hangzhou became one of the largest commercial cities in the Jiangnan region. In the Song Dynasty, Hangzhou became"}
Switch from vLLM to DeepGPU-LLM
DeepGPU-LLM lets you switch your vLLM codebase to the DeepGPU-LLM inference engine for improved performance and additional features without major code changes. The following examples show how to adapt your code for offline inference and serving.
vLLM-compatible offline inference
-
Get an offline inference example from vLLM.
The
offline_inference.pyscript is shown below: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}") -
Modify the vLLM example to use the DeepGPU-LLM inference engine.
To switch the inference engine, change the import from
vllmtodeepgpu_llmand update the model path to your converted DeepGPU model file.# Change from vllm import LLM, SamplingParams to: from deepgpu_llm import LLM, SamplingParams # Change llm = LLM(model="facebook/opt-125m") to: llm = LLM("path/to/your/deepgpu_model")
vLLM-compatible serving
-
Get the serving example from vLLM.
Source: api_server.
-
Modify the vLLM example to use the DeepGPU-LLM inference engine.
Modify the vLLM serving code by changing the
vllmimports to theirdeepgpu_llmequivalents.# Change from vllm.engine.arg_utils import AsyncEngineArgs to: from deepgpu_llm.engine.arg_utils import AsyncEngineArgs # Change from vllm.engine.async_llm_engine import AsyncLLMEngine to: from deepgpu_llm.engine.async_llm_engine import AsyncLLMEngine # Change from vllm.sampling_params import SamplingParams to: from deepgpu_llm.sampling_params import SamplingParams # Change from vllm.usage.usage_lib import UsageContext to: from deepgpu_llm.usage.usage_lib import UsageContext # Change from vllm.utils import random_uuid to: from deepgpu_llm.utils import random_uuid -
Start the DeepGPU-LLM-based API server to provide a model inference service.
# Start the standard service: python3 -m deepgpu_llm.entrypoints.api_server \ --model <YOUR_MODEL> \ --trust-remote-code \ --tensor-parallel-size <TENSOR_PARALLEL_SIZE> \ --gpu-memory-utilization 0.95 # Start the OpenAI-compatible service: python3 -m deepgpu_llm.entrypoints.openai.api_server \ --model <YOUR_MODEL> \ --trust-remote-code \ --tensor-parallel-size <TENSOR_PARALLEL_SIZE> \ --gpu-memory-utilization 0.95 -
Use the
benchmark_serving.pyscript and the ShareGPT dataset to run an inference performance benchmark.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