当前位置:   article > 正文

ChatGLM3-6B部署与微调及微调后使用_chatglm3-6b 微调

chatglm3-6b 微调

目录

一、下载代码

二、下载模型

三、 启动验证

四、 微调

五、 微调后的模型


记录ChatGLM3-6B部署及官方Lora微调示例详细步骤及如何使用微调后的模型进行推理

一、下载代码

使用git clone 命令下载源码

git clone https://github.com/THUDM/ChatGLM3.git

如图所示

二、下载模型

模型权重文件从魔塔进行下载,不需要翻墙。权重文件比较大,所以花费时间也比较长,请耐心等待。

  1. git lfs install
  2. git clone https://www.modelscope.cn/ZhipuAI/chatglm3-6b.git

  

使用pwd命令获取模型路径,这个路径后面需要用到:

  1. pwd
  2. /mnt/workspace/chatglm3-6b

三、 启动验证

使用命令方式启动,启动之前需要修改模型地址配置。在路径 ChatGLM3/basic_demo 下找到文件 cli_demo.py 文件,修改MODEL_PATH,修改后的路径就是第二步【下载模型】后使用 pwd 命令查询出来的路径。

启动之前安装依赖

  1. cd 到 ChatGLM3 路径下
  2. pip install -r requirements.txt

使用一下命令启动并验证,第一次启动会略慢

  1. cd 到 basic_demo 路径下
  2. python cli_demo.py

四、 微调

经过多次尝试,微调的GPU显存应不小于24G,不然容易报OOM等错误。微调参数意义参考: ChatGLM3/finetune_demo at main · THUDM/ChatGLM3 (github.com)

首先先安装微调的依赖

  1. cd 到目录 ChatGLM3/finetune_demo
  2. pip install -r requirements.txt

 上传数据

转换数据,调整为标准的对话格式

  1. import json
  2. from typing import Union
  3. from pathlib import Path
  4. def _resolve_path(path: Union[str, Path]) -> Path:
  5. return Path(path).expanduser().resolve()
  6. def _mkdir(dir_name: Union[str, Path]):
  7. dir_name = _resolve_path(dir_name)
  8. if not dir_name.is_dir():
  9. dir_name.mkdir(parents=True, exist_ok=False)
  10. def convert_adgen(data_dir: Union[str, Path], save_dir: Union[str, Path]):
  11. def _convert(in_file: Path, out_file: Path):
  12. _mkdir(out_file.parent)
  13. with open(in_file, encoding='utf-8') as fin:
  14. with open(out_file, 'wt', encoding='utf-8') as fout:
  15. for line in fin:
  16. dct = json.loads(line)
  17. sample = {'conversations': [{'role': 'user', 'content': dct['content']},
  18. {'role': 'assistant', 'content': dct['summary']}]}
  19. fout.write(json.dumps(sample, ensure_ascii=False) + '\n')
  20. data_dir = _resolve_path(data_dir)
  21. save_dir = _resolve_path(save_dir)
  22. train_file = data_dir / 'train.json'
  23. if train_file.is_file():
  24. out_file = save_dir / train_file.relative_to(data_dir)
  25. _convert(train_file, out_file)
  26. dev_file = data_dir / 'dev.json'
  27. if dev_file.is_file():
  28. out_file = save_dir / dev_file.relative_to(data_dir)
  29. _convert(dev_file, out_file)
  30. convert_adgen('data/AdvertiseGen', 'data/AdvertiseGen_fix')

 得到转换后的训练和验证数据:

使用以下命令开始训练, data/AdvertiseGen_fix  - 微调数据路径; /mnt/workspace/chatglm3-6b - 模型权重路径

  1. cd 到 finetune_demo 目录下
  2. CUDA_VISIBLE_DEVICES=0 NCCL_P2P_DISABLE="1" NCCL_IB_DISABLE="1" python finetune_hf.py data/AdvertiseGen_fix /mnt/workspace/chatglm3-6b configs/lora.yaml

训练中,根据数据量和参数设置的不同而花费的时间不同,我大概花了1个小时

 验证微调后的效果

CUDA_VISIBLE_DEVICES=0 NCCL_P2P_DISABLE="1" NCCL_IB_DISABLE="1" python inference_hf.py output/checkpoint-3000/ --prompt "类型#裙*版型#显瘦*材质#网纱*风格#性感*裙型#百褶*裙下摆#压褶*裙长#连衣裙*裙衣门襟#拉链*裙衣门襟#套头*裙款式#拼接*裙款式#拉链*裙款式#木耳边*裙款式#抽褶*裙款式#不规则"

 

五、 微调后的模型

如果想要在 basic_demo 路径下的各demo中结合使用微调后的模型,需要修改 basic_demo/ 下的*_demo.py代码,即使用 finetune_demo/inference_hf 中的 方法 load_model_and_tokenizer 替换各demo里面获取 model 和 tokenizer的方法

  1. def load_model_and_tokenizer(
  2. model_dir: Union[str, Path], trust_remote_code: bool = True
  3. ) -> tuple[ModelType, TokenizerType]:
  4. model_dir = _resolve_path(model_dir)
  5. if (model_dir / 'adapter_config.json').exists():
  6. model = AutoPeftModelForCausalLM.from_pretrained(
  7. model_dir, trust_remote_code=trust_remote_code, device_map='auto'
  8. )
  9. tokenizer_dir = model.peft_config['default'].base_model_name_or_path
  10. else:
  11. model = AutoModelForCausalLM.from_pretrained(
  12. model_dir, trust_remote_code=trust_remote_code, device_map='auto'
  13. )
  14. tokenizer_dir = model_dir
  15. tokenizer = AutoTokenizer.from_pretrained(
  16. tokenizer_dir, trust_remote_code=trust_remote_code
  17. )
  18. return model, tokenizer

以 basic_demo/cli_demo.py 为例,暴力粘合后的代码如下:

  1. import os
  2. import platform
  3. from pathlib import Path
  4. from typing import Annotated, Union
  5. from peft import AutoPeftModelForCausalLM, PeftModelForCausalLM
  6. from transformers import (
  7. AutoModelForCausalLM,
  8. AutoTokenizer,
  9. PreTrainedModel,
  10. PreTrainedTokenizer,
  11. PreTrainedTokenizerFast,
  12. )
  13. ModelType = Union[PreTrainedModel, PeftModelForCausalLM]
  14. TokenizerType = Union[PreTrainedTokenizer, PreTrainedTokenizerFast]
  15. def _resolve_path(path: Union[str, Path]) -> Path:
  16. return Path(path).expanduser().resolve()
  17. MODEL_PATH = os.environ.get('MODEL_PATH', 'THUDM/chatglm3-6b')
  18. TOKENIZER_PATH = os.environ.get("TOKENIZER_PATH", MODEL_PATH)
  19. def load_model_and_tokenizer(model_dir: Union[str, Path]) -> tuple[ModelType, TokenizerType]:
  20. model_dir = _resolve_path(model_dir)
  21. if (model_dir / 'adapter_config.json').exists():
  22. model = AutoPeftModelForCausalLM.from_pretrained(
  23. model_dir, trust_remote_code=True, device_map='auto'
  24. )
  25. tokenizer_dir = model.peft_config['default'].base_model_name_or_path
  26. else:
  27. model = AutoModelForCausalLM.from_pretrained(
  28. model_dir, trust_remote_code=True, device_map='auto'
  29. )
  30. tokenizer_dir = model_dir
  31. tokenizer = AutoTokenizer.from_pretrained(
  32. tokenizer_dir, trust_remote_code=True
  33. )
  34. return model, tokenizer
  35. # tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH, trust_remote_code=True)
  36. # model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True, device_map="auto").eval()
  37. finetune_path = '/mnt/workspace/ChatGLM3/finetune_demo/output/checkpoint-3000'
  38. model, tokenizer = load_model_and_tokenizer(finetune_path)
  39. # add .quantize(bits=4, device="cuda").cuda() before .eval() to use int4 model
  40. # must use cuda to load int4 model
  41. os_name = platform.system()
  42. clear_command = 'cls' if os_name == 'Windows' else 'clear'
  43. stop_stream = False
  44. welcome_prompt = "欢迎使用 ChatGLM3-6B 模型,输入内容即可进行对话,clear 清空对话历史,stop 终止程序"
  45. def build_prompt(history):
  46. prompt = welcome_prompt
  47. for query, response in history:
  48. prompt += f"\n\n用户:{query}"
  49. prompt += f"\n\nChatGLM3-6B:{response}"
  50. return prompt
  51. def main():
  52. past_key_values, history = None, []
  53. global stop_stream
  54. print(welcome_prompt)
  55. while True:
  56. query = input("\n用户:")
  57. if query.strip() == "stop":
  58. break
  59. if query.strip() == "clear":
  60. past_key_values, history = None, []
  61. os.system(clear_command)
  62. print(welcome_prompt)
  63. continue
  64. print("\nChatGLM:", end="")
  65. current_length = 0
  66. for response, history, past_key_values in model.stream_chat(tokenizer, query, history=history, top_p=1,
  67. temperature=0.01,
  68. past_key_values=past_key_values,
  69. return_past_key_values=True):
  70. if stop_stream:
  71. stop_stream = False
  72. break
  73. else:
  74. print(response[current_length:], end="", flush=True)
  75. current_length = len(response)
  76. print("")
  77. if __name__ == "__main__":
  78. main()

 其中,注释掉的为原获取 model 和 tokenizer的方法

最后使用 python cli_demo.py执行测试

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/968031
推荐阅读
相关标签
  

闽ICP备14008679号