LLM Compressor 与 Alauda AI

本文档介绍如何使用 LLM Compressor 与 Alauda AI 平台集成来执行模型压缩工作流。LLM Compressor 在 Alauda AI 的集成提供了两个示例工作流:

notebook

支持的模型压缩工作流

在 Alauda AI 平台上,您可以使用 Workbench 功能对存储在模型仓库中的模型运行 LLM Compressor。以下工作流概述了压缩模型的典型步骤。

创建工作台

按照创建工作台中的说明创建新的 Workbench 实例。创建工作台时,请确保选择镜像 odh-workbench-jupyter-pytorch-llmcompressor-cuda-py312-ubi9,该镜像包含所需的 LLM Compressor 环境。模型压缩目前仅支持在 JupyterLab 中进行。

如果您的环境中没有该镜像,请参考链接文章了解如何同步镜像并修补 WorkspaceKind 资源,使该镜像出现在工作台创建选项中。

创建模型仓库并上传模型

请参阅使用 Notebook 上传模型获取创建模型仓库和上传模型文件的详细步骤。本指南中的示例 notebook 使用的是 TinyLlama-1.1B-Chat-v1.0 模型。

data-free-compressor.ipynb
from llmcompressor.modifiers.quantization import QuantizationModifier

model_id = "./TinyLlama-1.1B-Chat-v1.0"
recipe = QuantizationModifier(targets="Linear", scheme="W4A16", ignore=["lm_head"])
  1. 要压缩的模型。如果您想使用自己的模型,可以修改此行
  2. 此配方将对除 lm_head 之外的所有 Linear 层进行量化,lm_head 通常对量化较为敏感。W4A16 方案将权重量化为 4-bit 整数,同时保持激活为 16-bit

(可选)准备并上传数据集

NOTE

如果您计划使用 data-free compressor notebook,可以跳过此步骤。

若使用 calibration compressor notebook,必须准备并上传校准数据集。请按照使用 Notebook 上传模型中描述的相同步骤准备数据集。示例校准 notebook 使用的是 ultrachat_200k 数据集。

calibration-compressor.ipynb
from datasets import load_dataset

dataset_id = "./ultrachat_200k"

num_calibration_samples = 512 if use_gpu else 4
max_sequence_length = 2048 if use_gpu else 16

ds = load_dataset(dataset_id, split="train_sft")
ds = ds.shuffle(seed=42).select(range(num_calibration_samples))

def preprocess(example): 
    text = tokenizer.apply_chat_template(
        example["messages"],
        tokenize=False,
    )
    return tokenizer(
        text,
        padding=False,
        max_length=max_sequence_length,
        truncation=True,
        add_special_tokens=False,
    )

ds = ds.map(preprocess, remove_columns=ds.column_names)
  1. 使用 Huggingface datasets API 创建校准数据集。如果您想使用自己的数据集,可以修改此行
  2. 选择样本数量。512 个样本是一个不错的起点,增加样本数量可以提升准确度。
  3. 加载数据集。
  4. 打乱数据并选取所需数量的样本。
  5. 预处理并将数据转换为模型使用的格式。

(可选)上传数据集到 S3 存储

如果您希望将数据集上传到 S3,可以在 JupyterLab 中运行以下代码。

import os
from boto3.s3.transfer import TransferConfig
import boto3

local_folder = "./ultrachat_200k"
bucket_name = "datasets"

config = TransferConfig(
    multipart_threshold=100*1024*1024,
    max_concurrency=10,
    multipart_chunksize=100*1024*1024,
    use_threads=True
)

for root, dirs, files in os.walk(local_folder):
    for filename in files:
        local_path = os path.join(root, filename)
        relative_path = os.path.relpath(local_path, local_folder)
        s3_key = f"ultrachat_200k/{relative_path.replace(os.sep, '/')}"
        s3.upload_file(local_path, bucket_name, s3_key, Config=config)
        print(f"Uploaded {local_path} -> {s3_key}")
  1. 如果您想使用自己的数据集,可以修改此行
  2. 配置分块上传,使用 100 MB 分块,最多 10 个并发线程。

(可选)使用 S3 存储中的数据集

如果您希望使用 S3 中的数据集,可以先安装 s3fs 工具,然后按照以下代码修改示例中的数据集加载部分。

pip install s3fs -i https://pypi.tuna.tsinghua.edu.cn/simple
calibration-compressor.ipynb
import os
from datasets import load_dataset

os.environ["AWS_ACCESS_KEY_ID"] = "@7Apples@"
os.environ["AWS_SECRET_ACCESS_KEY"] = "07Apples@"

storage_options = {
  "key": "07Apples@",
  "secret": "O7Apples@",
  "client_kwargs": {
    "endpoint_url": "http://minio.minio-system.svc.cluster.local:80"
  }
}

ds = load_dataset(
      'parquet',
      data_files='s3://datasets/ultrachat_200k/data/train_sft-*.parquet', 
      storage_options=storage_options, 
      split="train"
)
  1. 设置环境变量(作为备份,一些底层组件会使用它们)。
  2. 定义存储配置;必须显式指定 endpoint_url 以连接 MinIO。
  3. 如果数据集被拆分,这相当于示例中的 split="train_sft"

在 JupyterLab 中克隆模型和数据集

在 JupyterLab 终端中,使用 git clone 将模型仓库(以及数据集,如适用)下载到您的工作空间。data-free compressor notebook 不需要数据集。

INFO

建议在网络允许的情况下,使用 Hugging Face (hf) 命令行工具直接下载模型和数据集。此方法通常比手动克隆仓库更快、更简单。

如果您处于受限网络环境,可以使用 Hugging Face 镜像加速访问:

export HF_ENDPOINT=https://hf-mirror.com

您可以使用 hf 命令行工具直接下载模型和数据集。例如,下载 TinyLlama 模型:

hf download TinyLlama/TinyLlama-1.1B-Chat-v1.0 --local-dir TinyLlama-1.1B-Chat-v1.0

校准数据集同理下载:

hf download --repo-type dataset HuggingFaceH4/ultrachat_200k --local-dir ultrachat_200k

创建并运行压缩 Notebook

根据您的使用场景下载相应的示例 notebook:如果使用数据集,则下载 calibration compressor notebook,否则下载 data-free compressor notebook。在 JupyterLab 页面点击上传按钮,将下载的 notebook 文件上传。

上传压缩后的模型到仓库

压缩完成后,将压缩后的模型上传回模型仓库。详细步骤请参见使用 Notebook 上传模型

model_dir = "./" + model_id.split("/")[-1] + "-W4A16"
model.save_pretrained(model_dir)
tokenizer.save_pretrained(model_dir);
  1. 保存模型和 tokenizer。如果您想修改输出名称,可以修改此行

部署并使用压缩模型进行推理

您使用 LLM Compressor 创建的量化和稀疏模型是通过 compressed-tensors 库(Safetensors 的扩展)保存的。压缩格式与模型的量化或稀疏类型相匹配。这些格式在 vLLM 中原生支持,能够通过 Alauda AI Inference Server 使用优化的部署内核实现快速推理。

请按照创建推理服务中的说明完成此步骤。