From 43498bf30975be63c4f27c40cff92519b3d93b89 Mon Sep 17 00:00:00 2001 From: Tlntin Date: Wed, 31 Jul 2024 03:36:06 +0000 Subject: [PATCH] fixup some bug --- README.md | 17 ++++-- api.py | 2 +- client/openai_function_call.py | 42 ++++++++----- client/openai_normal_client.py | 1 + client/openai_stream_client.py | 1 + config.py | 4 +- image/qwen2-1.5b-instruct-functional-call.jpg | Bin 0 -> 63706 bytes requirements.txt | 3 +- utils/inference.py | 57 +++++++++++++++--- utils/session.py | 4 ++ 10 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 image/qwen2-1.5b-instruct-functional-call.jpg diff --git a/README.md b/README.md index d58de6a..78b3479 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ ```bash git clone https://github.com/Tlntin/qwen-ascend-llm.git ``` + 2. 下载qwen1.5/qwen2的模型,选择chat模型或者instruct模型,将其放到download文件夹,仅支持huggingface下载的模型,网络不好的可以用镜像站:https://hf-mirror.com/Qwen @@ -18,7 +19,12 @@ ### 分步骤运行 ##### 步骤1:编译模型(以Qwen2-1.5B-Instruct)为例。 -1. 导出onnx,默认kv-cache长度为1024,可以根据自己的内存、显存来设置更大参数。 +1. 除了上面说的CANN环境安装外,还需额外安装一些python模块。 + ```bash + cd qwen-ascend-llm + pip install -r ./requirements.txt + ``` +2. 导出onnx,默认kv-cache长度为1024,可以根据自己的内存、显存来设置更大参数。 ```bash python3 export/export_onnx.py \ --hf_model_dir="./download/Qwen2-1.5B-Instruct" \ @@ -26,7 +32,7 @@ --kv_cache_length=1024 ``` -2. 验证onnx,返回项目根目录,运行cli_chat.py,测试一下onnx对话是否正常(注意:由于是cpu运行,所以速度较慢,请耐心等待)。 +3. 验证onnx,返回项目根目录,运行cli_chat.py,测试一下onnx对话是否正常(注意:由于是cpu运行,所以速度较慢,请耐心等待)。 ```bash python3 ./cli_chat.py \ --session_type=onnx \ @@ -34,14 +40,14 @@ --onnx_model_path="./output/onnx/qwen2_1.5b_chat.onnx" ``` -3. 改变onnx结构,目前导出的Trilu算子和Cast算子有些问题,atc命令无法识别,需要改一下结构。 +4. 改变onnx结构,目前导出的Trilu算子和Cast算子有些问题,atc命令无法识别,需要改一下结构。 ```bash python3 export/change_node.py \ --input_model_path="./output/onnx/qwen2_1.5b_chat.onnx" \ --output_model_path="./output/onnx2/qwen2_1.5b_chat.onnx" ``` -4. 转onnx为om模型, 将修改后的onnx利用atc命令导出到onnx,**注意此处的om_model_path不带`.om`后缀**。运行过程可能会有一些警告,或者子图融合报错,只要结果是提示`success`就说明没啥问题。kv_cache_length长度和第一步导出onnx时的长度保持一致。`--max_prefill_length`为prefill阶段,单次能处理的最大长度,该数值越长则越能降低首字延迟,但是相应的onnx转om的时间也会变长。设置该数值时,一般为2的指数,例如2、4、8、16等等,推理时会利用递归自动匹配合适的prefill长度,例如输入12,会匹配[8, 4]。当前默认数值为8,如果设置为1,则不会开启动态shape推理功能。 +5. 转onnx为om模型, 将修改后的onnx利用atc命令导出到onnx,**注意此处的om_model_path不带`.om`后缀**。运行过程可能会有一些警告,或者子图融合报错,只要结果是提示`success`就说明没啥问题。kv_cache_length长度和第一步导出onnx时的长度保持一致。`--max_prefill_length`为prefill阶段,单次能处理的最大长度,该数值越长则越能降低首字延迟,但是相应的onnx转om的时间也会变长。设置该数值时,一般为2的指数,例如2、4、8、16等等,推理时会利用递归自动匹配合适的prefill长度,例如输入12,会匹配[8, 4]。当前默认数值为8,如果设置为1,则不会开启动态shape推理功能。 ```bash python3 export/onnx2om.py \ --hf_model_dir="./download/Qwen2-1.5B-Instruct" \ @@ -81,9 +87,10 @@ ```bash # openai_stream_client.py 流式请求,类似打字机效果 # openai_normal_client.py 非流式请求,需要等模型推理完再返回 - # openai_function_call.py 测试function_call + # openai_function_call.py 测试function_call,该功能启用时建议增加max_input_length和kv_cache_length的长度。 ``` +- functional_call demo展示(使用qwen2-1.5b-instruct)![](./image/qwen2-1.5b-instruct-functional-call.jpg) ### 当前功能 - [x] 导出onnx, om模型 diff --git a/api.py b/api.py index 2b5faf2..ddb8278 100644 --- a/api.py +++ b/api.py @@ -350,7 +350,7 @@ def parse_response(response): # completion mode, not chat mode -def text_complete_last_message(history, stop_words_ids, max_new_tokens): # sampling_config, : +def text_complete_last_message(history, stop_words_ids, sampling_config, max_new_tokens): im_start = "<|im_start|>" im_end = "<|im_end|>" prompt = f"{im_start}system\nYou are a helpful assistant.{im_end}" diff --git a/client/openai_function_call.py b/client/openai_function_call.py index 574cadd..fda27d4 100644 --- a/client/openai_function_call.py +++ b/client/openai_function_call.py @@ -5,6 +5,7 @@ import time import random import json +import asyncio urllib3.disable_warnings() @@ -100,7 +101,8 @@ def get_current_weather(location: str): if len(location_data) > 0: location_dict = location_data[0] city_id = location_dict["id"] - weather_res = weather.get_weather_from_api(city_id) + # 由于输入长度限制,这里只取一天的天气,有条件的可以自己更改。 + weather_res = weather.get_weather_from_api(city_id)[:1] n_day = len(weather_res) return f"查询到最近{n_day}天的天气。" + json.dumps(weather_res, ensure_ascii=False) else: @@ -109,16 +111,18 @@ def get_current_weather(location: str): def call_qwen(messages, functions=None): # print(messages) if functions: - response = client.chat.completions.create( - model="Qwen", messages=messages, functions=functions + return client.chat.completions.create( + model="Qwen", + messages=messages, + functions=functions, + temperature=0, ) else: - response = client.chat.completions.create( - model="Qwen", messages=messages + return client.chat.completions.create( + model="Qwen", + messages=messages, + temperature=0 ) - # print(response) - # print(response.choices[0].message.content) - return response def chat(query: str): @@ -148,6 +152,7 @@ def chat(query: str): "content": query, } ] + print("[INFO] Invoke AI and ask if it need to call the plugin.") response = call_qwen(messages, functions) res = response.choices[0].message message_dict = { @@ -178,19 +183,23 @@ def chat(query: str): had_params = list(function_params.keys()) if len(had_params) != len(require_params): raise Exception("ERROR, need to do other fill params") - - - response = eval(function_name)(**function_params) + print("[INFO] will call funtion {} with params {}".format( + function_name, function_params + )) + fun_response = eval(function_name)(**function_params) + print("[INFO] call function response is: ", response) message = { "role": "function", "name": function_name, } - if len(response) > 0: - message["content"] = response + if len(fun_response) > 0: + message["content"] = fun_response else: message["content"] = "未找到任何信息" messages.append(message) + print("[INFO] send function response to AI") response = call_qwen(messages, functions) + return response return response @@ -200,6 +209,7 @@ def chat(query: str): print("目前已支持天气查询插件") print("=" * 20) query = "北京天气如何?穿短袖会不会冷?" -print("用户输入:", query) -res = chat(query) -print("回答结果:", res.choices[0].message.content) +print("User:", query) +response = chat(query) +res = response.choices[0].message.content +print("ChatBot: ", res) \ No newline at end of file diff --git a/client/openai_normal_client.py b/client/openai_normal_client.py index f11c745..3ff73b0 100644 --- a/client/openai_normal_client.py +++ b/client/openai_normal_client.py @@ -13,6 +13,7 @@ break if prompt == 'clear': messages = messages[:1] + print("ChatBot: 已清理历史对话信息。") continue messages.append({"role": "user", "content": prompt}) completion = client.chat.completions.create( diff --git a/client/openai_stream_client.py b/client/openai_stream_client.py index 191be54..eaa0ebb 100644 --- a/client/openai_stream_client.py +++ b/client/openai_stream_client.py @@ -14,6 +14,7 @@ break if prompt == 'clear': messages = messages[:1] + print("ChatBot: 已清理历史对话信息。") continue messages.append({"role": "user", "content": prompt}) response = client.chat.completions.create( diff --git a/config.py b/config.py index 4e9348e..ff31a45 100644 --- a/config.py +++ b/config.py @@ -10,8 +10,8 @@ def __init__( onnx_model_path: str, session_type: str = "acl", # 支持acl和onnx两种,acl即Ascend C Language device_id: int = 0, - sampling_method: str = "top_k", - sampling_value: float = 10, + sampling_method: str = "top_p", # 支持 greedy, top_p, top_k + sampling_value: float = 0.8, temperature: float = 0.7, max_batch: int = 1, max_input_length: int = 512, # 输入长度的最大数值 diff --git a/image/qwen2-1.5b-instruct-functional-call.jpg b/image/qwen2-1.5b-instruct-functional-call.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6dc53889ccc41aa87ef6886550d0b436c8c0aeb6 GIT binary patch literal 63706 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�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 MeNYJx^xx`#18C?1x&QzG literal 0 HcmV?d00001 diff --git a/requirements.txt b/requirements.txt index 9ef3435..378afc1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,11 @@ onnx==1.16.1 onnxruntime==1.18.1 +transformers==4.37.0 # onnxruntime-cann==1.18.1 torch==2.1.0 torch-npu==2.1.0.post6 tqdm fastapi uvicorn -sse_starlette +sse_starlette==1.6.5 openai \ No newline at end of file diff --git a/utils/inference.py b/utils/inference.py index 469cae0..d77dc25 100644 --- a/utils/inference.py +++ b/utils/inference.py @@ -124,7 +124,7 @@ def stream_predict( if history is None: history = [] sampling_value = sampling_config.get("sampling_value", self.sampling_value) - temperature = sampling_config.get("sampling_value", self.temperature) + temperature = sampling_config.get("temperature", self.temperature) messages = [{"role": "system", "content": system_prompt}] # print("prompt: ", prompt) with self.lock: @@ -144,6 +144,8 @@ def stream_predict( input_ids = self.tokenizer( [text], return_tensors="np" )["input_ids"].astype(np.int64).reshape(1, -1) + input_ids = input_ids[:, -self.max_input_length:] + print("input_ids shape: ", input_ids.shape) self.first = False ids_list = [] text_length = 0 @@ -158,9 +160,20 @@ def stream_predict( temp_list = trange(max_output_len, desc="decode") else: temp_list = range(max_output_len) + prefill_show_progress = False for i in temp_list: - prefill_show_progress = (i == 0) - logits = self.session.run(input_ids, show_progress=prefill_show_progress)[0] + if i == 0: + if show_progress: + prefill_show_progress = True + # reset counter + self.session.run_times = 0 + self.session.kv_cache.real_kv_size = 0 + else: + prefill_show_progress = False + logits = self.session.run( + input_ids, + show_progress=prefill_show_progress + )[0] input_ids = self.sample_logits( logits[0][-1:], self.sampling_method, @@ -207,7 +220,7 @@ def predict( if history is None: history = [] sampling_value = sampling_config.get("sampling_value", self.sampling_value) - temperature = sampling_config.get("sampling_value", self.temperature) + temperature = sampling_config.get("temperature", self.temperature) messages = [{"role": "system", "content": system_prompt}] # print("prompt: ", prompt) with self.lock: @@ -227,6 +240,7 @@ def predict( input_ids = self.tokenizer( [text], return_tensors="np" )["input_ids"].astype(np.int64).reshape(1, -1) + input_ids = input_ids[:, -self.max_input_length:] self.first = False ids_list = [] # text_length = 0 @@ -240,9 +254,20 @@ def predict( temp_list = trange(max_output_len, desc="decode") else: temp_list = range(max_output_len) + prefill_show_progress = False for i in temp_list: - prefill_show_progress = (i == 0) - logits = self.session.run(input_ids, show_progress=prefill_show_progress)[0] + if i == 0: + if show_progress: + prefill_show_progress = True + # reset counter + self.session.run_times = 0 + self.session.kv_cache.real_kv_size = 0 + else: + prefill_show_progress = False + logits = self.session.run( + input_ids, + show_progress=prefill_show_progress + )[0] input_ids = self.sample_logits( logits[0][-1:], self.sampling_method, @@ -275,9 +300,10 @@ def generate( show_progress: bool = False, ): sampling_value = sampling_config.get("sampling_value", self.sampling_value) - temperature = sampling_config.get("sampling_value", self.temperature) + temperature = sampling_config.get("temperature", self.temperature) self.first = False ids_list = [] + input_ids = input_ids[:, -self.max_input_length:] input_length = input_ids.shape[1] max_output_len = self.max_output_length - input_length max_output_len = min(max_output_len, max_new_tokens) @@ -285,9 +311,20 @@ def generate( temp_list = trange(max_output_len, desc="decode") else: temp_list = range(max_output_len) + prefill_show_progress = False for i in temp_list: - prefill_show_progress = (i == 0) - logits = self.session.run(input_ids, show_progress=prefill_show_progress)[0] + if i == 0: + if show_progress: + prefill_show_progress = True + # reset counter + self.session.run_times = 0 + self.session.kv_cache.real_kv_size = 0 + else: + prefill_show_progress = False + logits = self.session.run( + input_ids, + show_progress=prefill_show_progress + )[0] input_ids = self.sample_logits( logits[0][-1:], self.sampling_method, @@ -302,7 +339,7 @@ def generate( break ids_list.append(input_ids[0].item()) text_out = self.tokenizer.decode(ids_list) - print("Debug: ", text_out) + # print("Debug: ", text_out) # stop_word = is_stop_word_or_prefix(text_out, ["[|Human|]", "[|AI|]"]) self.state['message'] = text_out with self.lock: diff --git a/utils/session.py b/utils/session.py index e76b361..2b4f81f 100644 --- a/utils/session.py +++ b/utils/session.py @@ -181,6 +181,10 @@ def run_some( seq_length: int = 1, is_dynamic: bool = False ): + # print( + # "self.run_times: ", self.run_times, + # "real kv size: ", self.kv_cache.real_kv_size + # ) self.run_times += seq_length cache, mask, pos_ids = self.kv_cache.get_inputs(seq_length) result:List[np.ndarray] = self.model.inference(