PEFT的最大优势之一是你只需要保存适配器参数(LoRA),而不是完整的基模型。这具有巨大的实际意义:
训练后,LoRA适配器作为附加权重保存。基模型保持不变。
# 保存LoRA适配器
model.save_pretrained("./lora_adapter")
# 保存tokenizer(如果修改过,虽然很少见)
tokenizer.save_pretrained("./lora_adapter")
这会创建一个./lora_adapter目录,包含以下文件:
adapter_config.json — LoRA配置(r, alpha, target_modules等)adapter_model.bin — LoRA权重(A和B)README.md(可选)— 元数据重要提示: 基模型不会保存在这里。你必须保持对原始基模型(例如来自Hugging Face Hub)的访问权限,以便后续加载适配器。
要使用训练好的适配器:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
import torch
# 量化配置(可选用于高效推理)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
# 加载基模型
model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
# 加载LoRA适配器
model = PeftModel.from_pretrained(model, "./lora_adapter")
# 模型现在具有专业化行为
model.eval() # 设置为评估模式用于推理
虽然动态适配器加载很灵活,但为了生产部署或更快的推理,将LoRA权重合并到基模型中很有用。这会创建一个完整的专业化模型,在推理期间不需要PEFT基础设施。
# 将LoRA适配器与基模型合并
model = model.merge_and_unload()
# 现在模型是一个具有更新权重的完整模型
# 保存为标准Hugging Face模型
model.save_pretrained("./merged_model")
tokenizer.save_pretrained("./merged_model")
警告:
- 一旦合并,你无法重新加载另一个适配器而不重新加载原始基模型。
- 合并模型占用与原始基模型相同的磁盘空间(Qwen2.5-0.5B在FP16中约为1GB)。
- 合并仅在模型为完整精度(FP16/BF16)时可能。如果量化为4位,首先需要反量化(需要更多内存)。
# 如果模型是4位,首先反量化(需要更多显存)
model = model.dequantize() # 将权重转换为BF16/FP16
# 然后合并
model = model.merge_and_unload()
# 保存
model.save_pretrained("./merged_model_full_precision")
一旦合并并保存,模型表现得像任何标准Hugging Face模型:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"./merged_model",
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained("./merged_model", trust_remote_code=True)
# 准备好进行推理,无需PEFT!