AutoGPTQ是一个基于GPTQ算法,简单易用且拥有用户友好型接口的大语言模型量化工具包。
性能对比推理速度以下结果通过这个脚本生成,文本输入的batchsize为1,解码策略为beamsearch并且强制模型生成512个token,速度的计量单位为tokens/s(越大越好)。
量化模型通过能够最大化推理速度的方式加载。
modelGPUnum_beamsfp16gptq-int4llama-7b1xA100-40G118.8725.53llama-7b1xA100-40G468.7991.30moss-moon16b1xA100-40G112.4815.25moss-moon16b1xA100-40G4OOM42.67moss-moon16b2xA100-40G106.8306.78moss-moon16b2xA100-40G413.1010.80gpt-j6b1xRTX3060-12G1OOM29.55gpt-j6b1xRTX3060-12G4OOM47.36困惑度(PPL)对于困惑度的对比,你可以参考 这里 和 这里快速开始量化和推理警告:这里仅是对AutoGPTQ中基本接口的用法展示,只使用了一条文本来量化一个特别小的模型,因此其结果的表现可能不如在大模型上执行量化后预期的那样好。
以下展示了使用 auto_gptq 进行量化和推理的最简单用法:fromtransformersimportAutoTokenizer,TextGenerationPipelinefromauto_gptqimportAutoGPTQForCausalLM,BaseQuantizeConfigpretrained_model_dir="facebook/opt-125m"quantized_model_dir="opt-125m-4bit"tokenizer=AutoTokenizer.from_pretrained(pretrained_model_dir,use_fast=True)examples=[tokenizer("auto-gptqisaneasy-to-usemodelquantizationlibrarywithuser-friendlyapis,basedonGPTQalgorithm.")]quantize_config=BaseQuantizeConfig(bits=4,#将模型量化为4-bit数值类型group_size=128,#一般推荐将此参数的值设置为128desc_act=False,#设为False可以显著提升推理速度,但是ppl可能会轻微地变差)#加载未量化的模型,默认情况下,模型总是会被加载到CPU内存中model=AutoGPTQForCausalLM.from_pretrained(pretrained_model_dir,quantize_config)#量化模型,样本的数据类型应该为List[Dict],其中字典的键有且仅有input_ids和attention_maskmodel.quantize(examples)#保存量化好的模型model.save_quantized(quantized_model_dir)#使用safetensors保存量化好的模型model.save_quantized(quantized_model_dir,use_safetensors=True)#将量化好的模型直接上传至HuggingFaceHub#当使用use_auth_token=True时,确保你已经首先使用huggingface-clilogin进行了登录#或者可以使用use_auth_token="hf_xxxxxxx"来显式地添加账户认证token#(取消下面三行代码的注释来使用该功能)#repo_id=f"YourUserName/{quantized_model_dir}"#commit_message=f"AutoGPTQmodelfor{pretrained_model_dir}:{quantize_config.bits}bits,gr{quantize_config.group_size},desc_act={quantize_config.desc_act}"#model.push_to_hub(repo_id,commit_message=commit_message,use_auth_token=True)#或者你也可以同时将量化好的模型保存到本地并上传至HuggingFaceHub#(取消下面三行代码的注释来使用该功能)#repo_id=f"YourUserName/{quantized_model_dir}"#commit_message=f"AutoGPTQmodelfor{pretrained_model_dir}:{quantize_config.bits}bits,gr{quantize_config.group_size},desc_act={quantize_config.desc_act}"#model.push_to_hub(repo_id,save_dir=quantized_model_dir,use_safetensors=True,commit_message=commit_message,use_auth_token=True)#加载量化好的模型到能被识别到的第一块显卡中model=AutoGPTQForCausalLM.from_quantized(quantized_model_dir,device="cuda:0")#从HuggingFaceHub下载量化好的模型并加载到能被识别到的第一块显卡中#model=AutoGPTQForCausalLM.from_quantized(repo_id,device="cuda:0",use_safetensors=True,use_triton=False)#使用model.generate执行推理print(tokenizer.decode(model.generate(**tokenizer("auto_gptqis",return_tensors="pt").to(model.device))[0]))#或者使用TextGenerationPipelinepipeline=TextGenerationPipeline(model=model,tokenizer=tokenizer)print(pipeline("auto-gptqis")[0]["generated_text"])参考 此样例脚本 以了解进阶的用法。自定义模型以下展示了如何拓展`auto_gptq`以支持`OPT`模型,如你所见,这非常简单:
fromauto_gptq.modelingimportBaseGPTQForCausalLMclassOPTGPTQForCausalLM(BaseGPTQForCausalLM):#chainedattributenameoftransformerlayerblocklayers_block_name="model.decoder.layers"#chainedattributenamesofothernnmodulesthatinthesamelevelasthetransformerlayerblockoutside_layer_modules=["model.decoder.embed_tokens","model.decoder.embed_positions","model.decoder.project_out","model.decoder.project_in","model.decoder.final_layer_norm"]#chainedattributenamesoflinearlayersintransformerlayermodule#normally,therearefoursublists,foreachonethemodulesinitcanbeseenasoneoperation,#andtheordershouldbetheorderwhentheyaretrulyexecuted,inthiscase(andusuallyinmostcases),#theyare:attentionq_k_vprojection,attentionoutputprojection,MLPprojectinput,MLPprojectoutputinside_layer_modules=[["self_attn.k_proj","self_attn.v_proj","self_attn.q_proj"],["self_attn.out_proj"],["fc1"],["fc2"]]然后,你就可以像在基本用法一节中展示的那样使用 OPTGPTQForCausalLM.from_pretrained 和其他方法。
在下游任务上执行评估你可以使用在 auto_gptq.eval_tasks 中定义的任务来评估量化前后的模型在某个特定下游任务上的表现。
这些预定义的模型支持所有在 transformers 和本项目中被实现了的causal-language-models。
以下是使用`cardiffnlp/tweet_sentiment_multilingual`数据集在序列分类(文本分类)任务上评估`EleutherAI/gpt-j-6b`模型的示例:fromfunctoolsimportpartialimportdatasetsfromtransformersimportAutoTokenizer,AutoModelForCausalLM,GenerationConfigfromauto_gptqimportAutoGPTQForCausalLM,BaseQuantizeConfigfromauto_gptq.eval_tasksimportSequenceClassificationTaskMODEL="EleutherAI/gpt-j-6b"DATASET="cardiffnlp/tweet_sentiment_multilingual"TEMPLATE="Question:What'sthesentimentofthegiventext?Choicesare{labels}.\nText:{text}\nAnswer:"ID2LABEL={0:"negative",1:"neutral",2:"positive"}LABELS=list(ID2LABEL.values())defds_refactor_fn(samples):text_data=samples["text"]label_data=samples["label"]new_samples={"prompt":[],"label":[]}fortext,labelinzip(text_data,label_data):prompt=TEMPLATE.format(labels=LABELS,text=text)new_samples["prompt"].append(prompt)new_samples["label"].append(ID2LABEL[label])returnnew_samples#model=AutoModelForCausalLM.from_pretrained(MODEL).eval().half().to("cuda:0")model=AutoGPTQForCausalLM.from_pretrained(MODEL,BaseQuantizeConfig())tokenizer=AutoTokenizer.from_pretrained(MODEL)task=SequenceClassificationTask(model=model,tokenizer=tokenizer,classes=LABELS,data_name_or_path=DATASET,prompt_col_name="prompt",label_col_name="label",**{"num_samples":1000,#howmanysampleswillbesampledtoevaluation"sample_max_len":1024,#maxtokensforeachsample"block_max_len":2048,#maxtokensforeachdatablock#functiontoloaddataset,onemustonlyacceptdata_name_or_pathasinput#andreturndatasets.Dataset"load_fn":partial(datasets.load_dataset,name="english"),#functiontopreprocessdataset,whichisusedfordatasets.Dataset.map,#mustreturnDict[str,list]withonlytwokeys:[prompt_col_name,label_col_name]"preprocess_fn":ds_refactor_fn,#truncatelabelwhensample'slengthexceedsample_max_len"truncate_prompt":False})#notethatmax_new_tokenswillbeautomaticallyspecifiedinternallybasedongivenclassesprint(task.run())#self-consistencyprint(task.run(generation_config=GenerationConfig(num_beams=3,num_return_sequences=3,do_sample=True)))了解更多教程 提供了将 auto_gptq 集成到你的项目中的手把手指导和最佳实践准则。
示例 提供了大量示例脚本以将 auto_gptq 用于不同领域。
评论