在Databricks中将CALM2转换为AWQ格式

我沉迷其中超过了预期,花费了很多时间…

引入

我在下面的文章中使用了CyberAgent公司的CALM2。
由于现在还有与Transformers的AWQ格式集成在一起的问题,所以我将尝试将CALM2量子化为AWQ格式来使用。
(通常Bloke兄弟会给我提供AWQ格式的存储库,但这次不知道为什么被取消了)

 

2023/11/06更新:TheBloke兄貴也再次被提及了呢。看起来这个方法很实用。如果你想自己进行AWQ量子化,可以参考以下内容。

 

步骤1. 准备量子化时的校准数据集。

在进行量子化时,需要准备适当的数据集进行校准。

由于这里有人提供CALM2的GPTQ模型,所以我会使用与此处相同的以下校准数据集。

 

并且,这里是GPTQ模型。

 

请随意创建一个笔记本,并执行从huggingface获取数据的过程。
请务必在CPU集群+ML运行时上执行以下处理。

在GPU集群运行时,可能是由于文件系统的差异导致load_dataset出现错误。
(我认为这是在Databricks中使用时的固有问题,这是我遇到的最大问题点)

from datasets import load_dataset

def load_ja_calib():
    data = load_dataset("mmnga/wikipedia-ja-20230720-1k", split="train")    
    return spark.createDataFrame(data)

load_ja_calib().write.saveAsTable("training.llm.mmnga_wikipedia_ja_20230720_1k")

这次将以“mmnga_wikipedia_ja_20230720_1k”作为表名保存在training.llm模式中。请提前准备好该模式。

然而,Spark和HuggingFace数据集之间的相互转换非常方便。

第二步:加载模型和量子化

我将在GPU集群中执行处理。
我使用了g5.4xlarge的AWS实例类型。DBR版本是14.1ML。

安装必要的模块。
据说autoawq在0.1.5和0.1.6版本之间的内部处理有相当大的变化,但我会使用最新版本(0.1.6)来运行。
※由于需要pytorch >= 2.1.0,所以安装可能需要一些时间。

%pip install -U transformers accelerate
%pip install autoawq=="0.1.6"

dbutils.library.restartPython()

定义函数以读取校准数据。

def load_ja_calib():
    df = spark.table("training.llm.mmnga_wikipedia_ja_20230720_1k")
    pdf = df.select("text").toPandas()

    return list(pdf["text"])

使用AutoAWQ加载模型。
CALM2模型使用先前保存的模型进行操作。

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

UC_VOLUME = "/Volumes/training/llm/model_snapshots"
uc_dir = "/models--cyberagent--calm2-7b-chat"
model_path = f"{UC_VOLUME}{uc_dir}"

quant_config = { "zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM" }

# Load model
model = AutoAWQForCausalLM.from_pretrained(model_path, device_map="auto", torch_dtype="auto")
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# Quantize
model.quantize(tokenizer, quant_config=quant_config, calib_data=load_ja_calib())

如果没有问题,加载和量子化处理会被执行,并在大约20分钟内完成。

步骤3. 量子模型的存储

添加一个用于加载transformers的设定,并将模型存储在临时文件夹中。

from transformers import AwqConfig, AutoConfig

quant_path = "/tmp/local-calm2-7b-chat-AWQ"

# modify the config file so that it is compatible with transformers integration
quantization_config = AwqConfig(
    bits=quant_config["w_bit"],
    group_size=quant_config["q_group_size"],
    zero_point=quant_config["zero_point"],
    version=quant_config["version"].lower(),
).to_dict()

model.model.config.quantization_config = quantization_config

# Save quantized model
model.save_quantized(quant_path, safetensors=True)
tokenizer.save_pretrained(quant_path)

由於如果繼續這樣下去,文件將在集群結束時消失,所以我們將它們存儲到Unity目錄卷。

dbutils.fs.cp("file:/tmp/calm2-7b-chat-AWQ", "/Volumes/training/llm/model_snapshots/models--local--cyberagent-calm2-7b-chat-AWQ-calib-ja-1k", recurse=True)

第四步:进行推论

为了确认是否成功进行转换,我们将加载转换后的模型并进行推理。

from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers import TextStreamer

model_path = "/Volumes/training/llm/model_snapshots/models--local--cyberagent-calm2-7b-chat-AWQ-calib-ja-1k"

model = AutoModelForCausalLM.from_pretrained(model_path, device_map="cuda")
tokenizer = AutoTokenizer.from_pretrained(model_path)
streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
def generate_stream_text(prompt: str, max_new_tokens: int = 512) -> str:

    tokens = tokenizer(prompt, return_tensors="pt").input_ids.cuda()

    generation_config = GenerationConfig(
        max_new_tokens=max_new_tokens,
        do_sample=True,
        top_k=40,
        top_p=0.95,
        temperature=0.7,
        eos_token_id=model.config.eos_token_id,
        pad_token_id=model.config.pad_token_id,
    )

    generation_output = model.generate(
        tokens,
        streamer=streamer,
        generation_config=generation_config,
    )

    return tokenizer.decode(generation_output[0], skip_special_tokens=True)

我会用中文来回答尊敬的npaka先生的问题。

prompt = """USER: まどか☆マギカで誰が一番かわいい?
ASSISTANT: """

max_new_tokens = 128
_ = generate_stream_text(prompt, max_new_tokens)
まどか☆マギカのキャラクターは、それぞれ個性的な性格やビジュアルを持っています。

その中でも、一番かわいいと人気が高いのは鹿目まどかでしょう。彼女の優しさや純粋さ、そして何より魔法少女としての強さを持っていることが、多くのファンを魅了している理由でしょう。

また、巴マミや暁美ほむらなども、女性ファンからの人気が高いです。彼女たちの強さや優しさ、そして魔法少女としての責任感などが、多くのファンを引きつける魅力となっています。

他にも、美樹さやかや佐倉杏子など、個性的なキャラクターがたくさんいるのがまどか☆マギ

他看起来非常稳重。

我也会用英文来听一下。

prompt = """USER: What is Databricks?
ASSISTANT: """

max_new_tokens = 128
_ = generate_stream_text(prompt, max_new_tokens)
1. Databricks, Inc. is an American cloud computing company that provides a platform for building, managing, and securing data pipelines and workloads.
2. Databricks provides a cloud-based platform that allows users to build and manage data pipelines and workloads for their data lakes, data warehouses, and analytics workflows. It offers a range of tools and services, including Apache Spark, Apache Kafka, Apache Flink, and Apache Beam, to help users manage their data pipelines and workflows.
3. Databricks provides a comprehensive cloud platform for building and managing

不管内容的正确与否,这是一篇没有破绽的文章。

总结

我自己尝试进行了AWQ的量化。对于日语LLM来说,准备好校准数据似乎很重要,但说实话,我在这方面是个外行,想知道最佳实践是什么。。。

由于TheBloke大兄贵发布了AWQ转换好的模型,因此主要的LLM可能没有太多自己转换的机会。然而,由于已经与Transformers集成,所以需求似乎会增加。

我个人认为,在Databricks上使用Transformers时,相较于GPTQ,AWQ更易于操作。
(这是我的一个技术问题,我在Databricks上真的无法很好地处理GPTQ模型…)

然而,根据下面的博客,GPTQ(或者说是Exllama)得出的结果似乎是最佳的,我希望能够更好地运用它(我也想看看vLLM在调优之后的比较结果)。

 

还有,请有人把它上传到Huggingface Hub。(你自己来做)

bannerAds