[中文] [English]
🔥 MFTCoder-accelerate 新增支持accelerate + FSDP框架, 支持全量微调和LoRA;
🔥 MFTCoder-accelerate 支持最新更多主流开源模型: mistral, mixtral-8x7b(Mixture of Experts), deepseek, chatglm3;
🔥 MFTCoder-accelerate 新增self-paced Loss, 用于收敛均衡;
🔥 MFTCoder-accelerate 支持使用accelerate + DeepSpeed框架下支持 全量参数/QLoRA/LoRA微调;
🔥 MFTCoder-accelerate 在训练中支持了多任务微调MFT, 可以同时平衡多个任务的训练,训练的模型支持多任务推理;
🔥 MFTCoder-accelerate 在训练中支持多种模型基座: codellama, llama2, llama, starcoder, codegeex2, chatglm2, qwen等
训练数据为jsonl格式,每一行的数据格式如下,其中chat_rounds字段是必需的,可以根据实际需求添加或删除其他字段。 可以参考项目中的xxx.jsonl文件。
{
"id":0,
"data_name":"code-helper",
"chat_rounds":[
{
"role": "system",
"content": "你是一个智能代码助手,可以回复用户与代码相关的问题"
},
{
"role": "human",
"content": "写一个快速排序"
},
{
"role": "bot",
"content": "以下是一个快速排序算法xxxxxx"
},
{
"role": "human",
"content": "解释一下这段代码"
},
{
"role": "bot",
"content": "好的,这段代码xxx"
}
]
}
推理数据格式为模型在训练数据格式下拼接的字符串形式,它也是推理时输入prompt拼接的方式:
"""
<s>system
这是System指令
<s>human
这是第1轮用户输入的问题
<s>bot
这是第1轮模型生成的内容{EOS_TOKEN}
<s>human
这是第2轮用户输入的问题
<s>bot
这是第2轮模型生成的内容{EOS_TOKEN}
...
...
...
<s>human
这是第n轮用户输入的问题
<s>bot
{模型现在要生成的内容}{EOS_TOKEN}
"""
目前支持全量参数(Full-parameters)指令微调、QLoRA指令微调,LoRA指令微调。 一些优秀的代码预训练模型权重,理论上,HuggingFace上开源的模型,均可使用本项目进行训练:
🤗 最新代码预训练SOTA,CodeLlama :code-llama-34b, code-llama-34b-python, 新的SOTA基座。
🤗 10B级别最佳代码预训练模型Starcoder wizardCoder-15B, PanGu-coder2等前SOTA的基座模型。
🤗 多语言能手Qwen-7b :适用于多语言任务,也适用中文任务。进行指令微调时。
mftcoder_accelerate文件结构
mftcoder_accelerate
|
src
configs
|
data
|
model
|
*pefts*
|
tokenizer
|
utils
|
evals
我们将训练中使用的各种组件抽取出来,以便后续的扩展和优化, 详见src
目录下的实现。
训练入口文件是mftcoder_accelerate/src/pefts/mft_accelerate.py
参数配置存储在mftcoder_accelerate/src/configs
目录下,方便统一管理和更改。
所以,在你开启训练之前,请进入src目录
cd mftcoder_accelerate/src
训练时,我们将多轮对话拼接成如下格式(也是上文中的推理数据格式),然后进行tokenize。 其中,默认情况下:
<s>human\n
作为human/user的起始符,<s>bot\n
作为bot/assistant的起始符,{EOS_TOKEN}
表示eos_token。
其中eos_token可以根据不同模型修改替换。不同角色的起始符可以配置,用来实现不同的对话/问答模版。
"<s>human\n{input1}<s>bot\n{target1}{EOS_TOKEN}<s>human\n{input2}<s>bot\n{target2}{EOS_TOKEN}\n"
在计算loss时,我们通过loss mask的方式,input部分的loss不参与参数更新,只有“target{EOS_TOKEN}”部分的loss参与参数更新。 这种方式充分利用了模型并行计算的优势,训练更加高效,同时也充分利用了decoder-only模型从左到右attention的特性,一次性将多轮对话中的每个target部分都参与了训练,训练更充分高效。
关于LoRA的详细介绍可参考论文:LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS
关于QLoRA的详细介绍可参考论文:QLORA: Efficient Finetuning of Quantized LLMs
QLoRA通过4-bit的nf4量化,且加入更多adapter,在大幅减少显存消耗的同时,尽可能逼近全量参数微调的效果。 QLoRA论文指出,该方法可以在一张V100上对33B的模型进行微调,并且性能逼近全量参数微调。
执行如下命令即可进行 Lora/QLora/全量 微调:
DeepSpeed配置在accelerate_ds_config.yaml中。
accelerate launch --config_file accelerate_ds_config.yaml pefts/mft_accelerate.py --train_config configs/xxx_train_config.json --distributed_type "DeepSpeed"
或者
DeepSpeed配置在脚本中通过命令行输入。
sh ds_single_launch.sh
FSDP配置在accelerate_fsdp_config.yaml中。
accelerate launch --config_file accelerate_fsdp_config.yaml pefts/mft_accelerate.py --train_config configs/xxx_train_config.json --distributed_type "FSDP"
或者
FSDP配置在脚本中通过命令行输入。
sh fsdp_single_launch.sh
训练需要的参数配置在configs/*_train_config
中,主要参数说明如下:
,
间隔不同path,每个path是一个目录,目录的最后一级名字作为任务名称,下面包含1到多个jsonl数据如果使用LoRA或者QLoRA进行训练,本项目仅保存adapter的权重和配置文件,需要将adapter权重与base model进行合并。 可以使用如下merge_base_and_lora_to_hf.py脚本。
python pefts/merge_base_and_lora_to_hf.py \
--base_model_or_path model_path \
--adaptor_path lora_adapter_path \
--model_type model_type \
--merged_output_path output_path
我们提供了单轮对话和多轮对话的如下脚本,该脚本可同时兼容大部分huggingface格式的模型。
from transformers import (
AutoTokenizer,
AutoModelForCausalLM,
)
model_name_or_path = "codefuse-ai/CodeFuse-Deepseek-33B"
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True, padding_side="left")
tokenizer.eos_token_id = tokenizer.convert_tokens_to_ids("<|end▁of▁sentence|>")
tokenizer.pad_token_id = tokenizer.eos_token_id
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, trust_remote_code=True)
HUMAN_ROLE_START_TAG = "<s>human\n"
BOT_ROLE_START_TAG = "<s>bot\n"
texts = ["write a python function of quick sort."]
texts = [f"{HUMAN_ROLE_START_TAG}{text}{BOT_ROLE_START_TAG}" for text in texts]
inputs = tokenizer(texts, return_tensors='pt', padding=True, add_special_tokens=False).to("cuda")
outputs = model.generate(
inputs=inputs["input_ids"],
attention_mask=inputs["attention_mask"],
max_new_tokens=512,
top_p=0.95,
temperature=0.1,
do_sample=True,
eos_token_id=tokenizer.eos_token_id,
pad_token_id=tokenizer.pad_token_id
)
gen_text = tokenizer.batch_decode(outputs[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)
print(gen_text)
生成脚本中的top_p、temperature、repetition_penalty、do_sample等参数对模型的生成效果影响较大,可按照自己的使用场景进行调试修改。 实践中,在代码生成场景中,如果采样模式,do_sample=True, top_p=0.95, temperature=0.1是pass@1指标的不错选择; 如果非采样模式, do_sample=False, beam_num=1或者3是不错的选择,其中beam_num=1即为greedy decoding。
如果发生OOM,可以缩小per_device_train_batch_size、seq_length等参数来缓解。由于面对的模型普遍较大(6b, 13b, 34b, 70b等)我们已经默认使用gradient_checkpointing技术,可以大幅降低显存占用,但训练速度会稍慢一些。
参考init_env.sh和requirements.txt
通过如下方式,即可指定使用0和1号卡进行训练:
CUDA_VISIBLE_DEVICES=0,1 accelerate launch --config_file pefts/accelerate_ds_config.yaml pefts/mft_accelerate.py --train_config configs/xxx_train_config.json --distributed_type "deepspeed"
首先,我们强烈建议您安装Flash Attention 2(FA2),(>=2.1.0, 2.3.6功能更齐全)。
训练参数中"attn_implementation" 设置成 "eager" 可以用naive attention,也就是未经加速的attention。
训练参数中"attn_implementation" 设置成 "flash_attention_2" 可以用FA2,速度快,省显存。
如果你可以自行安装环境并使用torch>=2.1.1,可以尝试设置参数"attn_implementation"为 "sdpa"。这样会尝试使用transformers兼容的torch.nn.functional.scaled_dot_product_attention。支持的模型还不全面。
对于LoRA/QLoRA, 我们推荐使用DeepSpeed作为底层分布式框架,它具有易用性和兼容性好的特点,并且速度很快。 FSDP 不支持QLoRA, 因为bitsandbytes暂不支持FSDP。
对于全量微调,我们推荐使用FSDP, 因为它在全量训练时可以发挥fully sharding的优势,达到更快的训练速度。
国产大模型比如chatglm2, chatglm3, baichuan2, qwen, aquila2等,使用的是和模型共同发布的modeling_xxx.py. 其它被transformers官方支持的大模型,由于已经升级支持flash attention等,所以全面切换到官方的modeling支持训练,之前的自定义modeling会被deprecated
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。