Problem
load_adapters() only supports the mlx-lm native format. PEFT/Unsloth adapters fail with:
AttributeError: 'SimpleNamespace' object has no attribute 'num_layers'
Root Cause
Two incompatibilities:
- Config keys differ (
peft_type / r / lora_alpha vs fine_tune_type / num_layers / lora_parameters)
- Weight file name and key format differ;
lora_A / lora_B require transposing
|
PEFT format |
mlx-lm format |
| Config |
adapter_config.json with peft_type |
adapter_config.json with fine_tune_type |
| Weight file |
adapter_model.safetensors |
adapters.safetensors |
| Key pattern |
base_model.model.model.layers.0.…lora_A.weight |
model.layers.0.…lora_a |
| lora_A shape |
(rank, in_features) |
(in_features, rank) |
Proposed Solution
Auto-detect PEFT format via peft_type key in adapter_config.json, then remap config and weights on the fly inside load_adapters(). No API change — existing mlx-lm adapters are completely unaffected.
This was also noted in ml-explore/mlx#1910, where Awni mentioned it is not yet supported but should be "fairly easy to implement".
Tested With
- Base:
LiquidAI/LFM2.5-1.2B-Base
- Adapter:
YUGOROU/TeenEmo-LFM2.5-1.2B-DPO (Unsloth DPO, rank=32)
- All 184 weight keys correctly remapped; LoRA delta numerically verified (
max|PEFT_delta.T − MLX_delta| = 0.0)
- Model generates expected Japanese counseling output with
<think> blocks
Note: Generation behavior may differ slightly from GGUF inference due to quantization differences between backends, which is expected.
Scope
peft_type: "LORA" only. DoRA/AdaLoRA as future work if useful.
I'd Like to Open a PR
Implementation is ready:
mlx_lm/tuner/utils.py: _is_peft_config(), _convert_peft_config(), _remap_peft_weights(), updated load_adapters()
tests/test_tuner_utils.py: 23 new test cases (25 total, all passing)
mlx_lm/LORA.md: usage docs for PEFT adapters
Happy to open a PR if this direction is acceptable.
Problem
load_adapters()only supports the mlx-lm native format. PEFT/Unsloth adapters fail with:Root Cause
Two incompatibilities:
peft_type/r/lora_alphavsfine_tune_type/num_layers/lora_parameters)lora_A/lora_Brequire transposingadapter_config.jsonwithpeft_typeadapter_config.jsonwithfine_tune_typeadapter_model.safetensorsadapters.safetensorsbase_model.model.model.layers.0.…lora_A.weightmodel.layers.0.…lora_a(rank, in_features)(in_features, rank)Proposed Solution
Auto-detect PEFT format via
peft_typekey inadapter_config.json, then remap config and weights on the fly insideload_adapters(). No API change — existing mlx-lm adapters are completely unaffected.This was also noted in ml-explore/mlx#1910, where Awni mentioned it is not yet supported but should be "fairly easy to implement".
Tested With
LiquidAI/LFM2.5-1.2B-BaseYUGOROU/TeenEmo-LFM2.5-1.2B-DPO(Unsloth DPO, rank=32)max|PEFT_delta.T − MLX_delta| = 0.0)<think>blocksNote: Generation behavior may differ slightly from GGUF inference due to quantization differences between backends, which is expected.
Scope
peft_type: "LORA"only. DoRA/AdaLoRA as future work if useful.I'd Like to Open a PR
Implementation is ready:
mlx_lm/tuner/utils.py:_is_peft_config(),_convert_peft_config(),_remap_peft_weights(), updatedload_adapters()tests/test_tuner_utils.py: 23 new test cases (25 total, all passing)mlx_lm/LORA.md: usage docs for PEFT adaptersHappy to open a PR if this direction is acceptable.