Uma das maiores vantagens do PEFT é que você só precisa salvar os parâmetros do adaptador (LoRA), não o modelo base completo. Isso tem enormes implicações práticas:
Após o treinamento, o adaptador LoRA é salvo como pesos adicionais. O modelo base permanece intacto.
# Salvar o adaptador LoRA
model.save_pretrained("./lora_adapter")
# Salvar tokenizer (se modificado, embora raro)
tokenizer.save_pretrained("./lora_adapter")
Isso cria um diretório ./lora_adapter com arquivos como:
adapter_config.json — Configuração LoRA (r, alpha, target_modules, etc.)adapter_model.bin — Pesos LoRA (A e B)README.md (opcional) — MetadadosImportante: O modelo base não é salvo aqui. Você deve manter acesso ao modelo base original (por exemplo, do Hugging Face Hub) para carregar o adaptador posteriormente.
Para usar o adaptador treinado:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
import torch
# Configuração de quantização (opcional para inferência eficiente)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
# Carregar modelo base
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)
# Carregar adaptador LoRA
model = PeftModel.from_pretrained(model, "./lora_adapter")
# O modelo agora tem comportamento especializado
model.eval() # Definir para modo de avaliação para inferência
Embora o carregamento dinâmico de adaptadores seja flexível, para implantação em produção ou inferência mais rápida, fundir pesos LoRA no modelo base é útil. Isso cria um modelo completo especializado que não requer infraestrutura PEFT durante a inferência.
# Fundir adaptador LoRA com modelo base
model = model.merge_and_unload()
# Agora o modelo é um modelo completo com pesos atualizados
# Salvar como modelo Hugging Face padrão
model.save_pretrained("./merged_model")
tokenizer.save_pretrained("./merged_model")
Aviso:
- Uma vez fundido, você não pode recarregar outro adaptador sem recarregar o modelo base original.
- O modelo fundido ocupa o mesmo espaço em disco que o modelo base original (~1GB para Qwen2.5-0.5B em FP16).
- A fusão só é possível se o modelo estiver em precisão completa (FP16/BF16). Se estiver quantizado para 4 bits, primeiro desquantize (requer mais memória).
# Se o modelo é de 4 bits, primeiro desquantize (requer mais VRAM)
model = model.dequantize() # Converte pesos para BF16/FP16
# Depois funde
model = model.merge_and_unload()
# Salvar
model.save_pretrained("./merged_model_full_precision")
Uma vez fundido e salvo, o modelo se comporta como qualquer modelo Hugging Face padrão:
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)
# Pronto para inferência sem PEFT!