实战LLaMA2-7B指令微调

实战LLaMA2-7B指令微调

前言:数据质量远胜于数据数量------高质量的指令数据集能极大提升模型效果

1、Alpaca格式介绍

用一套固定的、清晰的格式(指令+输入+响应)来"教"AI如何正确地理解和完成人类的各种请求。

格式如下

txt 复制代码
### Instruction:
(指令内容-作用:告诉AI这次要"扮演"什么角色(翻译官、总结者、提问者等))

### Input:
(输入内容-完成这项任务所需要的具体资料,如一段需要翻译的文字,有时可以为空。比如你的指令是"讲个笑话",那就不需要额外材料。)

### Response:
(期望的回复-这是最关键的部分,是"教学样本"。AI通过成千上万张这样的"工作单"(指令+输入)和"标准答案"(响应)来学习,以后遇到类似的"指令+输入"时,它就能模仿着生成正确的"响应"。)

示例如下

复制代码
### Instruction:
把这段中文翻译成英文
### Input:
今天天气真好。
### Response:t
The weather is so nice today.

2、Databricks Dolly-15K数据集介绍

Databricks Dolly-15K 是一个由专家精心制作的、包含1.5万道高质量练习题的开源数据集,专门用于系统性地训练AI,让它变得更聪明、更听话、更有用。其遵循 CC开源协议 。这意味着任何个人、学校或公司(包括他们的竞争对手)都可以免费下载、使用甚至修改它 ,用来训练自己的AI模型。这极大地推动了整个AI行业的发展,让更多人能做出好用的AI。

3、实战

1、下载 数据集以 Alpaca-Style 格式化指令数据

python 复制代码
from datasets import load_dataset
from random import randrange

# 下载 databricks-dolly-15k 数据集
dataset = load_dataset("databricks/databricks-dolly-15k", split="train")

# 以 Alpaca-Style 格式化指令数据
def format_instruction(sample_data):
    """
    Formats the given data into a structured instruction format.

    Parameters:
    sample_data (dict): A dictionary containing 'response' and 'instruction' keys.

    Returns:
    str: A formatted string containing the instruction, input, and response.
    """
    # Check if required keys exist in the sample_data
    if 'response' not in sample_data or 'instruction' not in sample_data:
        # Handle the error or return a default message
        return "Error: 'response' or 'instruction' key missing in the input data."

    return f"""### Instruction:
Use the Input below to create an instruction, which could have been used to generate the input using an LLM.

### Input:
{sample_data['response']}

### Response:
{sample_data['instruction']}
"""

# 以 Alpaca-Style 格式化指令数据,然后随机抽选一个样例,打印 Alpaca 格式化后的样例
print(format_instruction(dataset[randrange(len(dataset))]))

2、加载和配置模型

使用快速注意力(Flash Attentio) 加速训练,检查硬件是否支持 Flash Attention

shell 复制代码
python -c "import torch; assert torch.cuda.get_device_capability()[0] >= 8, 'Hardware not supported for Flash Attention'"
# 如果硬件不支持,会显示:AssertionError: Hardware not supported for Flash Attention
# 如果硬件支持(CUDA compute capability >= 8.0),可以安装 flash-attn 加速包:
MAX_JOBS=4 pip install flash-attn --no-build-isolation
python 复制代码
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

# 检查硬件是否支持 Flash Attention
if torch.cuda.get_device_capability()[0] >= 8:
    from utils.llama_patch import replace_attn_with_flash_attn
    print("Using flash attention")
    replace_attn_with_flash_attn()
    use_flash_attention = True
else:
    use_flash_attention = False
    print("Hardware not supported for Flash Attention")

# 获取 LLAMA 2-7B 模型权重
# 无需 Meta AI 审核的模型权重,别人开源的
model_id = "NousResearch/llama-2-7b-hf"
# 通过 Meta AI 审核后可使用此 Model ID 下载
# model_id = "meta-llama/llama-2-7b-hf"

# 使用 BnB 加载优化后的模型
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

# 加载模型与分词器
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=bnb_config,
    use_cache=False,
    device_map="auto"
)

# 验证模型是否在使用 flash attention
if use_flash_attention:
    from utils.llama_patch import forward
    assert model.model.layers[0].self_attn.forward.__doc__ == forward.__doc__, "Model is not using flash attention"

tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
python 复制代码
import datetime
from transformers import TrainingArguments
from peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model

# 生成时间戳用于输出目录
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
# 演示训练参数(实际训练时可设置为 False)
demo_train = True
output_dir = f"models/llama-7-int4-dolly-{timestamp}"

# 训练超参数配置
args = TrainingArguments(
    output_dir=output_dir,
    num_train_epochs=1 if demo_train else 3,
    max_steps=100,
    per_device_train_batch_size=3,  # Nvidia T4 16GB 显存支持的最大 Batch Size
    gradient_accumulation_steps=1 if demo_train else 4,
    gradient_checkpointing=True,
    optim="paged_adamw_32bit",
    logging_steps=10,
    save_strategy="steps" if demo_train else "epoch",
    save_steps=10,
    learning_rate=2e-4,
    bf16=True,  # 修正:取消注释并启用 bfloat16
    max_grad_norm=0.3,
    warmup_ratio=0.03,
    lr_scheduler_type="constant"
)

# QLoRA 配置
peft_config = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.1,
    r=16,
    bias="none",
    task_type="CAUSAL_LM",  # 修正:将 "CAUSALL_LM" 改为 "CAUSAL_LM"
)

# 使用 QLoRA 配置加载 PEFT 模型
model = prepare_model_for_kbit_training(model)
qlora_model = get_peft_model(model, peft_config)

qlora_model.print_trainable_parameters()

SFTTrainer(监督式微调训练器)来训练模型。

python 复制代码
from trl import SFTTrainer

# 数据库的最大长度序列(筛选后的训练数据样例数为1158)
max_seq_length = 2048

trainer = SFTTrainer(
    model=qlora_model,  # 修正为 qlora_model
    train_dataset=dataset,
    peft_config=peft_config,
    max_seq_length=max_seq_length,
    tokenizer=tokenizer,
    packing=True,
    formatting_func=format_instruction,
    args=args,
)

3、开始训练模型

python 复制代码
trainer.train()

4、加载和运行经过微调的LLaMA2-7B模型进行推理

python 复制代码
# 代码片段1:使用微调后的LLaMA2-7B推理
import torch
from peft import AutoPeftModelForCausalLM
from transformers import AutoTokenizer

# model_dir = "models/llama-7-int4-dolly"
model_dir = "models/llama-7-int4-dolly-20240404_033139"

# 加载基础LLM模型与分词器
model = AutoPeftModelForCausalLM.from_pretrained(
    model_dir,
    low_cpu_mem_usage=True,
    torch_dtype=torch.float16,
    load_in_4bit=True,
)
tokenizer = AutoTokenizer.from_pretrained(model_dir)

# 代码片段2:生成测试样本
from datasets import load_dataset
from random import randrange

# 从hub加载数据集并得到一个样本
dataset = load_dataset("databricks/databricks-dolly-15k", split="train")
sample = dataset[randrange(len(dataset))]

prompt = f"""### Instruction:
Use the Input below to create an instruction, which could have been used to generate the input using an LLM.

### Input:
{sample['response']}

### Response:
"""

input_ids = tokenizer(prompt, return_tensors="pt", truncation=True).input_ids.cuda()

outputs = model.generate(input_ids=input_ids, max_new_tokens=100, do_sample=True, top_p=0.9, temperature=0.9)

print(f"Prompt:\n{sample['response']}\n")
print(f"Generated instruction:\n{tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0][len(prompt):]}")
print(f"Ground truth:\n{sample['instruction']}")

预期输出格式,示例

复制代码
Prompt:
The process of photosynthesis in plants converts light energy, usually from the sun, into chemical energy stored in glucose. This vital reaction takes place in the chloroplasts of plant cells and requires water and carbon dioxide, releasing oxygen as a byproduct.

Generated instruction:
Explain the process of photosynthesis in plants.

Ground truth:
Describe how photosynthesis works in plants.
  1. Prompt: 部分是从数据集中随机抽取的一个"回答"。它是一段关于光合作用的陈述性事实。
  2. Generated instruction: 部分是你的微调模型根据上面的回答所生成的"指令"。它学会了将一段陈述性文字,转换成一个可以引导LLM生成类似文本的提问式指令。
  3. Ground truth: 部分是数据集中人工编写的、与该回答配对的真实指令。它作为"标准答案",用于评估模型生成指令的质量。
相关推荐
sww_10265 分钟前
Spring-AI和LangChain4j区别
java·人工智能·spring
Coovally AI模型快速验证13 分钟前
超越Sora的开源思路:如何用预训练组件高效训练你的视频扩散模型?(附训练代码)
人工智能·算法·yolo·计算机视觉·音视频·无人机
GitCode官方24 分钟前
参会预告 | AtomGit 邀您共赴 TritonNext 2026 技术大会,解锁 AI 系统与编译生态新机遇
人工智能·开源·atomgit
MobiusStack32 分钟前
Cursor团队最新文章解读丨动态上下文发现,重新定义AI记忆
人工智能
Rui_Freely1 小时前
Vins-Fusion之 相机—IMU在线标定(十一)
人工智能·算法·计算机视觉
沛沛老爹1 小时前
Web开发者5分钟上手:Agent Skills环境搭建与基础使用实战
java·人工智能·llm·llama·rag·agent skills
DeepFlow 零侵扰全栈可观测1 小时前
3分钟定位OA系统GC瓶颈:DeepFlow全栈可观测平台实战解析
大数据·运维·人工智能·云原生·性能优化
想用offer打牌1 小时前
一站式讲清Spring AI Alibaba的OverAllState和RunnableConfig
人工智能·架构·github
生成论实验室1 小时前
生成论之基:“阴阳”作为元规则的重构与证成——基于《易经》与《道德经》的古典重诠与现代显象
人工智能·科技·神经网络·算法·架构
数据分享者1 小时前
对话对齐反馈数据集:12000+高质量人类-助手多轮对话用于RLHF模型训练与评估-人工智能-大语言模型对齐-人类反馈强化学习-训练符合人类期望的对话模型
人工智能·语言模型·自然语言处理