Fine-tunes LLMs with Hugging Face PEFT (LoRA, QLoRA, IA3, multi-adapter serve) training under 1% of weights. Use when adapting 7B–70B models on limited GPU memory or serving multiple adapters from one base. Not for full-weight fine-tuning of small models and not for hosting Gradio demos (huggingface-spaces).
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Fine-tunes LLMs with Hugging Face PEFT (LoRA, QLoRA, IA3, multi-adapter serve) training under 1% of weights. Use when adapting 7B–70B models on limited GPU memory or serving multiple adapters from one base. Not for full-weight fine-tuning of small models and not for hosting Gradio demos (huggingface-spaces).
Fine-tune LLMs by training <1% of parameters using LoRA, QLoRA, and 25+ adapter methods. HuggingFace's official library integrated with the transformers ecosystem.
When to Use
Use PEFT/LoRA when:
Fine-tuning 7B-70B models on consumer GPUs (RTX 4090, A100)
Need to train <1% parameters (6 MB adapters vs 14 GB full model)
Want fast iteration with multiple task-specific adapters
Deploying multiple fine-tuned variants from one base model
Use QLoRA (PEFT + quantization) when:
Fine-tuning 70B models on a single 24 GB GPU
Memory is the primary constraint
Can accept ~5% quality trade-off vs full fine-tuning
Use full fine-tuning instead when:
Training small models (<1B parameters)
Need maximum quality and have compute budget
Significant domain shift requires updating all weights
Prerequisites
Python 3.9+
CUDA-enabled GPU (recommended) or CPU (slow)
HuggingFace account with access to gated models (e.g., Llama 3.1 requires token)
Windows host is primary (PowerShell). Use pip commands directly in PowerShell; for long paths, ensure long-path support is enabled.
Installation
# Basic installation
pip install peft
# With quantization support (recommended)
pip install peft bitsandbytes
# Full stack
pip install peft transformers accelerate bitsandbytes datasets
Procedure
1. LoRA Fine-Tuning (Standard)
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import get_peft_model, LoraConfig, TaskType
from datasets import load_dataset
import torch
# Load base model
model_name = "meta-llama/Llama-3.1-8B"
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype="auto", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
# LoRA configuration
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=,
lora_alpha=,
lora_dropout=,
target_modules=[, , , ],
bias=
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
dataset = load_dataset(, split=)
():
text =
tokenizer(text, truncation=, max_length=, padding=)
tokenized = dataset.(tokenize, remove_columns=dataset.column_names)
training_args = TrainingArguments(
output_dir=,
num_train_epochs=,
per_device_train_batch_size=,
gradient_accumulation_steps=,
learning_rate=,
fp16=,
logging_steps=,
save_strategy=
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized,
data_collator= data: {: torch.stack([f[] f data]),
: torch.stack([f[] f data]),
: torch.stack([f[] f data])}
)
trainer.train()
model.save_pretrained()
from peft import PeftModel, AutoPeftModelForCausalLM
from transformers import AutoModelForCausalLM
# Option 1: Load with PeftModel
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.1-8B")
model = PeftModel.from_pretrained(base_model, "./lora-llama-adapter")
# Option 2: Load directly (recommended)
model = AutoPeftModelForCausalLM.from_pretrained(
"./lora-llama-adapter",
device_map="auto"
)
Merge adapter into base model
# Merge for deployment (no adapter overhead)
merged_model = model.merge_and_unload()
# Save merged model
merged_model.save_pretrained("./llama-merged")
tokenizer.save_pretrained("./llama-merged")
# Push to Hub
merged_model.push_to_hub("username/llama-finetuned")
Multi-adapter serving
from peft import PeftModel
# Load base with first adapter
model = AutoPeftModelForCausalLM.from_pretrained("./adapter-task1")
# Load additional adapters
model.load_adapter("./adapter-task2", adapter_name="task2")
model.load_adapter("./adapter-task3", adapter_name="task3")
# Switch between adapters at runtime
model.set_adapter("task1") # Use task1 adapter
output1 = model.generate(**inputs)
model.set_adapter("task2") # Switch to task2
output2 = model.generate(**inputs)
# Disable adapters (use base model)with model.disable_adapter():
base_output = model.generate(**inputs)
5. Alternative PEFT Methods
Method
Trainable %
Memory
Speed
Best For
LoRA
0.1-1%
Low
Fast
General fine-tuning
QLoRA
0.1-1%
Very Low
Medium
Memory-constrained
AdaLoRA
0.1-1%
Low
Medium
Automatic rank selection
IA3
0.01%
Minimal
Fastest
Few-shot adaptation
Prefix Tuning
0.1%
Low
Medium
Generation control
Prompt Tuning
0.001%
Minimal
Fast
Simple task adaptation
P-Tuning v2
0.1%
Low
Medium
NLU tasks
IA3 (minimal parameters)
from peft import IA3Config
ia3_config = IA3Config(
target_modules=["q_proj", "v_proj", "k_proj", "down_proj"],
feedforward_modules=["down_proj"]
)
model = get_peft_model(model, ia3_config)
# Trains only 0.01% of parameters!
Prefix Tuning
from peft import PrefixTuningConfig
prefix_config = PrefixTuningConfig(
task_type="CAUSAL_LM",
num_virtual_tokens=20, # Prepended tokens
prefix_projection=True# Use MLP projection
)
model = get_peft_model(model, prefix_config)
# axolotl config.yamladapter:loralora_r:16lora_alpha:32lora_dropout:0.05lora_target_modules:-q_proj-v_proj-k_proj-o_projlora_target_linear:true# Target all linear layers
With vLLM (inference)
from vllm import LLM
from vllm.lora.request import LoRARequest
# Load base model with LoRA support
llm = LLM(model="meta-llama/Llama-3.1-8B", enable_lora=True)
# Serve with adapter
outputs = llm.generate(
prompts,
lora_request=LoRARequest("adapter1", 1, "./lora-adapter")
)
# Verify adapter is activeprint(model.active_adapters) # Should show adapter name# Check trainable parameters
model.print_trainable_parameters()
# Ensure model in training mode
model.train()
Quality degradation
# Increase rank
LoraConfig(r=32, lora_alpha=64)
# Target more modules
target_modules = "all-linear"# Use more training data and epochs
TrainingArguments(num_train_epochs=5)
# Lower learning rate
TrainingArguments(learning_rate=1e-4)
Best practices
Start with r=8-16, increase if quality insufficient
Use alpha = 2 * rank as starting point
Target attention + MLP layers for best quality/efficiency
Enable gradient checkpointing for memory savings
Save adapters frequently (small files, easy rollback)
Evaluate on held-out data before merging
Use QLoRA for 70B+ models on consumer hardware
Verification
Verify installation and versions:
pip show peft transformers bitsandbytes
Expected output should show peft>=0.13.0, transformers>=4.45.0, bitsandbytes>=0.43.0.
merged_model = model.merge_and_unload()
# Should run without error and produce a standard transformers modelprint(type(merged_model)) # <class 'transformers.models.llama.modeling_llama.LlamaForCausalLM'>
References
Load these reference files when you need deeper detail:
references/advanced-usage.md — Load when exploring DoRA, LoftQ, rank stabilization, or custom PEFT modules.
references/troubleshooting.md — Load when encountering errors, debugging training issues, or optimizing performance.