在过去几个月里,对交互式聊天生成(或对话式响应生成)模型的关注度大大提高。ChatGPT 和 Google Bard 等对话式响应生成模型席卷了 AI 世界。交互式聊天生成的目的是回答人类提出的各种问题,这些基于 AI 的模型使用自然语言处理 (NLP) 生成的对话几乎与人类生成的对话难以区分。
本文展示了一个代码示例,介绍如何基于 Hugging Face 的预训练 DialoGPT 模型创建交互式聊天,并添加 Intel® Extension for PyTorch 以对模型执行动态量化。
开始使用
为何选择 DialoGPT?
DialoGPT(对话生成预训练 Transformer)是一个大规模的预训练对话响应生成模型,在从 Reddit 评论链和讨论主题中提取的 1.47 亿个类似对话的交流基础上进行训练。DialoGPT 由微软于 2019 年提出。其主要目标是创建能够对各种对话主题产生自然响应的开放域聊天机器人。利用 DialoGPT 的对话响应生成系统能够生成更适用、更富有资源、更多样化且更具上下文相关性的回复。
DialoGPT 架构
DialoGPT 架构基于 GPT-2 模型。它被构建为一个自回归语言模型,并使用多层 Transformer 作为模型架构。GPT-2 由 OpenAI 提出。GPT-2 模型在通用文本数据上进行训练,而 DialoGPT 则在 Reddit 讨论主题上进行训练。
让我们看看 GPT-2 架构。通用的 Transformer 架构中有两种类型的块
- 编码器 - 包含自注意力层和前馈神经网络
- 解码器 - 类似于编码器,但自注意力层被掩码
自注意力层允许一个位置查看当前单词右侧的 token(文本中的后续单词),而掩码自注意力层则阻止这种情况发生。
GPT-2 使用 Transformer 解码器块构建。这意味着架构中使用了以下层
- 嵌入层 – 负责将输入文本转换为嵌入(每个单词都被转换为固定长度的向量表示)
- Transformer 解码器 – 包含多个带有掩码自注意力和前馈神经网络层的解码器块
- 输出层 – 负责将从解码器获得的嵌入转换为单词
GPT-2 架构(以及 DialoGPT 架构)如下图所示。
由于模型基于 Transformer 架构,存在重复和复制输入的问题。为了避免重复,我们可以使用 Top-K 采样和 Top-p 采样。
- Top-K 采样 - 过滤出 K 个最可能的下一个单词,并将概率质量重新分配给这 K 个单词。
- Top-p 采样 - 不仅选择 K 个最可能的单词,而是选择累计概率超过概率 p 的最小单词集合。
然后将概率质量重新分配给集合中的单词。因此,单词集合的大小可以根据下一个单词的概率分布动态增加或减少。
使用 Intel® Extension for PyTorch 进行量化
什么是量化?
量化是对模型内全部或部分层的精度进行系统性降低。这意味着将深度学习中常用的单精度浮点数 (FP32) 等更高精度类型转换为 FP16(16 位)或 INT8(8 位)等较低精度类型。
这有助于实现:
- 更低的内存带宽
- 更低的存储
- 在精度损失极小或没有损失的情况下获得更高的性能
对于基于 Transformer 架构的大型模型,如 BERT 或 GPT,量化尤其重要。
量化有两种类型:
- 静态量化 – 静态量化对模型的权重和激活进行量化。当内存带宽和计算节省都很重要时,使用此量化方法。
- 动态量化 – 在动态量化中,权重提前量化,但激活在推理过程中动态量化。
Intel Extension for PyTorch: Intel Extension 扩展了 PyTorch,提供了最新的功能和优化,可在 Intel® 硬件上额外提升性能。了解如何单独安装或作为Intel® AI Analytics Toolkit 的一部分获取。
该扩展可以作为 Python* 模块加载或作为 C++ 库链接。Python 用户可以通过导入 intel_extension_for_pytorch 动态启用它。
- 此CPU 教程提供了关于 Intel CPUs 的 Intel Extension for PyTorch 的详细信息。源代码可在master 分支获得。
- 此GPU 教程提供了关于 Intel GPUs 的 Intel Extension for PyTorch 的详细信息。源代码可在xpu-master 分支获得。
如何使用 Intel Extension for PyTorch 执行动态量化?
以下是使用动态量化将现有 FP32 模型量化为 INT8 模型的步骤
- 准备量化配置 - 我们可以使用 ipex.quantization.default_dynamic_qconfig 的默认动态量化配置。
- 使用 ipex.quantization.prepare 方法准备 FP32 模型(提供输入参数,如要量化的 FP32 模型、准备好的配置、示例输入以及是否应进行原地量化等信息)。
- 将模型从 FP32 转换为 INT8 - 使用 ipex.quantization.convert 方法进行转换。输入模型将是在步骤 2 中准备好的模型。
我们还鼓励您查看 Intel® Neural Compressor 工具,该工具可自动化量化、剪枝和知识蒸馏等流行的模型压缩技术,适用于多种深度学习框架。
代码示例
代码示例中实现了以下步骤
- 加载模型和分词器:此步骤使用了 Transformers 库(查看 Intel® Extension for Transformers)以及 Hugging Face 主类中提供的 Auto 类。这些类允许我们通过给定的名称自动查找相关的模型。它们还允许开发者轻松更改模型,而无需对代码进行重大修改,如下所示
tokenizer = AutoTokenizer.from_pretrained(model) model = AutoModelForCausalLM.from_pretrained(model)
将模型参数指定为分词器的输入,模型初始化仅指定预训练 DialoGPT 模型的路径。在本示例中,我们使用 ‘microsoft/DialoGPT-large’。如果您的资源有限,可以使用 ‘microsoft/DialoGPT-medium’ 或 ‘microsoft/DialoGPT-small’ 模型,并获得可比的结果。
- 执行模型的动态量化
- 使用 Intel Extension for PyTorch 库中的默认动态量化配置创建配置。
- 准备模型。
- 将模型从 FP32 转换为 INT8。
这些步骤在上面一节中有详细解释。
- 响应生成:响应生成的第一步是编码输入句子,如下面的代码所示
new_input_ids = tokenizer.encode(input(">> You:") + tokenizer.eos_token, return_tensors='pt')
在此示例中,我们希望模型保存历史记录,因此我们将输入句子以 token 的形式添加到聊天历史记录中
bot_input_ids = torch.cat([chat_history_ids, new_input_ids], dim=-1) if chat_round > 0 else new_input_ids
文本生成可以通过 model.generate 函数完成,在该函数中我们可以指定所有重要参数,例如保存的聊天历史记录、响应的 token 长度以及 Top-K 和 Top-p 采样的使用。
chat_history_ids = model.generate(bot_input_ids, do_sample=True, max_length=2000, top_k=50, top_p=0.95, pad_token_id=tokenizer.eos_token_id)
最后一步是解码并打印响应
- 交互式对话准备:在生成响应后,最后一步是添加交互。这可以通过使用一个简单的 for 循环来实现。基于已初始化的分词器、模型和空的聊天历史记录,为多个回合生成响应
for chat_round in range(n): chat_history_ids = generate_response( tokenizer, model, chat_round, chat_history_ids )
交互式聊天生成的一个示例如下图所示。
下一步?
开始使用 Intel Extension for PyTorch 和 DialoGPT 构建交互式聊天生成模型。下载并亲自试用 Intel AI Analytics Toolkit 和 Intel Extension for PyTorch,构建各种端到端 AI 应用。
我们鼓励您查看并整合 Intel 的其他 AI/ML 框架优化和 端到端工具集到您的 AI 工作流程中,并了解统一、开放、基于标准的 oneAPI 编程模型,该模型构成了 Intel AI Software Portfolio 的基础,可帮助您准备、构建、部署和扩展您的 AI 解决方案。
有关新款第四代 Intel® Xeon® 可扩展处理器的更多详细信息,请访问 Intel 的 AI 解决方案平台门户,了解 Intel 如何赋能开发者在这些强大的 CPU 上运行端到端 AI 流水线。