# LoRA

[LoRA (Low-Rank Adaptation)](https://huggingface.co/papers/2106.09685) adapte un modèle pré-entraîné à une nouvelle tâche en figeant les poids d’origine et en entraînant un petit ensemble de nouveaux paramètres. L’adaptation est plus rapide et moins coûteuse qu’un fine-tuning complet, ce qui la rend pratique pour des tâches telles que la génération d’images dans un nouveau style.

Les points de contrôle LoRA ne font généralement que quelques centaines de Mo. Chargez-les avec `pipeline.load_lora_weights` et définissez `weight_name` sur le nom du fichier du point de contrôle. Consultez [load_lora_weights()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights) pour les paramètres partagés.

```py
import torch
from diffusers import AutoPipelineForText2Image

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/super-cereal-sdxl-lora",
    weight_name="cereal_box_sdxl_v1.safetensors",
    adapter_name="cereal"
)
pipeline("bears, pizza bites").images[0]
```

```py
import torch
from diffusers import LTXConditionPipeline
from diffusers.utils import export_to_video, load_image

pipeline = LTXConditionPipeline.from_pretrained(
    "Lightricks/LTX-Video-0.9.5", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

pipeline.load_lora_weights(
    "Lightricks/LTX-Video-Cakeify-LoRA",
    weight_name="ltxv_095_cakeify_lora.safetensors",
    adapter_name="cakeify"
)
pipeline.set_adapters("cakeify")

# use "CAKEIFY" to trigger the LoRA
prompt = "CAKEIFY a person using a knife to cut a cake shaped like a Pikachu plushie"
image = load_image("https://huggingface.co/Lightricks/LTX-Video-Cakeify-LoRA/resolve/main/assets/images/pikachu.png")

video = pipeline(
    prompt=prompt,
    image=image,
    width=576,
    height=576,
    num_frames=161,
    decode_timestep=0.03,
    decode_noise_scale=0.025,
    num_inference_steps=50,
).frames[0]
export_to_video(video, "output.mp4", fps=26)
```

Les API LoRA de pipeline de cette page fonctionnent de la même manière pour toutes les familles de modèles. Le module de débruitage est `pipeline.unet` pour [Stable Diffusion](../api/pipelines/stable_diffusion/overview) et [SDXL](../api/pipelines/stable_diffusion/stable_diffusion_xl), et `pipeline.transformer` pour les modèles de type DiT tels que [Flux](../api/pipelines/flux), [Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3), [AuraFlow](../api/pipelines/aura_flow) et [LTX](../api/pipelines/ltx_video). Le même schéma s'applique aux modèles vidéo tels que [CogVideoX](../api/pipelines/cogvideox), [HunyuanVideo](../api/pipelines/hunyuan_video) et [Wan](../api/pipelines/wan). Les méthodes PEFT au niveau du modèle utilisent cet attribut et un `prefix` correspondant (`"unet"` ou `"transformer"`).

`pipeline.load_lora_weights` est la méthode recommandée pour charger les poids LoRA dans le débruiteur (UNet ou transformer) et les encodeurs de texte. Consultez [load_lora_weights()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights) pour les paramètres partagés. Il peut gérer les cas suivants :

- le point de contrôle partage les clés entre le débruiteur et les encodeurs de texte
- le point de contrôle utilise des clés distinctes pour le débruiteur et l'encodeur de texte

La méthode [load_lora_adapter()](/docs/diffusers/v0.43.0/fr/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.load_lora_adapter) charge un adaptateur LoRA au *niveau du modèle* sur tout modèle Diffusers qui est une sous-classe de `PeftAdapterMixin`, tel qu'un UNet ou un transformer. Elle construit et prépare la configuration de l'adaptateur, puis charge les poids dans ce module.

Utilisez `prefix` pour filtrer les clés du state dict du module cible (`"unet"` ou `"transformer"`). La valeur par défaut est `"transformer"`, il faut donc passer `prefix="unet"` pour Stable Diffusion et SDXL.

```py
import torch
from diffusers import AutoPipelineForText2Image

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet.load_lora_adapter(
    "jbilcke-hf/sdxl-cinematic-1",
    weight_name="pytorch_lora_weights.safetensors",
    adapter_name="cinematic",
    prefix="unet"
)
# use cnmt in the prompt to trigger the LoRA
pipeline("A cute cnmt eating a slice of pizza, stunning color scheme, masterpiece, illustration").images[0]
```

```py
import torch
from diffusers import FluxPipeline

pipeline = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.transformer.load_lora_adapter(
    "alvarobartt/ghibli-characters-flux-lora",
    adapter_name="lora",
    prefix="transformer",
)
```

## torch.compile

[torch.compile](../optimization/fp16#torchcompile) accélère l’inférence en compilant le modèle PyTorch afin d’utiliser des noyaux optimisés. Avant la compilation, les poids LoRA doivent d’abord être fusionnés dans le modèle de base puis déchargés.

```py
import torch
from diffusers import DiffusionPipeline

# load base model and LoRA
pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)

# activate LoRA and set adapter weight
pipeline.set_adapters("ikea", adapter_weights=0.7)

# fuse LoRAs and unload weights
pipeline.fuse_lora(adapter_names=["ikea"], lora_scale=1.0)
pipeline.unload_lora_weights()
```

En général, compilez le débruiteur, car c'est le composant le plus gourmand en calculs du pipeline.

```py
pipeline.unet.to(memory_format=torch.channels_last)
pipeline.unet = torch.compile(pipeline.unet, mode="reduce-overhead", fullgraph=True)

pipeline("A bowl of ramen shaped like a cute kawaii bear").images[0]
```

Pour Flux et d'autres pipelines DiT, compilez plutôt `pipeline.transformer`.

```py
pipeline.transformer = torch.compile(pipeline.transformer, mode="reduce-overhead", fullgraph=True)
```

Reportez-vous à la section [hotswapping](#hotswapping) pour apprendre à éviter la recompilation lors de l'utilisation de modèles compilés et de plusieurs LoRAs.

## Échelle des poids

Utilisez le paramètre `adapter_weights` de [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) pour contrôler la quantité de LoRA à appliquer. Un poids de `0` équivaut à n'utiliser que les poids du modèle de base, tandis qu'un poids de `1` équivaut à utiliser pleinement le LoRA.

Passez un scalaire à `adapter_weights` sur [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) pour contrôler l'intensité de l'application de LoRA.

```py
import torch
from diffusers import AutoPipelineForText2Image

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/super-cereal-sdxl-lora",
    weight_name="cereal_box_sdxl_v1.safetensors",
    adapter_name="cereal"
)
pipeline.set_adapters("cereal", adapter_weights=1.0)
pipeline("bears, pizza bites").images[0]
```

`set_adapters` comme motif principal, mais certains pipelines acceptent également `cross_attention_kwargs={"scale": 1.0}` lors de l’appel comme moyen secondaire pour mettre à l’échelle l’attention. Les pipelines qui n’utilisent pas l’attention croisée exposent généralement `attention_kwargs` à la place (ou `joint_attention_kwargs` sur Flux et Stable Diffusion 3).

> [!WARNING]
> La méthode [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters) ne met à l'échelle que les poids d'attention. Si un LoRA contient des ResNets ou des sous-échantillonneurs et sur-échantillonneurs, ces composants conservent une valeur d'échelle de `1.0`.

Passez un dictionnaire pour mettre à l'échelle chaque bloc d'encodeur de texte ou de débruiteur. Les clés du dictionnaire suivent les modules du pipeline. L'exemple ci-dessous est SDXL (`unet` plus les encodeurs de texte). Flux utilise `transformer` et `text_encoder`. SD3 utilise `transformer` et plusieurs encodeurs de texte.

Dans cet exemple SDXL, le bloc `"down"` de l'UNet est mis à l'échelle de 0,9 et vous pouvez spécifier des échelles supplémentaires pour les blocs d'attention dans `"block_0"` et `"block_1"` sous `"up"`. Si un bloc comme `"mid"` n'est pas spécifié, la valeur par défaut `1.0` est utilisée.

```py
import torch
from diffusers import AutoPipelineForText2Image

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/super-cereal-sdxl-lora",
    weight_name="cereal_box_sdxl_v1.safetensors",
    adapter_name="cereal"
)
scales = {
    "text_encoder": 0.5,
    "text_encoder_2": 0.5,
    "unet": {
        "down": 0.9,
        "up": {
            "block_0": 0.6,
            "block_1": [0.4, 0.8, 1.0],
        }
    }
}
pipeline.set_adapters("cereal", scales)
pipeline("bears, pizza bites").images[0]
```

### Planification à l'échelle

Ajuster dynamiquement l'échelle LoRA pendant l'échantillonnage vous offre un meilleur contrôle sur la composition et la mise en page globales, car certaines étapes peuvent bénéficier davantage d'une échelle augmentée ou réduite.

Le [LoRA de personnage](https://huggingface.co/alvarobartt/ghibli-characters-flux-lora) de l’exemple ci-dessous démarre avec une échelle plus élevée qui décroît progressivement au cours des 20 premières étapes pour établir la génération du personnage. Aux étapes ultérieures, seule une échelle de `0.2` est appliquée afin d’éviter d’ajouter trop de caractéristiques du LoRA à d’autres parties de l’image sur lesquelles le LoRA n’a pas été entraîné.

```py
import torch
from diffusers import FluxPipeline

pipeline = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

pipeline.load_lora_weights("alvarobartt/ghibli-characters-flux-lora", adapter_name="lora")

num_inference_steps = 30
lora_steps = 20
lora_scales = torch.linspace(1.5, 0.7, lora_steps).tolist()
lora_scales += [0.2] * (num_inference_steps - lora_steps + 1)

pipeline.set_adapters("lora", lora_scales[0])

def callback(pipeline: FluxPipeline, step: int, timestep: torch.LongTensor, callback_kwargs: dict):
    pipeline.set_adapters("lora", lora_scales[step + 1])
    return callback_kwargs

prompt = """
Ghibli style The Grinch, a mischievous green creature with a sly grin, peeking out from behind a snow-covered tree while plotting his antics, 
in a quaint snowy village decorated for the holidays, warm light glowing from cozy homes, with playful snowflakes dancing in the air
"""
pipeline(
    prompt=prompt,
    guidance_scale=3.0,
    num_inference_steps=num_inference_steps,
    generator=torch.Generator().manual_seed(42),
    callback_on_step_end=callback,
).images[0]
```

## Chaud-froid

Le hotswapping de LoRA est une méthode efficace pour travailler avec plusieurs LoRA tout en évitant l’accumulation de mémoire due à plusieurs appels à `load_lora_weights` et, dans certains cas, la recompilation si le modèle est compilé. Ce flux de travail nécessite un LoRA chargé, car les nouveaux poids LoRA sont substitués sur place aux poids du LoRA déjà chargé.

```py
import torch
from diffusers import DiffusionPipeline

# load base model and LoRAs
pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
```

> [!WARNING]
> Le hotswapping n'est pas pris en charge pour les LoRAs qui ciblent l'encodeur de texte.

Définissez `hotswap=True` sur `load_lora_weights` pour remplacer le second LoRA. Utilisez le paramètre `adapter_name` pour indiquer quel LoRA remplacer. Si vous omettez `adapter_name` lors du chargement, Diffusers nomme les adaptateurs `default_0`, `default_1`, et ainsi de suite. Les adaptateurs nommés sont plus faciles à cibler explicitement.

```py
pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    hotswap=True,
    adapter_name="ikea"
)
```

### Modèles compilés

Pour les modèles compilés, utilisez [enable_lora_hotswap()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) pour éviter la recompilation lors du remplacement à chaud des LoRA. Cette méthode doit être appelée *avant* le chargement du premier LoRA et `torch.compile` doit être appelé *après* le chargement du premier LoRA.

> [!TIP]
> La méthode [enable_lora_hotswap()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) n'est pas toujours nécessaire si le second LoRA cible les mêmes rangs et échelles de LoRA que le premier.

Dans [enable_lora_hotswap()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap), définissez `target_rank` sur le rang le plus élevé parmi les adaptateurs que vous prévoyez de charger (128 par défaut).

```py
import torch
from diffusers import DiffusionPipeline

# load base model and LoRAs
pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
# 1. enable_lora_hotswap
pipeline.enable_lora_hotswap(target_rank=128)
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
# 2. torch.compile
pipeline.unet = torch.compile(pipeline.unet, mode="reduce-overhead", fullgraph=True)

# 3. hotswap
pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    hotswap=True,
    adapter_name="ikea"
)
```

> [!TIP]
> Déplacez votre code à l’intérieur du gestionnaire de contexte `with torch._dynamo.config.patch(error_on_recompile=True)` pour détecter si un modèle a été recompilé. Si un modèle est recompilé malgré le respect de toutes les étapes ci-dessus, veuillez ouvrir un [ticket](https://github.com/huggingface/diffusers/issues) avec un exemple reproductible.

Si vous prévoyez des résolutions variées lors de l’inférence avec cette fonctionnalité, assurez-vous de définir `dynamic=True` lors de la compilation. Reportez-vous à [compilation de formes dynamiques](../optimization/fp16#dynamic-shape-compilation) pour plus de détails.

Il existe toujours des scénarios où la recompilation est inévitable, par exemple lorsque le LoRA remplacé à chaud cible plus de couches que l’adaptateur initial. Essayez de charger le LoRA qui cible le plus de couches *en premier*. Pour plus de détails sur cette limitation, consultez la documentation PEFT sur le [remplacement à chaud](https://huggingface.co/docs/peft/main/en/package_reference/hotswap#peft.utils.hotswap.hotswap_adapter).

Pourquoi `target_rank` et l'ordre de chargement sont importants

La méthode [enable_lora_hotswap()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) convertit le facteur d’échelle LoRA de flottants en torch.tensors et ajuste la forme des poids à la plus grande forme requise afin d’éviter de réaffecter l’attribut entier lorsque les données des poids sont remplacées.

C'est pourquoi l'argument `target_rank` est important. Les résultats restent inchangés même lorsque les valeurs sont complétées par des zéros. Le calcul peut toutefois être plus lent, selon la taille du padding.

Étant donné qu’aucun nouvel attribut LoRA n’est ajouté, chaque LoRA ultérieur ne peut cibler que les mêmes couches, ou un sous-ensemble des couches, que celles ciblées par le premier LoRA. Le choix de l’ordre de chargement des LoRA est important, car si les LoRA ciblent des couches disjointes, vous risquez de créer un LoRA fictif qui cible l’union de toutes les couches cibles.

Consultez le billet de blog [LoRA fast](https://huggingface.co/blog/lora-fast) pour en savoir plus sur le hotswapping de LoRA avec des modèles compilés, et pour plus de détails sur l’implémentation, consultez le fichier [`hotswap.py`](https://github.com/huggingface/peft/blob/92d65cafa51c829484ad3d95cf71d09de57ff066/src/peft/utils/hotswap.py).

## Fusion

Les poids de chaque LoRA peuvent être fusionnés pour produire un mélange de plusieurs styles existants. Il existe plusieurs méthodes de fusion de LoRAs, qui diffèrent par *la manière* dont les poids sont fusionnés (ce qui peut affecter la qualité de la génération).

### set_adapters[[merge]]

La méthode [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) fusionne les LoRA en concaténant leurs matrices pondérées. Passez les noms des LoRA à [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) et utilisez le paramètre `adapter_weights` pour contrôler le facteur d'échelle de chaque LoRA. Par exemple, si `adapter_weights=[0.5, 0.5]`, la sortie est la moyenne des deux LoRA.

> [!TIP]
> Préférez `adapter_weights` sur [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) pour contrôler la quantité de chaque LoRA fusionné à appliquer. Consultez la section [Weight scale](#weight-scale) pour plus de détails.

```py
import torch
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    weight_name="fengzikai_v1.0_XL.safetensors",
    adapter_name="feng"
)
pipeline.set_adapters(["ikea", "feng"], adapter_weights=[0.7, 0.8])
# use by Feng Zikai to activate the lordjia/by-feng-zikai LoRA
pipeline("A bowl of ramen shaped like a cute kawaii bear, by Feng Zikai").images[0]
```

### add_weighted_adapter

> [!TIP]
> Il s’agit d’une méthode expérimentale ; vous pouvez consulter [Model merging](https://huggingface.co/docs/peft/developer_guides/model_merging) de PEFT pour plus de détails. Si vous souhaitez en savoir plus sur la motivation et la conception de cette intégration, consultez ce [issue](https://github.com/huggingface/diffusers/issues/6892).

La méthode `add_weighted_adapter` permet d'utiliser des méthodes de fusion plus efficaces telles que [TIES](https://huggingface.co/papers/2306.01708) ou [DARE](https://huggingface.co/papers/2311.03099). Ces méthodes de fusion suppriment les paramètres redondants et potentiellement interférents des modèles fusionnés. Gardez à l'esprit que les rangs LoRA doivent être identiques pour pouvoir être fusionnés. Le tutoriel ci-dessous utilise le UNet de SDXL.

Assurez-vous que la dernière version stable de Diffusers et PEFT est installée.

```bash
pip install -U -q diffusers peft
```

Charger un UNet correspondant à l'UNet LoRA.

```py
import copy
import torch
from diffusers import AutoModel, DiffusionPipeline
from peft import get_peft_model, LoraConfig, PeftModel

unet = AutoModel.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    use_safetensors=True,
    variant="fp16",
    subfolder="unet",
).to("cuda")  # or "mps", "xpu", "cpu"
```

Chargez un pipeline, passez-y le UNet et chargez un LoRA.

```py
pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    variant="fp16",
    dtype=torch.float16,
    unet=unet
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
```

Créez un `PeftModel` à partir du checkpoint LoRA en combinant le premier UNet que vous avez chargé et l'UNet LoRA du pipeline.

```py
sdxl_unet = copy.deepcopy(unet)
ikea_peft_model = get_peft_model(
    sdxl_unet,
    pipeline.unet.peft_config["ikea"],
    adapter_name="ikea"
)

original_state_dict = {f"base_model.model.{k}": v for k, v in pipeline.unet.state_dict().items()}
ikea_peft_model.load_state_dict(original_state_dict, strict=True)
```

> [!TIP]
> Vous pouvez enregistrer et réutiliser le `ikea_peft_model` en le publiant sur le Hub, comme indiqué ci-dessous.
> ```py
> ikea_peft_model.push_to_hub("ikea_peft_model", token=TOKEN)
> ```

Répétez ce processus et créez un `PeftModel` pour le second LoRA.

```py
pipeline.delete_adapters("ikea")
sdxl_unet.delete_adapters("ikea")

pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    weight_name="fengzikai_v1.0_XL.safetensors",
    adapter_name="feng"
)
pipeline.set_adapters(adapter_names="feng")

feng_peft_model = get_peft_model(
    sdxl_unet,
    pipeline.unet.peft_config["feng"],
    adapter_name="feng"
)

original_state_dict = {f"base_model.model.{k}": v for k, v in pipeline.unet.state_dict().items()}
feng_peft_model.load_state_dict(original_state_dict, strict=True)
```

Charger un modèle UNet de base et charger les adaptateurs.

```py
base_unet = AutoModel.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    use_safetensors=True,
    variant="fp16",
    subfolder="unet",
).to("cuda")  # or "mps", "xpu", "cpu"

model = PeftModel.from_pretrained(
    base_unet,
    "stevhliu/ikea_peft_model",
    use_safetensors=True,
    subfolder="ikea",
    adapter_name="ikea"
)
model.load_adapter(
    "stevhliu/feng_peft_model",
    use_safetensors=True,
    subfolder="feng",
    adapter_name="feng"
)
```

Fusionnez les LoRAs avec `add_weighted_adapter` et spécifiez la manière dont vous souhaitez les fusionner à l'aide de `combination_type`. L'exemple ci-dessous utilise la méthode `"dare_linear"` (consultez cette [publication de blog](https://huggingface.co/blog/peft_merging) pour en savoir plus sur ces méthodes de fusion), qui supprime aléatoirement certains poids puis effectue une somme pondérée des tenseurs en fonction du poids défini pour chaque LoRA dans `weights`.

Activez les LoRAs fusionnés avec [set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters).

```py
model.add_weighted_adapter(
    adapters=["ikea", "feng"],
    combination_type="dare_linear",
    weights=[1.0, 1.0],
    adapter_name="ikea-feng"
)
model.set_adapters("ikea-feng")

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    unet=model,
    variant="fp16",
    dtype=torch.float16,
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline("A bowl of ramen shaped like a cute kawaii bear, by Feng Zikai").images[0]
```

### fuse_lora

La méthode [fuse_lora()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) fusionne directement les poids LoRA avec les poids du débruiteur d'origine (UNet ou transformer) et de l'encodeur de texte du modèle sous-jacent. Cela réduit le surcoût lié au chargement du modèle sous-jacent pour chaque LoRA, car le modèle n'est chargé qu'une seule fois, ce qui diminue l'utilisation de la mémoire et augmente la vitesse d'inférence.

```py
import torch
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    weight_name="fengzikai_v1.0_XL.safetensors",
    adapter_name="feng"
)
pipeline.set_adapters(["ikea", "feng"], adapter_weights=[0.7, 0.8])
```

Appel [fuse_lora()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) pour les fusionner. Le paramètre `lora_scale` contrôle l’ampleur de la mise à l’échelle de la sortie par les poids LoRA. Il est important d’effectuer ce réglage maintenant, car le passage de `scale` à `cross_attention_kwargs` ne fonctionnera pas dans le pipeline.

```py
pipeline.fuse_lora(adapter_names=["ikea", "feng"], lora_scale=1.0)
```

Déchargez les poids LoRA, car ils sont déjà fusionnés avec le modèle sous-jacent. Enregistrez le pipeline fusionné à l'aide de [save_pretrained()](/docs/diffusers/v0.43.0/fr/api/pipelines/overview#diffusers.DiffusionPipeline.save_pretrained) pour l'enregistrer localement ou de `~PushToHubMixin.push_to_hub` pour l'enregistrer sur le Hub.

```py
pipeline.unload_lora_weights()
pipeline.save_pretrained("path/to/fused-pipeline")
```

```py
pipeline.unload_lora_weights()
pipeline.push_to_hub("fused-ikea-feng")
```

Le pipeline fusionné peut désormais être chargé rapidement pour l'inférence sans nécessiter le chargement séparé de chaque LoRA.

```py
pipeline = DiffusionPipeline.from_pretrained(
    "username/fused-ikea-feng", dtype=torch.float16,
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline("A bowl of ramen shaped like a cute kawaii bear, by Feng Zikai").images[0]
```

Utilisez [unfuse_lora()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unfuse_lora) pour restaurer les poids du modèle sous-jacent, par exemple si vous souhaitez utiliser une valeur différente pour `lora_scale`. Vous ne pouvez désagréger que s'il n'y a qu'un seul LoRA agrégé. Par exemple, cela ne fonctionnera pas avec le pipeline ci-dessus car il y a plusieurs LoRA agrégés. Dans ces cas, vous devrez recharger l'intégralité du modèle.

```py
pipeline.unfuse_lora()
```

## Gérer

Diffusers fournit plusieurs méthodes pour vous aider à gérer le travail avec les LoRA. Ces méthodes sont particulièrement utiles si vous travaillez avec plusieurs LoRA.

### set_adapters[[manage]]

[set_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) active également le LoRA actuel à utiliser s’il existe plusieurs LoRAs actifs. Cela permet de basculer entre différents LoRAs en spécifiant leur nom.

```py
import torch
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_lora_weights(
    "ostris/ikea-instructions-lora-sdxl",
    weight_name="ikea_instructions_xl_v1_5.safetensors",
    adapter_name="ikea"
)
pipeline.load_lora_weights(
    "lordjia/by-feng-zikai",
    weight_name="fengzikai_v1.0_XL.safetensors",
    adapter_name="feng"
)
# activates the feng LoRA instead of the ikea LoRA
pipeline.set_adapters("feng")
```

### save_lora_adapter

Enregistrez un adaptateur avec [save_lora_adapter()](/docs/diffusers/v0.43.0/fr/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.save_lora_adapter) sur le même module que vous avez chargé dans (`pipeline.unet` ou `pipeline.transformer`).

```py
import torch
from diffusers import AutoPipelineForText2Image

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet.load_lora_adapter(
    "jbilcke-hf/sdxl-cinematic-1",
    weight_name="pytorch_lora_weights.safetensors",
    adapter_name="cinematic",
    prefix="unet"
)
pipeline.unet.save_lora_adapter("path/to/save", adapter_name="cinematic")
```

### unload_lora_weights

La méthode [unload_lora_weights()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unload_lora_weights) décharge les poids LoRA du pipeline afin de restaurer les poids du modèle sous-jacent.

```py
pipeline.unload_lora_weights()
```

### disable_lora

La méthode [disable_lora()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.disable_lora) désactive tous les LoRA (mais ils restent conservés sur le pipeline) et restaure le pipeline aux poids du modèle sous-jacent.

```py
pipeline.disable_lora()
```

### get_active_adapters

La méthode [get_active_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_active_adapters) renvoie une liste des LoRA actifs attachés à un pipeline.

```py
pipeline.get_active_adapters()
# ["cereal", "ikea"]
```

### get_list_adapters

La méthode [get_list_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_list_adapters) renvoie tous les LoRAs chargés pour chaque composant du pipeline. Les clés du dictionnaire correspondent aux modules chargés, tels que `unet` ou `transformer` ainsi que les encodeurs de texte.

```py
pipeline.get_list_adapters()
# {"unet": ["cereal", "ikea"], "text_encoder_2": ["cereal"]}
```

### delete_adapters

La méthode [delete_adapters()](/docs/diffusers/v0.43.0/fr/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.delete_adapters) supprime complètement un LoRA et ses couches d'un modèle.

```py
pipeline.delete_adapters("ikea")
```

## Étapes suivantes

- Parcourez le [LoRA Studio](https://lorastudio.co/models) pour découvrir différents LoRA à utiliser, ou téléchargez vos LoRA préférés depuis Civitai vers le Hub à l’aide de l’espace ci-dessous.

<iframe src="https://multimodalart-civitai-to-hf.hf.space" frameborder="0" width="850" height="450"
>

- Vous pouvez trouver d'autres LoRAs dans les Spaces [FLUX LoRA the Explorer](https://huggingface.co/spaces/multimodalart/flux-lora-the-explorer) et [LoRA the Explorer](https://huggingface.co/spaces/multimodalart/LoraTheExplorer).

- Consultez le billet de blog [Fast LoRA inference for Flux with Diffusers and PEFT](https://huggingface.co/blog/lora-fast) pour apprendre à optimiser l'inférence LoRA avec des méthodes telles que FlashAttention-3 et la quantification fp8.

