Skip to content

Install PEFT 0.21.0: Parameter Efficient Fine Tuning

Deploy Hugging Face PEFT 0.21.0 the right way: Python 3.10+, pinned pip install, smoke test, real error fixes, upgrade and uninstall steps.

7 min readIntermediate

The #1 mistake when you deploy parameter efficient fine tuning

Most people run pip install peft in whatever shell is open, then train from a Jupyter kernel, ComfyUI portable embed, or SLURM job that points at a different Python. The wheel is fine. The interpreter is not. You get ModuleNotFoundError: No module named 'peft' or a half-upgraded stack where transformers expects a newer PEFT than the one you actually import.

PEFT 0.21.0 (stable as of 15 Sep 2026 on PyPI / GitHub tags) is Hugging Face’s library for parameter efficient fine tuning – LoRA and a pile of variants – on top of Transformers. This page is only how to install, verify, and remove that library. Not another full LoRA training walkthrough.

System requirements for PEFT 0.21.0

Think of the peft wheel as a hitch. Tiny. The truck is still PyTorch plus whatever base model you load later – that’s where GPU RAM and disk actually go.

Item Minimum Recommended
OS Any (PyPI: OS Independent) Linux x86_64 for CUDA training
Python ≥ 3.10.0 (hard requirement on 0.21.0) 3.11 or 3.12
CPU / RAM Enough to import torch + a tiny smoke model Sized for your base model / offload choice – not for peft itself
GPU None for install/import smoke tests CUDA GPU when you actually train large models (QLoRA memory follows the base model + bitsandbytes, not the peft package)
Disk peft on PyPI is ~1MB source; deps add more Tens of GB free once model weights/cache enter the picture
Core deps (as of peft 0.21.0 setup.py) torch≥1.13, transformers, accelerate≥0.21, safetensors, huggingface_hub≥0.25, numpy≥1.17, packaging≥20.0, psutil, pyyaml, tqdm Match the CUDA build of torch to your driver

bitsandbytes is not a hard dependency – install it only when you want 4/8-bit QLoRA.

Doc drift to watch: the install page still talks about testing on Python 3.9+, but published 0.21.0 metadata (Requires-Python / python_requires) is ≥3.10.0. Trust the package, not the lagging sentence.

Why do install docs lag package metadata so often? Different files, different release chores – and your pip resolver only reads the wheel. If you’ve ever “followed the docs” into a rejected install, this is that gap in writing.

Official download sources

Use only these:

No separate PEFT-team binary installer or official Docker image – you install into a Python env. LoRA’s original paper, if you want the method not the pip package: arXiv:2106.09685.

Install PEFT 0.21.0 step by step

Create a clean env first. That habit alone kills most “PEFT won’t import” tickets.

# Linux/macOS - Python 3.10+
python3.11 -m venv .venv-peft
source .venv-peft/bin/activate
python -m pip install -U pip setuptools wheel

# Pin the release you actually want
python -m pip install "peft==0.21.0"

# Optional stack for training later
python -m pip install -U "transformers" "accelerate>=0.21.0" "datasets"
# QLoRA only:
# python -m pip install bitsandbytes

The catch on Windows Arm64 + NVIDIA (docs call out RTX Spark-class boxes): default PyPI torch wheels are the wrong build. Pull torch from NVIDIA’s index before peft.

nvidia-smi
pip install torch --index-url https://pypi.nvidia.com/nvtorch_oot_nightly
pip install "peft==0.21.0"

Need unreleased fixes?

# Bleeding edge main
pip install git+https://github.com/huggingface/peft

# Editable checkout (contributors)
git clone https://github.com/huggingface/peft
cd peft
pip install -e ".[test]"

Pro tip: After install, run which python and python -c "import sys; print(sys.executable)" inside the same session you’ll train in. If those paths disagree with your notebook kernel, fix the kernel – don’t reinstall peft three times.

First-time configuration (minimum viable smoke test)

PEFT has no global config file and no daemon. “Configured” means: import works, and you can wrap a tiny model without CUDA.

import peft
from peft import LoraConfig, get_peft_model, TaskType
from transformers import AutoModelForCausalLM

print("peft", peft.__version__) # expect 0.21.0

# CPU-friendly smoke model - swap later for your real base
model = AutoModelForCausalLM.from_pretrained("sshleifer/tiny-gpt2")
cfg = LoraConfig(
 r=4,
 lora_alpha=8,
 task_type=TaskType.CAUSAL_LM,
 target_modules=["c_attn"], # matches GPT-2 naming
)
peft_model = get_peft_model(model, cfg)
peft_model.print_trainable_parameters()

Non-zero trainable count ⇒ injection worked. Partial target_modules mismatches can stay silent here – PEFT hard-fails only when zero names match (see FAQ if training “works” but weights barely move).

Verify the install works

python -c "import peft, transformers, accelerate, torch; 
print(peft.__version__, transformers.__version__, accelerate.__version__, torch.__version__)"

First number should be 0.21.0. Turns out a lot of “PEFT is broken” threads are version skew: peft / transformers / accelerate / torch drifted apart after a partial upgrade. Official troubleshooting treats that quartet as one stack – bump them together when examples fail right after an install that looked clean.

Common install errors and fixes

1. ModuleNotFoundError: No module named 'peft'
Same failure mode as the opening: env A installed, env B runs (ComfyUI portable Python, SLURM vs login node, notebook kernel orphaned from the venv). Activate the venv → python -m pip install peft==0.21.0 → point the job/kernel at that executable. Don’t keep spraying pip install into random shells.

2. Install rejected on Python 3.9
0.21.0 declares Requires-Python: >=3.10.0 on PyPI / in setup.py. Old blog posts still say 3.9. Move the project.

3. ImportError: cannot import name 'LoraConfig'
Casing is LoraConfig, not Loraconfig. Name correct but missing? Shadowed or broken install – python -c "import peft; print(peft.__file__)", then reinstall into that path.

4. ValueError: Attempting to unscale FP16 gradients after a “successful” install
Install wasn’t the bug. Per the PEFT troubleshooting guide, this shows up when the base model sat in fp16 while Trainer AMP expected trainable weights in fp32. Fix the dtypes / AMP setup on the training path (adapter params need to be unscale-safe), not by reinstalling the wheel.

Upgrade, migrate, uninstall

# Upgrade to latest on PyPI
python -m pip install -U peft

# Stay on the known-good pin
python -m pip install "peft==0.21.0"

# Uninstall cleanly
python -m pip uninstall peft -y

# Full env teardown if the stack is a mess
deactivate
rm -rf .venv-peft

Older adapter folders usually load on 0.21.0. When adapter_config.json carries a field your installed peft doesn’t know, the loader errors – upgrade peft (or install from git) before you start deleting keys by hand; stripping unknown fields can change behavior. Recent Transformers PEFT integration docs also put a floor around peft ≥ 0.20.0 for some native adapter paths (as of those docs), so ancient pins fight you twice.

0.21.0 is mostly additive – ShadowPEFT, KaSA, Super-Tuning, and friends. Classic LoRA only? Pin 0.21.0 anyway. It’s the boring pin that still works today.

Next: fresh 3.10+ venv → pip install peft==0.21.0 → tiny-gpt2 smoke test. Trainable% > 0? Wire the real base model. Library’s deployed.

FAQ

Do I need a GPU to install PEFT 0.21.0?

No. The wheel installs and imports on CPU-only machines. GPU matters when you load a large base model for training or inference – not for pip install.

Should I install peft from PyPI or from GitHub main?

Production and teaching boxes: pin peft==0.21.0 from PyPI. Reach for pip install git+https://github.com/huggingface/peft only when you need a fix or method that landed after the tag. Example: you’re blocked on a double-scaling bug already fixed on main but you’re still on an older wheel – git is justified. Otherwise main moves fast and can break copy-pasted examples until the next release.

Why does training “work” but the model barely changes after a correct install?

Install succeeded; adapter targeting didn’t. People assume PEFT validates every name in target_modules. It doesn’t. Zero matches → error. Some matches → the rest are skipped with no warning, most of the model stays frozen, loss still moves a little, and you burn an epoch. Right after get_peft_model, call print_trainable_parameters(). Trainable count absurdly small for the architecture? Print module names and fix target_modules (or architecture defaults / all-linear where supported) before another full run. That’s a training gotcha, not a missing pip package – details live in the troubleshooting guide on target modules.