基于ChatGLM2和OpenVINO?打造中文聊天助手
ChatGLM 是由清華大學(xué)團(tuán)隊(duì)開發(fā)的是一個(gè)開源的、支持中英雙語的類 ChatGPT 大語言模型,它能生成相當(dāng)符合人類偏好的回答, ChatGLM2 是開源中英雙語對(duì)話模型 ChatGLM 的第二代版本,在保留了初代模型對(duì)話流暢、部署門檻較低等眾多優(yōu)秀特性的基礎(chǔ)之上,通過全面升級(jí)的基座模型,帶來了更強(qiáng)大的性能,更長的上下文,并且該模型對(duì)學(xué)術(shù)研究完全開放,登記后亦允許免費(fèi)商業(yè)使用。接下來我們分享一下如何基于 ChatGLM2-6B 和 OpenVINO? 工具套件來打造一款聊天機(jī)器人。
注1:由于 ChatGLM2-6B 對(duì)在模型轉(zhuǎn)換和運(yùn)行過程中對(duì)內(nèi)存的占用較高,推薦使用支持 128Gb 以上內(nèi)存的的服務(wù)器終端作為測(cè)試平臺(tái)。
注2:本文僅分享部署 ChatGLM2-6B 原始預(yù)訓(xùn)練模型的方法,如需獲得自定義知識(shí)的能力,需要對(duì)原始模型進(jìn)行 Fine-tune;如需獲得更好的推理性能,可以使用量化后的模型版本。
OpenVINO?
模型導(dǎo)出
**第一步,**我們需要下載 ChatGLM2-6B 模型,并將其導(dǎo)出為 OpenVINO? 所支持的IR格式模型進(jìn)行部署,由于 ChatGLM 團(tuán)隊(duì)已經(jīng)將 6B 版本的預(yù)訓(xùn)練模型發(fā)布在 Hugging Face 平臺(tái)上,支持通過 Transformer 庫進(jìn)行推理,但不支持基于Optimum 的部署方式(可以參考Llama2的文章),因此這里我們需要提取 Transformer 中的 ChatGLM2 的 PyTorch 模型對(duì)象,并實(shí)現(xiàn)模型文件的序列化。主要步驟可以分為:
1.獲取 PyTorch 模型對(duì)象
通過Transformer庫獲取PyTorch對(duì)象,由于目前Transformer中原生的ModelForCausalLM類并不支持ChatGLM2模型架構(gòu),因此需要添加trust_remote_code=True參數(shù),從遠(yuǎn)程模型倉庫中獲取模型結(jié)構(gòu)信息,并下載權(quán)重。
2.模擬并獲取模型的輸入輸出參數(shù)
在調(diào)用 torch.onnx.export 接口將模型對(duì)象導(dǎo)出為 ONNX 文件之前,我們首先需要獲取模型的輸入和輸出信息。由于 ChatGLM2 存在 KV cache 機(jī)制,因此這個(gè)步驟中會(huì)模擬第一次文本生成時(shí)不帶 cache 的輸入,并將其輸出作為第二次迭代時(shí)的 cache 輸入,再通過第二次迭代來驗(yàn)證輸入數(shù)據(jù)是否完整。以下分別第一次和第二次迭代的 PyTorch 代碼:
3.導(dǎo)出為ONNX格式
在獲取完整的模型輸入輸出信息后,我們可以利用 torch.onnx.export 接口將模型導(dǎo)出為 ONNX 文件,如果通過模型結(jié)構(gòu)可視化工具查看該文件的話,不難發(fā)現(xiàn)原始模型對(duì)象中 attention_mask 這個(gè) input layer 消失了,個(gè)人理解是因?yàn)?attention_mask 對(duì)模型的輸出結(jié)果沒有影響,并且其實(shí)際功能已經(jīng)被 position_ids 代替了,所以 ONNX 在轉(zhuǎn)化模型的過程中自動(dòng)將其優(yōu)化掉了。
4.利用 OpenVINO? Model Optimizer 進(jìn)行格式轉(zhuǎn)換
最后一步可以利用 OpenVINO? 的 Model Optimizer 工具將模型文件轉(zhuǎn)化為 IR 格式,并壓縮為 FP16 精度,將較原始 FP32 模式,F(xiàn)P16 模型可以在保證模型輸出準(zhǔn)確性的同時(shí),減少磁盤占用,并優(yōu)化運(yùn)行時(shí)的內(nèi)存開銷。
**模型部署 **
當(dāng)完成 IR 模型導(dǎo)出后,我們首先需要構(gòu)建一個(gè)簡(jiǎn)單的問答系統(tǒng) pipeline,測(cè)試效果。如下圖所示, Prompt 提示會(huì)送入 Tokenizer 進(jìn)行分詞和詞向量編碼,然后有 OpenVINO? 推理獲得結(jié)果(藍(lán)色部分),來到后處理部分,我們會(huì)把推理結(jié)果進(jìn)行進(jìn)一步的采樣和解碼,最后生成常規(guī)的文本信息。這里 Top-K 以及 Top-P作 為答案的篩選方法,最終從篩選后的答案中進(jìn)行隨機(jī)采樣輸出結(jié)果。
圖:ChatGLM2 問答任務(wù)流程
整個(gè) pipeline 的大部分代碼都可以套用文本生成任務(wù)的常規(guī)流程,其中比較復(fù)雜一些的是 OpenVINO? 推理部分的工作,由于 ChatGLM2-6B 文本生成任務(wù)需要完成多次遞歸迭代,并且每次迭代會(huì)存在 cache 緩存,因此我們需要為不同的迭代輪次分別準(zhǔn)備合適的輸入數(shù)據(jù)。接下來我們?cè)敿?xì)解構(gòu)一下模型的運(yùn)行邏輯:
圖:ChatGLM2-6B模型輸入輸出原理
ChatGLM2 的 IR 模型的輸入主要由三部分組成:
**· input_ids **是向量化后的提示輸入
**· position_ids **用來描述輸入的位置信息,例如原始的 prompt 數(shù)據(jù)為 “How are you”, 那這是 position_ids 就是[[1,2,3]], 如果輸入為原始 prompt 的后的第一個(gè)被預(yù)測(cè)詞:”I”, 那 position_ids 則為[[4]], 以此類推。
**· past_key_values.x **是由一連串?dāng)?shù)據(jù)構(gòu)成的集合,用來保存每次迭代過程中可以被共享的 cache.
ChatGLM2 的 IR 模型的輸出則由兩部分組成:
**· Logits **為模型對(duì)于下一個(gè)詞的預(yù)測(cè),或者叫 next token
· present_key_values.x則可以被看作 cache,直接作為下一次迭代的 past_key_values.x 值
整個(gè) pipeline 在運(yùn)行時(shí)會(huì)對(duì) ChatGLM2 模型進(jìn)行多次迭代,每次迭代會(huì)遞歸生成對(duì)答案中下一個(gè)詞的預(yù)測(cè),直到最終答案長度超過預(yù)設(shè)值 max_sequence_length,或者預(yù)測(cè)的下一個(gè)詞為終止符 eos_token_id。
· 第一次迭代
如圖所示在一次迭代時(shí)(N=1)input_ids 為提示語句,此時(shí)我們還需要利用 Tokenizer 分詞器將原始文本轉(zhuǎn)化為輸入向量,而由于此時(shí)無法利用 cache 進(jìn)行加速,past_key_values.x 系列向量均為空值,這里我們會(huì)初始化一個(gè)維度為[0,1,2,128]的空值矩陣
· 第N次迭代
當(dāng)?shù)谝淮蔚瓿珊?,?huì)輸出對(duì)于答案中第一個(gè)詞的預(yù)測(cè) Logits,以及 cache 數(shù)據(jù),我們可以將這個(gè) Logits 作為下一次迭代的 input_ids 再輸入到模型中進(jìn)行下一次推理(N=2), 此時(shí)我們可以利用到上次迭代中的 cache 數(shù)據(jù)也就是 present_key_values.x,而無需每次將完整的“提示+預(yù)測(cè)詞”一并送入模型,從而減少一些部分重復(fù)的計(jì)算量。這樣周而復(fù)始,將當(dāng)前的預(yù)測(cè)詞所謂一次迭代的輸入,就可以逐步生成所有的答案。
詳細(xì)代碼如下,這里可以看到如果 past_key_values 等于 None 就是第一次迭代,此時(shí)需要構(gòu)建一個(gè)值均為空的 past_key_values 系列,如果不為 None 則會(huì)將真實(shí)的 cache 數(shù)據(jù)加入到輸入中。
測(cè)試輸出如下:
命令:python3 generate_ov.py -m "THUDM/chatglm2-6b" -p "請(qǐng)介紹一下上海?"
ChatGLM2-6B 回答:
“上海是中國的一個(gè)城市,位于東部沿海地區(qū),是中國重要的經(jīng)濟(jì)、文化和科技中心之一。
上海是中國的一個(gè)重要港口城市,是中國重要的進(jìn)出口中心之一,也是全球著名的金融中心之一。上海是亞洲和全球經(jīng)濟(jì)的中心之一,擁有許多國際知名金融機(jī)構(gòu)和跨國公司總部。
上海是一個(gè)擁有悠久歷史和豐富文化的城市。上海是中國重要的文化城市之一,擁有許多歷史文化名勝和現(xiàn)代文化地標(biāo)。上海是中國的一個(gè)重要旅游城市,吸引了大量國內(nèi)外游客前來觀光旅游。“
上海是一個(gè)擁有重要經(jīng)濟(jì)功能的現(xiàn)代城市。“
OpenVINO?
聊天助手
官方示例中 ChatGLM2 的主要用途為對(duì)話聊天,相較于問答模型模式中一問一答的形式,對(duì)話模式則需要構(gòu)建更為完整的對(duì)話,此時(shí)模型在生成答案的過程中還需要考慮到之前對(duì)話中的信息,并將其作為 cache 數(shù)據(jù)往返于每次迭代過程中,因此這里我們需要額外設(shè)計(jì)一個(gè)模板,用于構(gòu)建每一次的輸入數(shù)據(jù),讓模型能夠給更充分理解哪些是歷史對(duì)話,哪些是新的對(duì)話問題。
圖:ChatGLM2對(duì)話任務(wù)流程
這里的 text 模板是由“引導(dǎo)詞+歷史記錄+當(dāng)前問題(提示)”三部分構(gòu)成:
· 引導(dǎo)詞:描述當(dāng)前的任務(wù),引導(dǎo)模型做出合適的反饋
· 歷史記錄:記錄聊天的歷史數(shù)據(jù),包含每一組問題和答案
· 當(dāng)前問題:類似問答模式中的問題
我們采用 streamlit 框架構(gòu)建構(gòu)建聊天機(jī)器人的 web UI 和后臺(tái)處理邏輯,同時(shí)希望該聊天機(jī)器人可以做到實(shí)時(shí)交互,實(shí)時(shí)交互意味著我們不希望聊天機(jī)器人在生成完整的文本后再將其輸出在可視化界面中,因?yàn)檫@個(gè)需要用戶等待比較長的時(shí)間來獲取結(jié)果,我們希望在用戶在使用過程中可以逐步看到模型所預(yù)測(cè)的每一個(gè)詞,并依次呈現(xiàn)。因此我們需要?jiǎng)?chuàng)建一個(gè)可以被迭代的方法 generate_iterate,可以依次獲取模型迭代過程中每一次的預(yù)測(cè)結(jié)果,并將其依次添加到最終答案中,并逐步呈現(xiàn)。
當(dāng)完成任務(wù)構(gòu)建后,我們可以通過 streamlit run chat_robot.py 命令啟動(dòng)聊天機(jī)器,并訪問本地地址進(jìn)行測(cè)試。這里選擇了幾個(gè)常用配置參數(shù),方便開發(fā)者根據(jù)機(jī)器人的回答準(zhǔn)確性進(jìn)行調(diào)整:
· 系統(tǒng)提示詞:用于引導(dǎo)模型的任務(wù)方向
**· max_tokens: **生成句子的最大長度。
· top-k:從置信度對(duì)最高的k個(gè)答案中隨機(jī)進(jìn)行挑選,值越高生成答案的隨機(jī)性也越高。
**· top-p: **從概率加起來為 p 的答案中隨機(jī)進(jìn)行挑選, 值越高生成答案的隨機(jī)性也越高,一般情況下,top-p 會(huì)在 top-k 之后使用。
· Temperature:從生成模型中抽樣包含隨機(jī)性, 高溫意味著更多的隨機(jī)性,這可以幫助模型給出更有創(chuàng)意的輸出。如果模型開始偏離主題或給出無意義的輸出,則表明溫度過高。
注3:由于 ChatGLM2-6B 模型比較大,首次硬件加載和編譯的時(shí)間會(huì)相對(duì)比較久
OpenVINO?
總結(jié)
作為當(dāng)前最熱門的雙語大語言模型之一,ChatGLM2 憑借在各大基準(zhǔn)測(cè)試中出色的成績,以及支持微調(diào)等特性被越來越多開發(fā)者所認(rèn)可和使用。利用 OpenVINO? 構(gòu)建 ChatGLM2 系列任務(wù)可以進(jìn)一步提升其模型在英特爾平臺(tái)上的性能,并降低部署門檻。
審核編輯:劉清
-
編碼器
+關(guān)注
關(guān)注
45文章
3643瀏覽量
134535 -
向量機(jī)
+關(guān)注
關(guān)注
0文章
166瀏覽量
20880 -
cache技術(shù)
+關(guān)注
關(guān)注
0文章
41瀏覽量
1064 -
pytorch
+關(guān)注
關(guān)注
2文章
808瀏覽量
13229 -
ChatGPT
+關(guān)注
關(guān)注
29文章
1561瀏覽量
7683
原文標(biāo)題:基于 ChatGLM2 和 OpenVINO? 打造中文聊天助手 | 開發(fā)者實(shí)戰(zhàn)
文章出處:【微信號(hào):英特爾物聯(lián)網(wǎng),微信公眾號(hào):英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論