Datawhale干货
作者:宋志学,Datawhale成员


项目地址↓ 欢迎 Star ⭐️
https://github.com/datawhalechina/self-llm/tree/master/examples

Step 2: 数据准备
第2幕(退朝,百官散去)官员甲:咱们皇上可真是器重年将军和隆科多大人。官员乙:隆科多大人,恭喜恭喜啊!您可是国家的大功臣啊!官员丙:年大将军,皇上对你可是垂青有加呀!官员丁:年大人,您可是皇上的股肱之臣哪!苏培盛(追上年羹尧):年大将军请留步。大将军——年羹尧:苏公公,有何指教?苏培盛:不敢。皇上惦记大将军您的臂伤,特让奴才将这秘制的金创药膏交给大人,叫您使用。年羹尧(遥向金銮殿拱手):臣年羹尧恭谢皇上圣恩!敢问苏公公,小妹今日在宫中可好啊?苏培盛:华妃娘娘凤仪万千、宠冠六宫啊,大将军您放心好了。年羹尧:那就有劳苏公公了。(转身离去)苏培盛:应该的。
[
{"rloe":"官员甲", "content":"咱们皇上可真是器重年将军和隆科多大人。"},
{"rloe":"官员乙", "content":"隆科多大人,恭喜恭喜啊!您可是国家的大功臣啊!"},
{"rloe":"官员丙", "content":"年大将军,皇上对你可是垂青有加呀!"},
{"rloe":"官员丁", "content":"年大人,您可是皇上的股肱之臣哪!"},
{"rloe":"苏培盛", "content":"年大将军请留步。大将军——"}, ...]
可以借助一个小工具:extract-dialogue 从文本中提取对话。
......原来孙悟空走了以后,有一个混世魔王独占了水帘洞,并且抢走了许多猴子猴孙。孙悟空听到这些以后,气得咬牙跺脚。他问清了混世魔王的住处,决定找混世魔王报仇,便驾着筋斗云,朝北方飞去。不一会儿,孙悟空就来到混世魔王的水脏洞前,对门前的小妖喊到∶“你家那个狗屁魔王,多次欺负我们猴子。我今天来,要和那魔王比比高低!”小妖跑进洞里,报告魔王。魔王急忙穿上铁甲,提着大刀,在小妖们的簇拥下走出洞门。孙悟空赤手空拳,夺过了混世魔王的大刀,把他劈成了两半。然后,拔下一把毫毛咬碎喷了出去,毫毛变成许多小猴子,直杀进洞里,把所有的妖精全杀死,然后救出被抢走的小猴子,放了一把火烧了水脏洞。......
chat-甄嬛 的原始数据: https://github.com/KMnO4-zx/huanhuan-chat/tree/master/dataset/input/huanhuan 西游记白话文原始数据: https://github.com/KMnO4-zx/huanhuan-chat/blob/master/dataset/input/wukong/%E8%A5%BF%E6%B8%B8%E8%AE%B0%E7%99%BD%E8%AF%9D%E6%96%87.txt
最后再将其整理成 json
格式的数据,如下:
[ {"instruction": "小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——",
"input": "",
"output": "嘘——都说许愿说破是不灵的。" }, {"instruction": "这个温太医啊,也是古怪,谁不知太医不得皇命不能为皇族以外的人请脉诊病,他倒好,十天半月便往咱们府里跑。",
"input": "",
"output": "你们俩话太多了,我该和温太医要一剂药,好好治治你们。" }, {"instruction": "嬛妹妹,刚刚我去府上请脉,听甄伯母说你来这里进香了。",
"input": "",
"output": "出来走走,也是散心。" }]
Chat-嬛嬛 的数据: https://github.com/datawhalechina/self-llm/blob/master/dataset/huanhuan.json
所以,在这一步处理数据的大致思路就是:
1. 从原始数据中提取出角色和对话
2. 筛选出我们关注的角色的对话
3. 将对话转换成我们需要的格式
这一步也可以增加数据增强的环节,比如利用两到三条数据作为 example 丢给LLM,让其生成风格类似的数据。再或者也可以找一部分日常对话的数据集,使用 RAG 生成一些固定角色风格的对话数据。这里大家可以完全放开的大胆去尝试!
Step 3: 模型训练
self-llm
的每一个模型中,都会有一个 Lora
微调模块,我们只需要将数据处理成我们需要的格式,然后再调用我们的训练脚本即可。LLaMA3_1-8B-Instruct
模型进行微调,首先还是要下载模型,创建一个model_download.py
文件,输入以下内容:
import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import osmodel_dir = snapshot_download('LLM-Research/Meta-Llama-3.1-8B-Instruct', cache_dir='/root/autodl-tmp', revision='master')
注意:记得修改 cache_dir
为你的模型下载路径哦~
self-llm
的同学来说,这一步可能再简单不过了,在此处我会在当前目录下放置train.py
,大家修改其中的数据集路径和模型路径即可。当然也可以使用 self-llm 中的 lora 微调教程。 教程地址: https://github.com/datawhalechina/self-llm/blob/master/models/LLaMA3/04-LLaMA3-8B-Instruct%20Lora%20%E5%BE%AE%E8%B0%83.md
python train.py
train.py
中的数据集路径和模型路径哦~output
目录下生成lora
模型。可以使用以下代码进行测试:
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import PeftModelmode_path = './LLM-Research/Meta-Llama-3___1-8B-Instruct'
lora_path = './output/llama3_1_instruct_lora/checkpoint-699' # 这里改称你的 lora 输出对应 checkpoint 地址# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(mode_path, trust_remote_code=True)# 加载模型
model = AutoModelForCausalLM.from_pretrained(mode_path, device_map="auto",torch_dtype=torch.bfloat16, trust_remote_code=True).eval()# 加载lora权重
model = PeftModel.from_pretrained(model, model_id=lora_path)prompt = "嬛嬛你怎么了,朕替你打抱不平!"
messages = [{"role": "system", "content": "假设你是皇帝身边的女人--甄嬛。"},
{"role": "user", "content": prompt}]input_ids = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
# print(input_ids)
model_inputs = tokenizer([input_ids], return_tensors="pt").to('cuda')
generated_ids = model.generate(model_inputs.input_ids,max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print('皇上:', prompt)
print('嬛嬛:',response)
皇上: 嬛嬛你怎么了,朕替你打抱不平!嬛嬛: 皇上,臣妾不是故意的。
有兴趣的同学可以尝试使用
self-llm
中的其他模型进行微调,检验你的学习成果!Chat-嬛嬛贡献者
肖鸿儒(Datawhale成员)
来一起共建、共享 self-llm examples系列