[BUG] Unsloth booster fails on composite VLM LoRA: "No layers to finetune?" due to target_modules format mismatch
Reminder
- I have read the above rules and searched the existing issues.
System Info
Environment
- LLaMA-Factory: 0.9.6.dev0
- Unsloth: 2026.x
- Model: Qwen/Qwen3.5-4B
- Stage: SFT, LoRA
- Booster: unsloth
- GPU: NVIDIA A100 40GB
- OS: Linux
Reproduction
Describe the bug
When Booster = unsloth is enabled for LoRA SFT on a composite / vision-language model (e.g. Qwen/Qwen3.5-4B, model_type=qwen3_5), training crashes during LoRA adapter setup with:
The same training config works when Booster = auto (standard PEFT path).
To Reproduce
Steps to reproduce the behavior:
- Install LLaMA-Factory with Unsloth support (
use_unsloth/ Boosterunsloth). - Configure SFT with a composite VLM:
- Model:
Qwen/Qwen3.5-4B - Template:
qwen3_5_nothink - Finetuning type: LoRA (
lora_target=all) - Freeze vision tower:
true - Booster:
unsloth
- Model:
- Use any valid SFT dataset (text-only is sufficient).
- Start training via CLI or WebUI.
Training fails in get_unsloth_peft_model() → FastLanguageModel.get_peft_model().
Expected behavior
Unsloth booster should attach LoRA adapters to the intended language-model linear layers on composite VLMs, consistent with the standard PEFT path (with vision/projector frozen when configured).
Actual behavior
LoRA setup fails because LlamaFactory passes full module paths as target_modules, while Unsloth expects leaf module names.
Root cause
There is a format mismatch between two LlamaFactory code paths:
adapter.pybuilds LoRA targets, then callspatch_target_modules()inmodel_utils/visual.py.- For models in
COMPOSITE_MODELS(e.g.qwen3_5,qwen2_vl,llava, …),patch_target_modules()expands short targets likeout_projinto full paths:model.language_model.layers.0.linear_attn.out_proj
This is correct for standard HuggingFace PEFT.
- When
use_unsloth=True, those expanded paths are passed to:
FastLanguageModel.get_peft_model(target_modules=...)- Unsloth’s get_peft_regex() treats target_modules as leaf names and builds regexes that match module paths ending in those names. Passing a full path as the “leaf” matches nothing → 0 trainable layers → crash.
Proposed fix
In the Unsloth integration path only, convert expanded VLM target_modules back to unique leaf names before calling FastLanguageModel.get_peft_model().
Suggested change in model_utils/unsloth.py:
def _coerce_unsloth_target_modules(model, target_modules: list[str]) -> list[str]:
"""Unsloth expects LoRA leaf names; VLMs get full paths from patch_target_modules."""
model_type = getattr(model.config, "model_type", None)
if model_type not in COMPOSITE_MODELS:
return target_modules
if not target_modules or all("." not in name for name in target_modules):
return target_modules
return sorted({name.rsplit(".", 1)[-1] for name in target_modules})Others
No response
Source: hiyouga/LlamaFactory