• Llama2-Chinese项目:4-量化模型


    一.量化模型调用方式
      下面是一个调用FlagAlpha/Llama2-Chinese-13b-Chat[1]的4bit压缩版本FlagAlpha/Llama2-Chinese-13b-Chat-4bit[2]的例子:

    from transformers import AutoTokenizer
    from auto_gptq import AutoGPTQForCausalLM
    model = AutoGPTQForCausalLM.from_quantized('FlagAlpha/Llama2-Chinese-13b-Chat-4bit', device="cuda:0")
    tokenizer = AutoTokenizer.from_pretrained('FlagAlpha/Llama2-Chinese-13b-Chat-4bit',use_fast=False)
    input_ids = tokenizer(['Human: 怎么登上火星\nAssistant: '], return_tensors="pt",add_special_tokens=False).input_ids.to('cuda')        
    generate_input = {
        "input_ids":input_ids,
        "max_new_tokens":512,
        "do_sample":True,
        "top_k":50,
        "top_p":0.95,
        "temperature":0.3,
        "repetition_penalty":1.3,
        "eos_token_id":tokenizer.eos_token_id,
        "bos_token_id":tokenizer.bos_token_id,
        "pad_token_id":tokenizer.pad_token_id
    }
    generate_ids  = model.generate(**generate_input)
    text = tokenizer.decode(generate_ids[0])
    print(text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

      这里面有个问题就是由Llama2-Chinese-13b-Chat如何得到Llama2-Chinese-13b-Chat-4bit?这涉及另外一个AutoGPTQ库(一个基于GPTQ算法,简单易用且拥有用户友好型接口的大语言模型量化工具包)[3]。先梳理下思路,由于meta-llama/Llama-2-13b-chat-hf对中文支持较差,所以采用中文指令集在此基础上进行LoRA微调得到了FlagAlpha/Llama2-Chinese-13b-Chat-LoRA,而FlagAlpha/Llama2-Chinese-13b-Chat=FlagAlpha/Llama2-Chinese-13b-Chat-LoRA+meta-llama/Llama-2-13b-chat-hf,即将两者参数合并后的版本。FlagAlpha/Llama2-Chinese-13b-Chat-4bit就是对FlagAlpha/Llama2-Chinese-13b-Chat进行4bit量化后的版本。总结起来就是如何合并,如何量化这2个问题。官方提供的一些合并参数后的模型[4],如下所示:


    二.如何合并LoRA Model和Base Model
      网上合并LoRA参数和原始模型的脚本很多,参考文献[6]亲测可用。合并后的模型格式包括pthhuggingface两种。如下所示:
    1.LoRA Model文件列表
      对于LLama2-7B-hf进行LoRA微调生成文件如下所示:

    adapter_config.json
    adapter_model.bin
    optimizer.pt
    README.md
    rng_state.pth
    scheduler.pt
    special_tokens_map.json
    tokenizer.json
    tokenizer.model
    tokenizer_config.json
    trainer_state.json
    training_args.bin
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.Base Model文件列表
      LLama2-7B-hf文件列表,如下所示:

    config.json
    generation_config.json
    gitattributes.txt
    LICENSE.txt
    model-00001-of-00002.safetensors
    model-00002-of-00002.safetensors
    model.safetensors.index.json
    pytorch_model-00001-of-00002.bin
    pytorch_model-00002-of-00002.bin
    pytorch_model.bin.index.json
    README.md
    Responsible-Use-Guide.pdf
    special_tokens_map.json
    tokenizer.json
    tokenizer.model
    tokenizer_config.json
    USE_POLICY.md
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.合并后huggingface文件列表
      合并LoRA Model和Base Model后,生成huggingface格式文件列表,如下所示:

    config.json
    generation_config.json
    pytorch_model-00001-of-00007.bin
    pytorch_model-00002-of-00007.bin
    pytorch_model-00003-of-00007.bin
    pytorch_model-00004-of-00007.bin
    pytorch_model-00005-of-00007.bin
    pytorch_model-00006-of-00007.bin
    pytorch_model-00007-of-00007.bin
    pytorch_model.bin.index.json
    special_tokens_map.json
    tokenizer.model
    tokenizer_config.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.合并后pth文件列表
      合并LoRA Model和Base Model后,生成pth格式文件列表,如下所示:

    consolidated.00.pth
    params.json
    special_tokens_map.json
    tokenizer.model
    tokenizer_config.json
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.合并脚本[6]思路
      以合并后生成huggingface模型格式为例,介绍合并脚本的思路,如下所示:

    # 步骤1:加载base model
    base_model = LlamaForCausalLM.from_pretrained(
        base_model_path, # 基础模型路径
        load_in_8bit=False, # 加载8位
        torch_dtype=torch.float16, # float16
        device_map={"": "cpu"}, # cpu
    )
    
    # 步骤2:遍历LoRA模型
    for lora_index, lora_model_path in enumerate(lora_model_paths):
        # 步骤3:根据base model和lora model来初始化PEFT模型
        lora_model = PeftModel.from_pretrained(
                    base_model, # 基础模型
                    lora_model_path, # LoRA模型路径
                    device_map={"": "cpu"}, # cpu
                    torch_dtype=torch.float16, # float16
                )
        # 步骤4:将lora model和base model合并为一个独立的model         
        base_model = lora_model.merge_and_unload()
        ......
    
    # 步骤5:保存tokenizer
    tokenizer.save_pretrained(output_dir)
    
    # 步骤6:保存合并后的独立model
    LlamaForCausalLM.save_pretrained(base_model, output_dir, save_function=torch.save, max_shard_size="2GB")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

      合并LoRA Model和Base Model过程中输出日志可参考huggingface[7]和pth[8]。

    三.如何量化4bit模型
      如果得到了一个训练好的模型,比如LLama2-7B,如何得到LLama2-7B-4bit呢?因为模型参数越来越多,多参数模型的量化还是会比少参数模型的非量化效果要好。量化的方案非常的多[9][12],比如AutoGPTQ、GPTQ-for-LLaMa、exllama、llama.cpp等。下面重点介绍下AutoGPTQ的基础实践过程[10],AutoGPTQ进阶教程参考文献[11]。

    from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig # 量化配置
    from transformers import AutoTokenizer
    
    # 第1部分:量化一个预训练模型
    pretrained_model_name = r"L:/20230713_HuggingFaceModel/20230903_Llama2/Llama-2-7b-hf" # 预训练模型路径
    quantize_config = BaseQuantizeConfig(bits=4, group_size=128) # 量化配置,bits表示量化后的位数,group_size表示分组大小
    model = AutoGPTQForCausalLM.from_pretrained(pretrained_model_name, quantize_config) # 加载预训练模型
    tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name) # 加载tokenizer
    
    examples = [ # 量化样本
        tokenizer(
            "auto-gptq is an easy-to-use model quantization library with user-friendly apis, based on GPTQ algorithm."
        )
    ]
    # 翻译:准备examples(一个只有两个键'input_ids'和'attention_mask'的字典列表)来指导量化。这里只使用一个文本来简化代码,但是应该注意,使用的examples越多,量化后的模型就越好(很可能)。
    model.quantize(examples) # 执行量化操作,examples提供量化过程所需的示例数据
    quantized_model_dir = "./llama2_quantize_AutoGPTQ" # 保存量化后的模型
    model.save_quantized(quantized_model_dir) # 保存量化后的模型
    
    
    # 第2部分:加载量化模型和推理
    from transformers import TextGenerationPipeline # 生成文本
    
    device = "cuda:0"
    model = AutoGPTQForCausalLM.from_quantized(quantized_model_dir, device=device) # 加载量化模型
    pipeline = TextGenerationPipeline(model=model, tokenizer=tokenizer, device=device) # 得到pipeline管道
    print(pipeline("auto-gptq is")[0]["generated_text"]) # 生成文本
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    参考文献:
    [1]https://huggingface.co/FlagAlpha/Llama2-Chinese-13b-Chat
    [2]https://huggingface.co/FlagAlpha/Llama2-Chinese-13b-Chat-4bit
    [3]https://github.com/PanQiWei/AutoGPTQ/blob/main/README_zh.md
    [4]https://github.com/FlagAlpha/Llama2-Chinese#基于Llama2的中文微调模型
    [5]CPU中合并权重(合并思路仅供参考):https://github.com/yangjianxin1/Firefly/blob/master/script/merge_lora.py
    [6]https://github.com/ai408/nlp-engineering/blob/main/20230916_Llama2-Chinese/tools/merge_llama_with_lora.py
    [7]https://github.com/ai408/nlp-engineering/blob/main/20230916_Llama2-Chinese/tools/merge_llama_with_lora_log/merge_llama_with_lora_hf_log
    [8]https://github.com/ai408/nlp-engineering/blob/main/20230916_Llama2-Chinese/tools/merge_llama_with_lora_log/merge_llama_with_lora_pt_log
    [9]LLaMa量化部署:https://zhuanlan.zhihu.com/p/641641929
    [10]AutoGPTQ基础教程:https://github.com/PanQiWei/AutoGPTQ/blob/main/docs/tutorial/01-Quick-Start.md
    [11]AutoGPTQ进阶教程:https://github.com/PanQiWei/AutoGPTQ/blob/main/docs/tutorial/02-Advanced-Model-Loading-and-Best-Practice.md
    [12]Inference Experiments with LLaMA v2 7b:https://github.com/djliden/inference-experiments/blob/main/llama2/README.md
    [13]llama2_quantize_AutoGPTQ:https://github.com/ai408/nlp-engineering/blob/main/20230916_Llama2-Chinese/tools/llama2_quantize_AutoGPTQ.py

  • 相关阅读:
    企业无线局域网部署最佳实践
    嵌入式软硬件
    IAP程序升级 与 电脑BIOS 的关系
    冰蝎Java WebShell免杀生成 -- ByPassBehinder4J​
    Redis数据类型
    EFCore的新东西
    ACCESS教程之如何实现基于关键词组合两个表、left join、字符串包含关系 excel和access联动(教程含详细操作方式)
    Linux中vim查看文件某内容
    JAVA-元注解和注解
    【C++】入门篇-关键字&&命名空间&&输入输出&&缺省参数
  • 原文地址:https://blog.csdn.net/shengshengwang/article/details/133501241