使用 Optimum-Intel 和 OpenVINO GenAI 最佳化和部署模型

釋出日期:2024年9月20日
在 GitHub 上更新

在邊緣或客戶端部署 Transformers 模型需要仔細考慮效能和相容性。Python 雖然功能強大,但並非總是此類部署的理想選擇,尤其是在 C++ 主導的環境中。本部落格將指導您使用 Optimum-Intel 和 OpenVINO™ GenAI 最佳化和部署 Hugging Face Transformers 模型,確保高效的 AI 推理,並最大限度地減少依賴關係。

目錄

  1. 為何在邊緣部署中使用 OpenVINO™
  2. 步驟 1:設定環境
  3. 步驟 2:將模型匯出到 OpenVINO IR
  4. 步驟 3:模型最佳化
  5. 步驟 4:使用 OpenVINO GenAI API 部署
  6. 結論

為何在邊緣部署中使用 OpenVINO™

OpenVINO™ 最初是作為 C++ AI 推理解決方案開發的,這使其成為邊緣和客戶端部署的理想選擇,在這些部署中,最大限度地減少依賴關係至關重要。隨著 GenAI API 的引入,將大型語言模型 (LLM) 整合到 C++ 或 Python 應用程式中變得更加簡單,其功能旨在簡化部署並提高效能。

步驟 1:設定環境

先決條件

首先,確保您的環境已正確配置 Python 和 C++。安裝必要的 Python 包

pip install --upgrade --upgrade-strategy eager "optimum[openvino]"

以下是本部落格文章中使用的具體包

transformers==4.44
openvino==24.3
openvino-tokenizers==24.3
optimum-intel==1.20
lm-eval==0.4.3

有關 GenAI C++ 庫的安裝說明,請參見此處

步驟 2:將模型匯出到 OpenVINO IR

Hugging Face 和 Intel 的合作催生了 Optimum-Intel 專案。它旨在最佳化 Transformers 模型,使其在 Intel 硬體上進行推理。Optimum-Intel 支援 OpenVINO 作為推理後端,其 API 具有基於 OpenVINO 推理 API 構建的各種模型架構的包裝器。所有這些包裝器都以 OV 為字首,例如 OVModelForCausalLM。否則,它與 🤗 Transformers 庫的 API 類似。

要將 Transformers 模型匯出到 OpenVINO 中間表示 (IR),可以使用兩種選項:這可以透過 Python 的 .from_pretrained() 方法或 Optimum 命令列介面 (CLI) 來完成。以下是使用這兩種方法的示例

使用 Python API

from optimum.intel import OVModelForCausalLM

model_id = "meta-llama/Meta-Llama-3.1-8B"
model = OVModelForCausalLM.from_pretrained(model_id, export=True)
model.save_pretrained("./llama-3.1-8b-ov")

使用命令列介面 (CLI)

optimum-cli export openvino -m meta-llama/Meta-Llama-3.1-8B ./llama-3.1-8b-ov

./llama-3.1-8b-ov 資料夾將包含 .xml.bin IR 模型檔案以及源模型所需的配置檔案。🤗 分詞器也將轉換為 openvino-tokenizers 庫的格式,並在同一資料夾中建立相應的配置檔案。

步驟 3:模型最佳化

在資源受限的邊緣和客戶端裝置上執行 LLM 時,強烈建議進行模型最佳化。僅權重量化是一種主流方法,可顯著減少延遲和模型佔用空間。Optimum-Intel 透過神經網路壓縮框架 (NNCF) 提供僅權重量化,該框架具有專門為 LLM 設計的各種最佳化技術:從無資料 INT8 和 INT4 權重量化到資料感知方法,如 AWQGPTQ、量化尺度估計、混合精度量化。預設情況下,大於十億引數的模型權重被量化為 INT8 精度,這在精度方面是安全的。這意味著上述匯出步驟將生成 8 位權重的模型。然而,4 位整數僅權重量化可以實現更好的精度-效能權衡。

對於 meta-llama/Meta-Llama-3.1-8B 模型,我們建議結合 AWQ、量化尺度估計以及使用反映部署用例的校準資料集進行 INT4/INT8 混合精度權重量化。與匯出情況一樣,有兩種選項可以對 LLM 模型應用 4 位僅權重量化

使用 Python API

  • .from_pretrained() 方法中指定 quantization_config 引數。在這種情況下,應建立 OVWeightQuantizationConfig 物件並將其設定為此引數,如下所示
from optimum.intel import OVModelForCausalLM, OVWeightQuantizationConfig

MODEL_ID = "meta-llama/Meta-Llama-3.1-8B"
quantization_config = OVWeightQuantizationConfig(bits=4, awq=True, scale_estimation=True, group_size=64, dataset="c4")
model = OVModelForCausalLM.from_pretrained(MODEL_ID, export=True, quantization_config=quantization_config)
model.save_pretrained("./llama-3.1-8b-ov")

使用命令列介面 (CLI):

optimum-cli export openvino -m meta-llama/Meta-Llama-3.1-8B --weight-format int4 --awq --scale-estimation --group-size 64 --dataset wikitext2 ./llama-3.1-8b-ov

注意:模型最佳化過程可能需要時間,因為它會隨後應用多種方法並對指定資料集進行模型推理。

使用 API 進行模型最佳化更為靈活,因為它允許使用可作為可迭代物件(例如 🤗 庫的 Dataset 物件的例項或僅字串列表)傳遞的自定義資料集。

權重量化通常會導致精度指標的下降。為了比較最佳化模型和源模型,我們報告在 Wikitext 資料集上使用 lm-evaluation-harness 專案測量的每字困惑度指標,該專案開箱即用支援 🤗 Transformers 和 Optimum-Intel 模型。

模型 PPL PyTorch FP32 OpenVINO INT8 OpenVINO INT4
meta-llama/Meta-Llama-3.1-8B 7.3366 7.3463 7.8288

步驟 4:使用 OpenVINO GenAI API 部署

轉換和最佳化後,使用 OpenVINO GenAI 部署模型非常簡單。OpenVINO GenAI 中的 LLMPipeline 類提供 Python 和 C++ API,支援各種文字生成方法,並最大限度地減少依賴關係。

Python API 示例

import argparse
import openvino_genai

device = "CPU"  # GPU can be used as well
pipe = openvino_genai.LLMPipeline(args.model_dir, device)
config = openvino_genai.GenerationConfig()
config.max_new_tokens = 100
print(pipe.generate(args.prompt, config))

要執行此示例,您需要將最少的依賴項安裝到 Python 環境中,因為 OpenVINO GenAI 旨在提供輕量級部署。您可以將 OpenVINO GenAI 包安裝到相同的 Python 環境中,或者建立一個單獨的環境以比較應用程式佔用空間

pip install openvino-genai==24.3

C++ API 示例

讓我們看看如何使用 OpenVINO GenAI C++ API 執行相同的管道。GenAI API 旨在直觀且提供從 🤗 Transformers API 的無縫遷移。

注意:在下面的示例中,“device”變數可以指定您環境中任何其他可用的裝置。例如,如果您使用的是帶有整合顯示卡的 Intel CPU,“GPU”是一個不錯的選擇。要檢查可用裝置,您可以使用 ov::Core::get_available_devices 方法(請參閱 query-device-properties)。

#include "openvino/genai/llm_pipeline.hpp"
#include <iostream>

int main(int argc, char* argv[]) {
   std::string model_path = "./llama-3.1-8b-ov";
   std::string device = "CPU"  // GPU can be used as well
   ov::genai::LLMPipeline pipe(model_path, device);
   std::cout << pipe.generate("What is LLM model?", ov::genai::max_new_tokens(256));
}

自定義生成配置

LLMPipeline 還允許透過 ov::genai::GenerationConfig 指定自定義生成選項

ov::genai::GenerationConfig config;
config.max_new_tokens = 256;
std::string result = pipe.generate(prompt, config);

透過 LLMPipieline,使用者不僅可以輕鬆利用各種解碼演算法(例如束搜尋),還可以使用 Streamer 構建互動式聊天場景,如下例所示。此外,還可以利用 LLMPipeline 增強的內部最佳化,例如透過聊天方法 start_chat()finish_chat() 利用先前聊天曆史的 KV 快取來減少提示處理時間(請參閱 using-genai-in-chat-scenario)。

ov::genai::GenerationConfig config;
config.max_new_tokens = 100;
config.do_sample = true;
config.top_p = 0.9;
config.top_k = 30;

auto streamer = [](std::string subword) {
    std::cout << subword << std::flush;
    return false;
};

// Since the streamer is set, the results will
// be printed each time a new token is generated.
pipe.generate(prompt, config, streamer);

最後,讓我們看看如何在聊天場景中使用 LLMPipeline

pipe.start_chat()
for (size_t i = 0; i < questions.size(); i++) {
   std::cout << "question:\n";
   std::getline(std::cin, prompt);

   std::cout << pipe.generate(prompt) << std::endl;
}
pipe.finish_chat();

結論

Optimum-Intel 和 OpenVINO™ GenAI 的結合為在邊緣部署 Hugging Face 模型提供了強大、靈活的解決方案。透過遵循這些步驟,您可以在 Python 可能不理想的環境中實現最佳化、高效能的 AI 推理,確保您的應用程式在 Intel 硬體上流暢執行。

其他資源

  1. 您可以在此教程中找到更多詳細資訊。
  2. 要構建上述 C++ 示例,請參閱此文件
  3. OpenVINO 文件
  4. Jupyter Notebooks
  5. Optimum 文件

OpenVINO GenAI C++ chat demo

社群

註冊登入發表評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.