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

news/2024/10/21 13:48:58

在端侧部署 Transformer 模型需要仔细考虑性能和兼容性。Python 虽然功能强大,但对于部署来说有时并不算理想,特别是在由 C++ 主导的环境中。这篇博客将指导您如何使用 Optimum-Intel 和 OpenVINO™ GenAI 来优化和部署 Hugging Face Transformers 模型,确保在最小依赖性的情况下进行高效的 AI 推理。

为什么使用 OpenVINO 来进行端侧部署

OpenVINO™ 最初是作为 C++ AI 推理解决方案开发的,使其非常适合在端侧设备部署中,其中最小化依赖性至关重要。随着引入 GenAI API,将大型语言模型 (LLMs) 集成到 C++ 或 Python 应用程序中变得更加简单,其特性旨在简化部署并提升性能。

第一步: 创建环境

预先准备

开始之前,请确保您的环境已正确配置了 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++ 库的安装,请按照 此处 的说明进行操作。

第二步: 将模型导出为 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 OVModelForCausalLMmodel_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 模型文件以及来自源模型的所需配置文件。🤗 tokenizer 也将转换为 openvino-tokenizers 库的格式,并在同一文件夹中创建相应的配置文件。

第三步: 模型优化

在资源受限的端侧设备上运行大型语言模型 (LLMs) 时,模型优化是一个极为重要的步骤。仅量化权重是一种主流方法,可以显著降低延迟和模型占用空间。Optimum-Intel 通过神经网络压缩框架 (NNCF) 提供了仅量化权重 (weight-only quantization) 的功能,该框架具有多种专为 LLMs 设计的优化技术: 从无数据 (data-free) 的 INT8 和 INT4 权重量化到数据感知方法,如 AWQ、GPTQ、量化 scale 估计、混合精度量化等。默认情况下,超过十亿参数的模型的权重会被量化为 INT8 精度,这在准确性方面是安全的。这意味着上述导出步骤会生成具有 8 位权重的模型。然而,4 位整数的仅量化权重允许实现更好的准确性和性能的权衡。

对于 meta-llama/Meta-Llama-3.1-8B 模型,我们建议结合 AWQ、量化 scale 估计以及使用反映部署用例的校准数据集进行混合精度 INT4/INT8 权重的量化。与导出情况类似,在将 4 比特仅量化权重应用于 LLM 模型时有两种选项:

使用 Python API

  • .from_pretrained() 方法中指定 quantization_config 参数。在这种情况下,应创建 OVWeightQuantizationConfig 对象,并将其设置为该参数,如下所示:
from optimum.intel import OVModelForCausalLM, OVWeightQuantizationConfigMODEL_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

第四步: 使用 OpenVINO GenAI API 进行部署

在转换和优化之后,使用 OpenVINO GenAI 部署模型非常简单。OpenVINO GenAI 中的 LLMPipeline 类提供了 Python 和 C++ API,支持各种文本生成方法,并具有最小的依赖关系。

Python API 的例子

import argparse
import openvino_genaidevice = "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 wellov::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);

使用 LLMPipeline,用户不仅可以轻松利用各种解码算法,如 Beam Search,还可以像下面的示例中那样构建具有 Streamer 的交互式聊天场景。此外,用户可以利用 LLMPipeline 的增强内部优化,例如利用先前聊天历史的 KV 缓存减少提示处理时间,使用 chat 方法: start_chat()finish_chat() (参考 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 笔记本
  5. Optimum 文档

OpenVINO GenAI C++ 聊天演示


原文链接: https://hf.co/blog/deploy-with-openvino

原文作者: Alexander, Yury Gorbachev, Ekaterina Aidova, Ilya Lavrenov, Raymond Lo, Helena, Ella Charlaix

译者: Zipxuan

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/74162.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【STC15】面向对象的.h/.c程序架构

.h 文件 #ifndef __MAIN_H_ #define __MAIN_H_/* Includes ------------------------------------------------------------------*/ #include <STC15.h>/* extern variables-----------------------------------------------------------*//* extern function prototype…

服务器和电脑主机有什么区别

服务器和电脑主机在很多方面都有所区别。下面我们将从1、定义;2、用途;3、硬件配置;4、软件配置;5、稳定性和安全性;6、价格等六个方面对这两者进行详细对比。其中,服务器是指提供各类服务的设备;电脑主机通常是指个人电脑(PC),它主要用于个人或者单个用户的需求,例如…

Java 中的数据加密和安全传输_1

在Java中实现数据加密和安全传输涉及几个关键技术:使用加密算法、实施安全的密钥管理、采用安全传输协议。加密算法如AES和RSA用于保护数据的机密性,防止未授权访问。安全的密钥管理确保只有授权用户才能解密数据。而安全传输协议如SSL/TLS保护数据在网络中的传输。其中,安全…

mybatis的一对多,多对一,以及多对多的配置和使用

根据这个应用场景,我们需要获取在查询一个用户信息的时候还要去读取这个用户发布的帖子 现在我们来看一看用户级联文章在JavaBean中的编写方式,这就是一对多在JavaBean中的配置现在我们再来看一看Mybatis的Mapper该如何编写一对多?很简单,就是在resultMap标签中配置<collec…

PbootCMS执行SQL发生错误(DISK I/O ERROR)怎么办

执行SQL发生错误(DISK I/O ERROR)问题描述:PBootCMS网站程序提示“执行 SQL 发生错误!错误:DISK I/O ERROR”。 解决方案:检查磁盘空间:确保服务器磁盘空间充足,没有满。 检查磁盘健康:使用磁盘检测工具检查磁盘健康状况,确保没有坏道。 优化数据库:优化数据库表,修…

K个节点翻转链表

概述 起因:leetcode题目 25. K 个一组翻转链表 问题描述 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节…

PbootCMS登录后无法使用数据备份功能,备份失败或提示错误怎么办

问题描述:登录后无法使用数据备份功能,备份失败或提示错误。 解决方案:检查文件权限:确保备份目录具有可写权限。 检查数据库连接:确保数据库连接配置正确,数据库服务正常运行。 检查PHP错误日志:查看服务器的PHP错误日志,查找可能的错误信息。 清除缓存:清除浏览器缓…

一文彻底弄清Redis的布隆过滤器

布隆过滤器(Bloom Filter)是一种空间效率极高的数据结构,用于快速判断一个元素是否在集合中。它能够节省大量内存,但它有一个特点:可能存在误判,即可能会认为某个元素存在于集合中,但实际上不存在;而对于不存在的元素,它保证一定不会误判。布隆过滤器适合在对存储空间…