ZAdapter
TPU-native bottleneck FFN adapter for parameter-efficient fine-tuning.
Unlike LoRA (parallel low-rank matrices merged into existing weights), ZAdapter injects a small bottleneck feed-forward block serially after attention and MLP in each transformer layer. This keeps the computation graph static — no merge/unmerge step, no dynamic branching — which plays well with XLA compilation on TPU.
input -> down_proj [d_model -> r] -> activation -> up_proj [r -> d_model] -> output
output = input + adapter(input)
Install
# JAX/Flax native (recommended for TPU)
pip install zadapter
# With zenbit NF4/Pallas integration
pip install zadapter[pallas]
# With PyTorch backward compatibility
pip install zadapter[pytorch]
# Everything
pip install zadapter[all]
Quick Start (JAX/Flax)
import jax
import jax.numpy as jnp
import flax.linen as nn
from zadapter import ZAdapter, AFAScheduleConfig
# Inside your Flax module
class MyBlock(nn.Module):
d_model: int = 4096
r: int = 64
@nn.compact
def __call__(self, x, step: int = 0):
# ... attention, MLP, etc ...
# Inject ZAdapter with Activation Function Annealing (AFA)
schedule = AFAScheduleConfig(total_steps=10000, anneal_fraction=0.3)
beta = schedule.beta(step)
x = ZAdapter(d_model=self.d_model, r=self.r)(x, beta=beta)
return x
Activation Function Annealing (AFA)
ZAdapter v0.2 introduces AFA — adapted from Li et al., "AFA-LoRA: Enabling Non-Linear Adaptations in LoRA with Activation Function Annealing" (2026).
- Training: Uses non-linear activation (GELU/ReLU/SiLU) for expressiveness
- Annealing: Smoothly transitions to identity function over first ~30% of training
- Post-training: Adapter collapses to a pure linear map → mergeable into base weight!
from zadapter import merge_into_weight
# After training (beta fully annealed to 0)
merged_weight = merge_into_weight(base_weight, adapter_params)
Shard-aware merge: Works on already-sharded weights (tensor-parallel) — no need to gather 900B+ models onto a single device.
Tensor Parallel (Large Models)
For models too large for a single TPU core (~30B+ params even with NF4):
from zadapter import setup_mesh, ColumnParallelDense, RowParallelDense, TPConfig
mesh = setup_mesh(TPConfig(num_shards=8))
class ShardedBlock(nn.Module):
@nn.compact
def __call__(self, x, beta=0.0):
x = ColumnParallelDense(features=4*d_model, mesh=mesh)(x)
x = ZAdapter(d_model=4*d_model, r=64)(x, beta=beta)
x = RowParallelDense(features=d_model, mesh=mesh)(x)
return x
ZAdapter params are replicated (not sharded) across the mesh — negligible memory cost, zero cross-device communication overhead for something that small.
Integration with zenbit (NF4 Quantization)
from zenbit.pallas_nf4.flax_layer import NF4DenseFused
from zadapter import ZAdapter
# NF4-quantized frozen base + trainable ZAdapter on top
h = NF4DenseFused(features=d_model)(x, quantized_weight)
h = ZAdapter(d_model=d_model, r=64)(h, beta=1.0)
See tests/test_zadapter_zenbit_integration.py for full integration tests.
Why ZAdapter over LoRA
| LoRA | ZAdapter v0.1 (PyTorch) | ZAdapter v0.2 (JAX) | |
|---|---|---|---|
| Injection | Parallel to weight | Serial FFN block | Serial FFN block |
| Mergeable | Yes (after training) | No | Yes (via AFA) |
| Graph | Dynamic (merge/unmerge) | Static, XLA-friendly | Static, XLA-friendly |
| Trainable params | ~0.1-1% | ~0.5-3% | ~0.5-3% |
| Backend | PyTorch | PyTorch | JAX/Flax/Pallas |
| Tensor Parallel | Manual | — | Native (Megatron-style) |
| Quantization | bitsandbytes | — | zenbit NF4 (Pallas kernel) |
Legacy PyTorch API (v0.1)
The PyTorch version is still available for backward compatibility:
from zadapter.pytorch import inject_adapter, get_trainable_params
Install with: pip install zadapter[pytorch]
Companion Library
For TPU sharding, data-parallel training loops, and NF4/int8 quantization: zenbit
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zadapter-0.2.0.tar.gz.
File metadata
- Download URL: zadapter-0.2.0.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce4192135ea3bb0d6fc62bbf4b23a89137f537531c0233608914cc1acf34736b
|
|
| MD5 |
f407c6170065cd201b772ec13a92bdb2
|
|
| BLAKE2b-256 |
89a9225775c41b1c785c3e2ad2fef7d05c1140ce9c2134c458a670f7e9c92680
|
File details
Details for the file zadapter-0.2.0-py3-none-any.whl.
File metadata
- Download URL: zadapter-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7e827d0550b865dc6c089943334d5a7cb33e6813bd6a237a224c2835593c371
|
|
| MD5 |
9cd2bfdc5b2792bf216275ae665ab5dd
|
|
| BLAKE2b-256 |
392b772d021ddbb41012b465e1f8acddfe323d26ae9eda64c0b55775098bf1f6
|