基于 Llama2 和 OpenVINO 打造聊天機(jī)器人
Llama 2是 Meta 發(fā)布了其最新的大型語言模型,Llama2 是基于 Transformer 的人工神經(jīng)網(wǎng)絡(luò),以一系列單詞作為輸入,遞歸地預(yù)測下一個單詞來生成文本。
?
這是一款開源且免費(fèi)的人工智能模型。此前,由于開源協(xié)議問題,Llama 1 雖然功能強(qiáng)大,但并不可免費(fèi)商用。然而,這一次 Meta 終于推出了免費(fèi)商用版本 Llama 2,借這一機(jī)會,我們分享一下如何基于 Llama2 和 OpenVINO 工具套件來打造一款聊天機(jī)器人。
項(xiàng)目倉庫地址:
https://github.com/OpenVINO-dev-contest/llama2.openvino
注1:由于 Llama2 對在模型轉(zhuǎn)換和運(yùn)行過程中對內(nèi)存的占用較高,推薦使用支持 128Gb 以上內(nèi)存的的服務(wù)器終端作為測試平臺。
注2:本文僅分享部署 Llama2 原始預(yù)訓(xùn)練模型的方法,如需獲得自定義知識的能力,需要對原始模型進(jìn)行 Fine-tune;如需獲得更好的推理性能,可以使用量化后的模型版本。
?
模型導(dǎo)出
?
第一步,我們需要下載 Llama2? 模型,并將其導(dǎo)出為OpenVINO? 所支持的?IR?格式模型進(jìn)行部署,這里我們使用 Optimum-Intel 所提供的接口,直接從 Hugging Face 倉庫中下載并生成 IR 模型。

?
?不過在這之前,我們首先需要向 Meta 申請模型下載的許可,方可開始下載,具體如何發(fā)送申請可以參考Llama2 倉庫中的說明和引導(dǎo):https://huggingface.co/meta-llama/Llama-2-7b-hf
在運(yùn)行項(xiàng)目倉庫中的 export_ir.py 腳本后,會在本地指定路徑中生成openvino_model.bin和 openvino_model.xml ,前者為模型參數(shù)文件,后者為模型結(jié)構(gòu)文件。
?
?
?
模型部署(方案一)
?
由于目前 Hugging Face 的 Transformer 以及 Optimum 庫都已經(jīng)支持了 Llama2 系列模型的部署,一種比較簡便和快捷的做法是,直接使用 Optimum-Intel 來運(yùn)行整個 Llama2 pipeline,由于 Optimum 中已經(jīng)預(yù)置了完整的問答類模型 pipeline:? ModelForCausalLM,并進(jìn)行了深度的集成, 所以我們只需要調(diào)用少量接口,并可以輕松調(diào)用 OpenVINO? 推理后端,實(shí)現(xiàn)一個簡單問答任務(wù)的部署。

這里再簡單介紹下什么是 Optimum。Optimum 庫是 Hugging Face 為了方便開發(fā)者在不同的硬件平臺部署來自 Transformer 和 Diffuser 庫的模型,所打造的部署工具,其中的 Optimum-Intel 庫則支持在 Intel 平臺部署模型時,調(diào)用 OpenVINO? 工具套件作為模型的推理后端,提升任務(wù)性能。
最終效果如下:
“Response: what is openvino ?
OpenVINO is an open-source software framework for deep learning inference that is designed to run on a variety of platforms, including CPUs, GPUs, and FPGAs. It is developed by the OpenVINO Project, which is a collaboration between Intel and the Linux Foundation.
OpenVINO provides a set of tools and libraries for developers to build, optimize, and deploy deep learning models for inference. It supports popular deep learning frameworks such as TensorFlow, PyTorch, and Caffe, and provides a number of features to improve the performance“
?
?
?
模型部署(方案二)
?
由于 Optimum 仍屬于“黑箱”模式,開發(fā)者無法充分自定義內(nèi)在的運(yùn)行邏輯,所以這里使用的第二種方式則是在脫離 Optimum 庫的情況,僅用 OpenVINO? 的原生接口部署 Llama2 模型,并重構(gòu) pipeline。
?
整個重構(gòu)后 pipeline 如下圖所示,Prompt 提示會送入 Tokenizer 進(jìn)行分詞和詞向量編碼,然后有 OpenVINO? 推理獲得結(jié)果(藍(lán)色部分),來到后處理部分,我們會把推理結(jié)果進(jìn)行進(jìn)一步的采樣和解碼,最后生成常規(guī)的文本信息。這里為了簡化流程,僅使用了 Top-K 作為篩選方法。
?

?
?
整個 pipeline 的大部分代碼都可以套用文本生成任務(wù)的常規(guī)流程,其中比較復(fù)雜一些的是 OpenVINO? 推理部分的工作,由于 Llama2 文本生成任務(wù)需要完成多次遞歸迭代,并且每次迭代會存在 cache 緩存,因此我們需要為不同的迭代輪次分別準(zhǔn)備合適的輸入數(shù)據(jù)。接下來我們詳細(xì)解構(gòu)一下模型的運(yùn)行邏輯:
?

??
Llama2 模型的輸入主要由三部分組成:
· input_ids?是向量化后的提示輸入
·attention_mask?用來描述輸入數(shù)據(jù)的長度, input_ids 需要被計(jì)算的數(shù)據(jù)所在對應(yīng)位置的 attention_mask 值用1表示,需要在計(jì)算時被丟棄數(shù)據(jù)用0表示
· past_key_values.x?是由一連串?dāng)?shù)據(jù)構(gòu)成的集合,用來保存每次迭代過程中可以被共享的cache.
?
Llama2 模型的輸出則由兩部分組成:
· Logits?為模型對于下一個詞的預(yù)測,或者叫 next token
· present.x?則可以被看作 cache,直接作為下一次迭代的past_key_values.x值
?
?
整個 pipeline 在運(yùn)行時會對 Llama2 模型進(jìn)行多次迭代,每次迭代會遞歸生成對答案中下一個詞的預(yù)測,直到最終答案長度超過預(yù)設(shè)值?max_sequence_length,或者預(yù)測的下一個詞為終止符 eos_token_id。
· 第一次迭代
如圖所示在一次迭代時(N=1)input_ids 為提示語句,此時我們還需要利用 Tokenizer 分詞器將原始文本轉(zhuǎn)化為輸入向量,而由于此時無法利用 cache 進(jìn)行加速,past_key_values.x 系列向量均為空值。
· 第N次迭代
當(dāng)?shù)谝淮蔚瓿珊?,會輸出對于答案中第一個詞的預(yù)測 Logits,以及 cache 數(shù)據(jù),我們可以將這個 Logits 作為下一次迭代的 input_ids 再輸入到模型中進(jìn)行下一次推理(N=2), 此時我們可以利用到上次迭代中的 cache 數(shù)據(jù)也就是 present.x,而無需將完整的“提示+預(yù)測詞”一并送入模型,從而減少一些部分重復(fù)的計(jì)算量。這樣周而復(fù)始,將當(dāng)前的預(yù)測詞所謂一次迭代的輸入,就可以逐步生成所有的答案。
?
聊天機(jī)器人
?
除了 Llama 2 基礎(chǔ)版本,Meta 還發(fā)布了 LLaMA-2-chat ,使用來自人類反饋的強(qiáng)化學(xué)習(xí)來確保安全性和幫助性, 專門用于構(gòu)建聊天機(jī)器人。相較于問答模型模式中一問一答的形式,聊天模式則需要構(gòu)建更為完整的對話,此時模型在生成答案的過程中還需要考慮到之前對話中的信息,并將其作為 cache 數(shù)據(jù)往返于每次迭代過程中,因此這里我們需要額外設(shè)計(jì)一個模板,用于構(gòu)建每一次的輸入數(shù)據(jù),讓模型能夠給更充分理解哪些是歷史對話,哪些是新的對話問題。
?

?
?
這里的 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 和后臺處理邏輯,同時希望該聊天機(jī)器人可以做到實(shí)時交互,實(shí)時交互意味著我們不希望聊天機(jī)器人在生成完整的文本后再將其輸出在可視化界面中,因?yàn)檫@個需要用戶等待比較長的時間來獲取結(jié)果,我們希望在用戶在使用過程中可以逐步看到模型所預(yù)測的每一個詞,并依次呈現(xiàn)。因此需要利用 Hugging Face 的 TextIteratorStreamer 組件,基于其構(gòu)建一個流式的數(shù)據(jù)處理 pipeline,此處的 streamer 為一個可以被迭代的對象,我可以依次獲取模型迭代過程中每一次的預(yù)測結(jié)果,并將其依次添加到最終答案中,并逐步呈現(xiàn)。

?
當(dāng)完成任務(wù)構(gòu)建后,我們可以通過 streamlit run chat_streamlit.py 命令啟動聊天機(jī)器,并訪問本地地址進(jìn)行測試。這里選擇了幾個常用配置參數(shù),方便開發(fā)者根據(jù)機(jī)器人的回答準(zhǔn)確性進(jìn)行調(diào)整:
· max_tokens: 生成句子的最大長度。
· top-k:?從置信度對最高的k個答案中隨機(jī)進(jìn)行挑選,值越高生成答案的隨機(jī)性也越高。
· top-p:?從概率加起來為p的答案中隨機(jī)進(jìn)行挑選, 值越高生成答案的隨機(jī)性也越高,一般情況下,top-p會在top-k之后使用。
· Temperature: 從生成模型中抽樣包含隨機(jī)性, 高溫意味著更多的隨機(jī)性,這可以幫助模型給出更有創(chuàng)意的輸出。如果模型開始偏離主題或給出無意義的輸出,則表明溫度過高。
?

注3:由于Llama2模型比較大,首次硬件加載和編譯的時間會相對比較久
?
總結(jié)
?
作為當(dāng)前最火爆的開源大語言模型,Llama2 憑借在各大基準(zhǔn)測試中出色的成績,以及支持微調(diào)等特性被越來越多開發(fā)者所認(rèn)可和使用。利用 Optimum-Intel 和 OpenVINO? 構(gòu)建 Llama2 系列任務(wù)可以進(jìn)一步提升其模型在英特爾平臺上的性能,并降低部署門檻。
?
參考資料
?
1.Optimum-Intel:?
https://github.com/huggingface/optimum-intel
?
2.Optimum:
https://huggingface.co/docs/optimum
3.GPT2 notebook samples:?https://github.com/openvinotoolkit/openvino_notebooks/tree/dd77a4c47312fdfdc2e43e27aa488e2802733760/notebooks/223-text-prediction
4.Llama2?Hugging?Face:?
https://huggingface.co/meta-llama/Llama-2-7b-chat-hf
?