adapters keeps its package metadata in setup.py and its tool config in pyproject.toml
A Unified Library for Parameter-Efficient and Modular Transfer Learning
At a glance
- What is it?
- adapters is an Apache 2.0 add-on library that folds parameter efficient fine tuning into HuggingFace Transformers, replacing the older adapter-transformers package. Its pyproject.toml declares no project table at all, its single dependency list mixes torch with pytest and seven exactly pinned Sphinx packages, and the documented test subsets do not match the declared markers.
- Who is it for?
- adapters is a reasonable choice if you have existing adapter checkpoints or want one interface across LoRA, prefix tuning, bottleneck variants and composition blocks without restructuring a Transformers setup, since a single call retrofits a model you already built. Two things to plan around.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 162 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
pyproject.toml configures the tools and setup.py configures the package
There are three build configuration files at the root and they divide the work oddly. setup.cfg is present as well. The pyproject.toml contains no project table and no build-system table; its entire content is a black configuration and a pytest marker list. Every piece of package metadata therefore lives in setup.py, which even says so in a comment: all setup logic is transferred and adapted from Transformers' setup.py, with an effort to follow their general layout wherever sensible. That inheritance is visible elsewhere too, in a Makefile target copied wholesale and in a vendored directory named hf_transformers sitting next to a .gitmodules file. The result is a library whose packaging is a fork of someone else's packaging rather than a native pyproject build.
One dependency list mixes torch, pytest and seven pinned Sphinx packages
setup.py holds one flat list, named with a leading underscore, and it spans every concern the project has. The runtime side is torch, torchvision, transformers at a compatible-release pin, accelerate with a floor, and Pillow. The test side is pytest capped below version 8, plus xdist, rich reporting, timeouts, parameterized, dill capped below 0.3.5, GitPython, and a timeout decorator. The documentation side is eight packages, and seven of them are pinned to an exact version: docutils at 0.16.0, markupsafe at 2.0.1, sphinx at 5.0.2, the theme at 2.0.0, sphinx-intl, sphinx-copybutton, sphinx-markdown-tables, and the opengraph extension. A documentation dependency pinned that hard is the one most likely to block a resolver long before a runtime one does.
The test target exports PYTHONPATH to shadow an installed copy
The Makefile does something worth copying. Before any target runs, it exports PYTHONPATH set to src, and the comment above explains why: to make sure the tests exercise the local checkout in src rather than a pre-installed copy of the same library from the environment. The comment also warns not to use quotes around the assignment, which is the detail that would otherwise silently break it. Two other lines in the same target are worth noting. The pytest invocation enables parallel workers across all cores with a loadfile distribution strategy, so tests are grouped by file rather than scattered, and after the run finishes the target prints the installed Transformers version, which reads as a deliberate diagnostic step rather than an accident.
The documented subset list and the declared markers do not match
The pytest configuration declares sixteen markers. Most name an adapter method: core, composition, heads, embeddings, class_conversion, prefix_tuning, prompt_tuning, reft, unipelt, compacter, bottleneck, and ia3 and lora. Three do not describe a method at all but a feature or an integration, flash_attn_test with a note on how to deselect it, bitsandbytes, and generate. The Makefile carries a comment listing the subsets you can pass to a dedicated target, and that list has thirteen entries. The two sets disagree in both directions. class_conversion is declared but missing from the documented list, and config_union appears in the documented list without being declared as a marker anywhere in the pyproject file.
black targets Python 3.8 while the readme requires 3.9
The stated support floor and the formatter configuration are one version apart. The readme says the library supports Python 3.9 and later, and PyTorch 2.0 and later. The black section of pyproject.toml sets a line length of 119 and target-version values of py38, py39, and py310. So the formatter is configured to emit syntax valid on a Python the project says it does not support, and py38 is listed first among the targets. Nothing breaks today because the emitted syntax is a subset, but the configuration is telling you something the support statement is not, and it is the kind of residue that arrives from copying a configuration file across repositories, which is the same habit the setup.py header comment admits to.
The style target rewrites files and the quality target only checks
Two targets run the same five tools with opposite intent, and both cover four directories: examples, tests, src, and utils. The quality target checks. It runs the formatter in check mode with preview enabled, the import sorter in check-only mode, two project-specific utility scripts with a check-only flag, and flake8 with no fix flag. The style target writes. Same formatter without the check, same sorter without the check-only, and it invokes the extra style checks target as a final step, which runs those two utility scripts for real. Both are listed as phony. The split is deliberate and readable, but it means the check target is the only one safe to wire into a continuous integration job, and it is also the one that will fail on a repository that has drifted from the formatter.
A disabled check is left in the Makefile with its explanation inline
One line of the quality target is commented out and kept. The disabled command is a script called check_inits, and the comment beside it says it is currently not working, quotes the reason in capital letters as this entire file needs an overhaul, and links to the exact line in a pinned Transformers revision that says so. The link points at version 4.52.4 while setup.py asks for a compatible release of 4.57.6, so even the citation points at an older upstream than the dependency allows. Leaving the line in place is the honest choice, since deleting it would lose the reason and the link. The cost is that the quality target looks one line longer than what it actually runs, which is exactly the kind of thing a reader has to notice rather than assume.
One adapter can hold a union of two configurations at once
The API has three entry points worth knowing. The retrofit path is a single call that adapts a setup you already have: build a model with the ordinary Transformers auto class, call init on it, then add a named adapter with a method name and train that adapter. The configuration path lets one adapter be a union, so a single named adapter can hold a prefix tuning configuration with a length of 20 and a parallel bottleneck configuration with a reduction factor of 4 together, which is not something a single method name expresses. It looks like this:
from adapters import ConfigUnion, PrefixTuningConfig, ParBnConfig, AutoAdapterModel
model = AutoAdapterModel.from_pretrained("microsoft/deberta-v3-base")
adapter_config = ConfigUnion(
PrefixTuningConfig(prefix_length=20),
ParBnConfig(reduction_factor=4),
)
model.add_adapter("my_adapter", config=adapter_config, set_active=True)And composition is scoped rather than permanent: adapters are loaded by name and then used together inside a setup context manager wrapping a parallel block, so the combination applies only for what happens inside the block.
Editorial conclusion
adapters is a reasonable choice if you have existing adapter checkpoints or want one interface across LoRA, prefix tuning, bottleneck variants and composition blocks without restructuring a Transformers setup, since a single call retrofits a model you already built. Two things to plan around. The dependency resolution is held back by documentation and test packages pinned to exact versions, including a docutils pin and a markupsafe pin, so an unrelated upgrade in your environment can fail on a library you never import. And if you run the test suite selectively, use the marker names declared in pyproject.toml rather than the subset list written in the Makefile, because the two disagree in both directions.
Frequently asked questions
What does the adapters library do?
It is an add-on library for HuggingFace Transformers that provides a unified interface for parameter efficient fine tuning and modular transfer learning, integrating more than ten adapter methods into more than twenty Transformer models. It supports quantized training variants, merging adapters through task arithmetic, and composing several adapters inside a scoped setup context.
What replaced adapter-transformers, and do old checkpoints still work?
The adapters library replaced the adapter-transformers package, and the readme states that all previously trained adapters are compatible with the new library. A separate transition guide is linked for moving across. The library itself is MIT free of that question because it is released under the Apache 2.0 licence.
How do I run only some of the adapters tests?
A dedicated Makefile target takes a subset variable and passes it to pytest as a marker expression. Its comment lists thirteen subsets, but the pytest configuration declares sixteen markers, and the two lists do not agree: class_conversion is declared but not listed, while config_union is listed but never declared as a marker. Use the declared marker names.
How do I make sure the tests use my local checkout?
The Makefile exports PYTHONPATH pointing at src before any target runs, with a comment stating the purpose is to test the local checkout rather than a pre-installed copy of the library. The comment also warns not to quote the assignment, since a quoted value would not do what the export intends.
What Python and PyTorch versions does adapters need?
The readme states Python 3.9 and later with PyTorch 2.0 and later. The formatter configuration in pyproject.toml nonetheless lists py38 among its target versions alongside py39 and py310, and its line length is set to 119. Package metadata is not declared in pyproject.toml at all, which carries only tool configuration.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/adapter-hub-adapters)