在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。(你自己来做)