AI Fundamentals

PEFT Guide

Hub guide to parameter-efficient fine-tuning: LoRA, QLoRA, adapters, prefix/prompt tuning — when to use PEFT vs full fine-tuning vs RAG vs prompting.

55 min readIntermediateLast reviewed: 21 July 2026

Quick Summary

PEFT adapts large models by training small injected modules while freezing most base weights — and, in practice, usually means LoRA via the Hugging Face PEFT library.

One Analogy

Full fine-tuning rebuilds the entire engine; PEFT bolts on a small calibrated module you can swap, store, and merge.

Engineering Rule

Default to LoRA for open-weight SFT; use QLoRA when VRAM is the constraint; never use PEFT as a substitute for RAG on changing facts.

TL;DR

  • PEFT means training a small fraction of parameters (adapters, low-rank updates, soft prompts) while freezing the base transformer.
  • Hugging Face PEFT is the standard library that unifies configs, save/load, and merging across methods — most teams mean "LoRA via PEFT" in day-to-day speech.
  • LoRA is the default for quality, ecosystem support, and merge-to-zero-overhead serving. QLoRA is LoRA on a 4-bit frozen base for memory-constrained training.
  • Prefix / prompt tuning and classic bottleneck adapters still matter for extreme parameter frugality or research, but lose to LoRA for most production SFT.
  • Decision order: prompting → RAG/tools for knowledge → fine-tuning with PEFT for stable behavior → full FT only with measured need → RLHF/DPO for preference alignment.
  • Adapters are small artifacts (tens to hundreds of MB) that enable multi-tenant serving on one base checkpoint when you keep them unmerged.

Quick Decision Guide

If you want to... Read
See all adapter methods PEFT
Use low-rank adapters LoRA
Train with limited VRAM QLoRA
Do full fine-tuning Fine-tuning
Change model knowledge instead RAG
Understand the base architecture Transformers

Who this guide is for

  • Best for: AI engineers · ML engineers · applied research engineers
  • Difficulty: Intermediate
  • Estimated time: 55 min

Learning Path

TransformersLarge Language ModelsFine-tuningPEFTLoRAQLoRA

On this page

Why This Matters

Full fine-tuning of an 8B–70B open model duplicates optimizer state, checkpoints, and often entire serving stacks per task. PEFT cuts trainable parameters to roughly 0.01–1%, shrinks artifacts, reduces forgetting pressure on the frozen base, and lets one Llama or Mistral checkpoint host many task adapters.

If you use Hugging Face Transformers + TRL in 2026, you are almost certainly touching PEFT whenever you train LoRA or QLoRA. Treating PEFT as a decision hub — which method, when to prefer RAG, when to merge — prevents cargo-cult configs and wasted GPU hours. Deep dives: LoRA, QLoRA, parent fine-tuning.

Platform teams also feel PEFT in procurement. Instead of budgeting eight GPUs per experimental task, they budget shared base capacity plus overnight adapter jobs. That changes roadmap conversations: product managers can request a “tone adapter” without implying a new model SKU. The risk shifts from hardware scarcity to governance — who may train, what data is legal, and how adapters are reviewed before they touch customers.

Engineering Insight

Fine-tuning changes behavior; RAG changes knowledge. Reach for PEFT adapters only when prompting and retrieval leave a stable behavior gap.

The Problem PEFT Solves

Adaptation at LLM scale fails for operational reasons as often as for modeling reasons:

Pain Full fine-tuning symptom PEFT response
GPU memory Adam states ≈ 2× params in FP32-equivalent pressure Train tiny modules; optionally 4-bit base (QLoRA)
Storage / blast radius Full copy per task Adapter files + shared base
Multi-task serving N model deployments N adapters, one base (unmerged)
Catastrophic forgetting Large updates on small data Frozen base preserves general skills
Experiment velocity Slow iteration Small searchable hyperparameter space (rank, targets)

PEFT does not solve missing labels, bad eval hygiene, or the desire to store a live product catalog in weights. Those remain data and architecture problems.

How We Got Here

Diagram: Evolution of efficient adaptation

timeline
    title From full FT to PEFT libraries
    2018-2019 : Full fine-tune BERT/GPT
              : One checkpoint per task
    2019 : Houlsby adapters
         : Bottleneck modules
    2021 : Prefix / prompt tuning
         : Soft prompts
    2021 : LoRA
         : Low-rank ΔW = BA
    2023 : QLoRA
         : 4-bit base + LoRA
    2023-2026 : HF PEFT + TRL default
              : SFT, DPO, multi-adapter serve

Methods proliferated; Hugging Face PEFT became the integration layer production teams standardize on.

Adapter layers (Houlsby), prefix tuning (Li & Liang), prompt tuning (Lester et al.), LoRA (Hu et al.), IA³, and AdaLoRA each optimized a different corner of the parameter–quality–latency space. Bitsandbytes + QLoRA then made 65B/70B-class SFT feasible on single large GPUs. Preference optimization (RLHF, DPO) typically rides the same PEFT stack so alignment fits in memory.

What Is PEFT?

Parameter-efficient fine-tuning is the family of methods that adapt a pretrained model by updating a small parameter subset. PEFT (capitalized) also names Hugging Face’s library that implements those methods behind one API:

from peft import get_peft_model, LoraConfig

config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    task_type="CAUSAL_LM",
)
model = get_peft_model(base_model, config)
model.print_trainable_parameters()

Method map

Method What trains Inference note Deep dive
LoRA Low-rank matrices on linear layers Mergeable → zero extra latency LoRA
QLoRA Same as LoRA; base stored 4-bit while training Train-time memory win QLoRA
Bottleneck adapters Down/up projections inserted in blocks Extra depth; rarely merged simply This hub
Prefix tuning Virtual KV prefixes per layer Extra context / KV This hub
Prompt tuning Soft tokens in input embedding space Tiny; limited capacity This hub
IA³ Scaling vectors on activations Very few params Niche
AdaLoRA LoRA with adaptive rank budget More moving parts When rank unclear

How PEFT Works

Lifecycle is method-agnostic:

  1. Load base causal LM (BF16/FP16, or 4-bit for QLoRA).
  2. Build a method *Config.
  3. get_peft_model freezes base weights and injects trainable modules.
  4. Train with Transformers Trainer or TRL SFTTrainer / DPOTrainer.
  5. Save adapter-only artifacts (adapter_config.json + weights).
  6. Evaluate vs prompt baseline; merge or hot-swap for serve.

What “parameter-efficient” actually buys

Efficiency shows up in three budgets. Optimizer memory scales with trainable parameters, so shrinking that set is the largest training win. Checkpoint I/O shrinks from tens of gigabytes to megabytes, which speeds experiment tracking and multi-region copies. Serving fan-out improves when many tasks share one resident base — especially important for open transformers checkpoints hosted on your GPUs rather than per-task API fine-tunes.

Efficiency does not automatically mean better sample efficiency. A rank-8 LoRA can still overfit 50 near-duplicate tickets. Data diversity, loss masking, and held-out slices dominate outcomes once the method is “LoRA-shaped.” Likewise, PEFT does not reduce inference FLOPs unless you merge (removing extra matmuls) or distill later. Unmerged prefix tuning can increase decode cost via longer effective KV sequences.

Library boundaries you will hit

PEFT assumes a Transformers PreTrainedModel (or compatible) surface for module injection. Custom research architectures need manual target_modules strings that match named_modules(). Some serving engines accept PEFT adapters natively; others only accept merged safetensors. Plan the export path before you invest in a training run: if production vLLM build lacks multi-LoRA, your “flexible adapters” story collapses to merge-or-nothing at release time.

my_adapter/
├── adapter_config.json
└── adapter_model.safetensors   # tens–hundreds of MB, not full model
from peft import PeftModel

base = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")
model = PeftModel.from_pretrained(base, "./my_adapter")
merged = model.merge_and_unload()  # LoRA path

LoRA adapter architecture

Source: Microsoft Research — LoRA paper

Architecture

Diagram: PEFT in the training/serving stack

flowchart TB
  subgraph train [Training]
    B[Base LLM weights]
    C[PEFT config]
    A[Trainable adapters]
    T[TRL / Trainer]
    B --> C --> A --> T
  end
  subgraph artifacts [Artifacts]
    AD[Adapter checkpoint]
    CF[adapter_config.json]
  end
  subgraph serve [Serving]
    B2[Shared base]
    M[Merged weights]
    X[Multi-adapter router]
  end
  T --> AD
  T --> CF
  AD --> M
  AD --> X
  B2 --> M
  B2 --> X

One base revision pins many adapters; merging collapses to a single dense checkpoint for simple deploys.

Layer Component Role
Config LoraConfig, PrefixTuningConfig, … Method + hyperparameters
Wrapper PeftModel Freeze, inject, save/load
Quant bitsandbytes + prepare_model_for_kbit_training QLoRA path
Train TRL / Transformers SFT, DPO, reward loops
Serve vLLM / TGI / LoRAX / S-LoRA Merged or multi-adapter

Step-by-Step Flow

Diagram: Choosing an adaptation path

flowchart TD
  S[Behavior or knowledge gap?] -->|Knowledge / fresh facts| R[RAG or tools]
  S -->|Stable behavior| P[Strong prompt baseline]
  P -->|Passes gates| Done[Ship prompt]
  P -->|Fails gates| F{GPU memory?}
  F -->|Comfortable| L[LoRA BF16/FP16]
  F -->|Tight| Q[QLoRA 4-bit]
  L --> E[Eval vs baseline]
  Q --> E
  E -->|PEFT ceiling| Full[Consider full FT]
  E -->|OK| Dep[Merge or multi-adapter deploy]

PEFT sits after prompting and beside RAG — not as a knowledge database.

  1. Confirm the gap is behavioral (fine-tuning boundaries).
  2. Freeze an eval set and prompt baseline.
  3. Pick LoRA unless VRAM forces QLoRA.
  4. Set target_modules, rank, alpha; print trainable %.
  5. Train 1–3 epochs; early-stop on eval.
  6. Save adapter; record base revision + tokenizer + chat template.
  7. Compare merged vs unmerged numerically on smoke prompts.
  8. Canary deploy; keep rollback adapter/base pair.

Real Production Example

Multi-tenant support platform: one Llama-3.1-8B-Instruct base, three LoRA adapters (triage classifier, tone-constrained reply, JSON extractor). Prefix tuning was trialed for summarization storage size; LoRA won on quality.

from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model, PeftModel
from trl import SFTTrainer
import torch

MODEL_ID = "meta-llama/Llama-3.1-8B-Instruct"

base = AutoModelForCausalLM.from_pretrained(
    MODEL_ID, torch_dtype=torch.bfloat16, device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)

def train_lora(name: str, dataset, r: int = 16):
    model = get_peft_model(
        base,
        LoraConfig(
            r=r,
            lora_alpha=2 * r,
            target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
            lora_dropout=0.05,
            task_type="CAUSAL_LM",
        ),
    )
    args = TrainingArguments(
        output_dir=f"./adapters/{name}",
        num_train_epochs=2,
        per_device_train_batch_size=4,
        learning_rate=2e-4,
        bf16=True,
        eval_strategy="epoch",
    )
    SFTTrainer(
        model=model,
        args=args,
        train_dataset=dataset["train"],
        eval_dataset=dataset["test"],
        processing_class=tokenizer,
    ).train()
    model.save_pretrained(f"./adapters/{name}")

# Serving sketch: switch adapters on one base
runtime = PeftModel.from_pretrained(base, "./adapters/triage", adapter_name="triage")
runtime.load_adapter("./adapters/reply", adapter_name="reply")
runtime.set_adapter("triage")
Method (same triage task) Accuracy Trainable Adapter size Train time
LoRA r=16 96.8% ~42M ~170 MB 2.1 h
Prefix (20 tokens) 94.2% ~1.6M ~6 MB 0.8 h
Prompt tuning 91.5% ~0.16M ~0.6 MB 0.3 h
Full FT 97.1% ~8B ~16 GB 8.4 h

LoRA recovered ~99.7% of full-FT accuracy at a fraction of cost; production standardized on LoRA + optional QLoRA for 70B experiments.

Design Decisions

Decision Prefer When
Method LoRA Default SFT / most DPO
Memory mode QLoRA Single-GPU 34B–70B class
Deploy shape Merge One adapter, max simplicity
Deploy shape Unmerged multi-adapter Tenant/task routing
Rank r=16 Start; sweep 8/32 with data size
Targets Attention projections Classification; add MLP for generation
Alignment PEFT + DPO/RLHF Preference data available

When to use each method

Method Use when Avoid when
LoRA Almost always for open SFT You proved PEFT ceiling with ablations
QLoRA VRAM bound Ample multi-GPU and you need max step speed
Prefix tuning Huge adapter counts, tiny storage You need merge-only serving
Prompt tuning Ultra-fast probes Complex generation behavior
AdaLoRA Rank allocation unclear after sweeps Simple r=16 already good
Full FT Large data + measured PEFT gap First experiment

Comparisons

Approach Changes Best for Update story
Prompting Context only Fast iteration Edit text
RAG / tools Retrieved evidence Fresh/private facts Index / API
PEFT (LoRA) Small weights Stable style/format/tools Retrain adapter
Full FT All weights Large shift / small models Full redeploy
RLHF/DPO Policy via prefs Helpfulness/safety tone Preference pipeline
PEFT method Trainable % (order) Mergeable Typical production role
LoRA 0.1–1% Yes Default
QLoRA LoRA-sized Adapter yes; 4-bit is train-time Memory-limited train
Prefix ≪1% No Niche multi-adapter
Prompt tuning ≪0.1% No Probes
Bottleneck adapters 0.5–8% Awkward Legacy / research

Common Mistakes

  1. Using PEFT to "upload the wiki." Use RAG; adapters memorize poorly and stale.
  2. Skipping print_trainable_parameters(). 100% trainable means the wrap failed.
  3. Saving full checkpoints by accident. Verify adapter directory sizes.
  4. Mismatched base revision. Llama 3.1 adapters on a different 3.0/4 checkpoint → garbage.
  5. Prompt tuning for deep behavior change. Capacity is too small.
  6. Ignoring inference overhead of non-LoRA methods. Prefix tokens tax KV cache forever.
  7. No prompt baseline. You cannot claim PEFT helped.
  8. Mixing methods on one model casually. One method per adapter unless you know the composition semantics.
  9. Forgetting task_type="CAUSAL_LM". Silent misconfig risk.
  10. Treating QLoRA as faster. It is smaller VRAM, often slower steps.

Where It Breaks Down

PEFT approximates full updates. If the base model lacks language coverage or reasoning skill, adapters cannot invent it. Non-Transformers ecosystems need custom injection. Composing many LoRAs can interfere — test mixtures. Very unusual architectures may need manual target_modules. Preference optimization still needs good preference data; PEFT only shrinks the optimizer footprint.

Another failure mode is process debt. Because adapters are cheap to train, organizations spawn dozens without owners. Six months later nobody knows which adapter is canonical for “billing reply,” eval sets disagree, and a merge conflict becomes a production incident. Cheap training without lifecycle policy recreates the same chaos full fine-tuning caused with heavier files.

Finally, PEFT cannot enforce deterministic contracts. Schema validation, authorization checks, and citation verification remain application responsibilities. An adapter that “usually” emits valid JSON still needs constrained decoding or parsers for hard guarantees — see structured outputs and guardrails.

When NOT to Use PEFT

Do not reach for PEFT when:

  • a prompt (and maybe few-shot) already clears quality/latency gates;
  • facts must be attributable and fresh — use RAG/tools;
  • you have no held-out eval or data rights;
  • the serving stack cannot load adapters and you refuse to merge/evaluate;
  • hardware lacks CUDA for QLoRA and even LoRA will not fit — pick a smaller base first;
  • the organization cannot version adapters or roll them back safely.

Prefer prompting → retrieval → PEFT → full FT, with fine-tuning as the behavioral layer. A useful heuristic: if you cannot name the metric that would make you delete the adapter, you are not ready to train it.

Running in Production

Dimension Practice
Versioning Bundle base revision, tokenizer, chat template, PEFT version, adapter hash
Routing Explicit adapter ID in traces; no silent fallback
Latency Merged LoRA ≈ base; cold adapter load costs hundreds of ms
Eval Per-adapter golden sets + cross-talk tests when switching
Security Adapters memorize; scan training data; isolate tenants
Rollback Keep prior adapter + config immutable
Alignment Run DPO/RLHF on PEFT when prefs exist — same ops model

Important

Default production path: LoRA → evaluate → merge → serve. Use dynamic multi-adapter only when product requirements justify the operational complexity.

Operating multi-adapter fleets

Once more than one adapter is live, treat the base model like a shared library and each adapter like a deployable microservice binary. Require a change ticket that lists dataset hash, training config, eval report, and intended traffic percentage. Canary by adapter ID — not by “the new model” — because several adapters may share one process.

Watch for silent cross-talk: a request routed to adapter A after adapter B was active should not retain B’s bias. Engines differ in whether set_adapter fully isolates state; write an integration test that alternates adapters on fixed prompts and asserts expected outputs. For high QPS, prefer engines with native multi-LoRA batching rather than loading adapters per request on the critical path.

Storage hygiene matters. Adapters are small enough that teams accidentally keep dozens of undated folders. Enforce naming task__baseRevision__r16__yyyyMMdd and garbage-collect unreferenced artifacts after the rollback window. Encrypt adapter stores if training data was sensitive; a 100MB file can still contain memorized secrets.

PEFT inside preference and tool-use pipelines

Supervised PEFT is only the first adapter you may ship. Preference optimization with DPO or RLHF often continues from an SFT adapter (or trains a new LoRA on top of the same base). Keep the lineage explicit: SFT adapter → preference adapter → optional merge. Tool-calling conventions are a frequent PEFT target: if your agent must emit a strict function-call grammar, adapters can reduce retries, but structured outputs and server-side validation remain mandatory.

Cost accounting should separate training GPU hours, adapter storage, and incremental inference cost. Merged LoRA usually has negligible inference premium versus the base; unmerged multi-adapter serving may trade a few percent throughput for operational flexibility. Revisit that trade whenever traffic concentrates on a single adapter — merging that winner can reclaim capacity.

Continue Learning

Production Checklist

  • Adapter strategy selected (LoRA / QLoRA / other PEFT method)
  • LoRA vs QLoRA evaluated against VRAM and quality gates
  • Prompt / retrieval baseline frozen before adapter training
  • Base revision, tokenizer, and PEFT library versions pinned
  • Adapter artifacts versioned with hash and training config
  • Explicit adapter ID required in traces (no silent fallback)
  • Per-adapter golden-set evaluation completed
  • Cross-talk test passed when switching adapters
  • Rollback prior adapter retained and immutable
  • Multi-adapter naming and garbage-collection policy enforced
  • Merge-then-serve vs dynamic multi-LoRA decision documented

Prerequisites

Core Concepts

Implementation

Optimization

Advanced Topics

  • RLHF · DPO — preference training with PEFT

Diagram: PEFT family graph

flowchart LR
    FT[Fine-tuning] --> PEFT[PEFT hub]
    PEFT --> LoRA[LoRA]
    PEFT --> QLoRA[QLoRA]
    LoRA --> QLoRA
    PEFT --> RLHF[RLHF]
    PEFT --> DPO[DPO]
    FT --> LLM[LLMs]
    LLM --> TR[Transformers]

Interview Questions

PEFT vs LoRA — are they the same?

PEFT is the family (and HF library). LoRA is the dominant method inside it. Colloquially people say PEFT to mean LoRA.

When is QLoRA preferable to LoRA?

When frozen base weights in BF16/FP16 do not fit, but you can accept dequant overhead and bitsandbytes/CUDA constraints. Quality is usually close; step time often worse.

Why merge LoRA adapters?

Merged weights remove extra matmuls and simplify engines that lack multi-adapter routing. Re-evaluate after merge and after any post-quantization.

How do PEFT and RAG divide responsibility?

RAG supplies evidence at request time. PEFT changes parametric behavior (format, tone, tool habits). Using PEFT for changing facts creates stale, uncitable memory.

What must be pinned for reproducible loads?

Base model revision, tokenizer/chat template, adapter config (rank, alpha, targets), and library versions.

Can DPO use PEFT?

Yes — wrapping the policy with LoRA is standard to fit preference optimization in memory.

Key Takeaways

  • PEFT freezes the base LLM and trains small modules; HF PEFT is the integration standard.
  • Start with LoRA; use QLoRA for VRAM; treat other methods as special cases.
  • Decide against prompting and RAG before training.
  • Operate adapters as versioned artifacts with eval gates and rollback.
  • Link the family: fine-tuningPEFTLoRA / QLoRADPO / RLHF.
  • If an adapter cannot beat a strong prompt baseline on a frozen eval set, delete it — PEFT is optional complexity, not a badge of seriousness.

FAQs

Which PEFT method should I use in 2026?

LoRA for nearly all open-weight SFT. QLoRA when the base model otherwise OOMs. Everything else needs a specific constraint.

How small are adapters?

Often 10–500 MB depending on rank, targets, and model width — versus tens of GB for full copies.

Does PEFT work with Unsloth / Axolotl / LLaMA-Factory?

Yes; most wrap the same LoRA/QLoRA ideas and emit PEFT-compatible adapters. Still evaluate the exported artifact.

Can I serve multiple adapters in vLLM?

Support evolves by version — check current multi-LoRA docs. LoRAX/S-LoRA exist specifically for multi-adapter batching. Merging remains the simplest path.

Is AdaLoRA worth it?

Only after fixed-rank LoRA sweeps fail. Complexity cost is real.

Does PEFT reduce hallucinations?

Not reliably. It can teach abstention format, but grounding still needs retrieval/tools (hallucinations).

References

Further Reading

Next Topics

Learning Path

Continue Learning

Related Guides

Related Tools

ToolCategoryPurposeWebsiteBest For
Hugging Face Transformers
Python SDK
frameworksLibrary for using pretrained transformers in Python and beyond.huggingface.coModel fine-tuning