Diffusers documentation
LoRA
LoRA
LoRA (Low-Rank Adaptation) 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() pour les paramètres partagés.
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]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 et SDXL, et pipeline.transformer pour les modèles de type DiT tels que Flux, Stable Diffusion 3, AuraFlow et LTX. Le même schéma s'applique aux modèles vidéo tels que CogVideoX, HunyuanVideo et 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() 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() 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.
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]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 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.
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.
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.
pipeline.transformer = torch.compile(pipeline.transformer, mode="reduce-overhead", fullgraph=True)Reportez-vous à la section 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() 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() pour contrôler l'intensité de l'application de LoRA.
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).
La méthode 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 par 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.
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 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é.
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é.
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"
)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.
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() 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.
La méthode 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(), définissez target_rank sur le rang le plus élevé parmi les adaptateurs que vous prévoyez de charger (128 par défaut).
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"
)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 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 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.
Why `target_rank` and load order matter
La méthode 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 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.
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
La méthode set_adapters() fusionne les LoRA en concaténant leurs matrices pondérées. Passez les noms des LoRA à 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.
Préférez
adapter_weightssur set_adapters() pour contrôler la quantité de chaque LoRA fusionné à appliquer. Consultez la section Weight scale pour plus de détails.
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
Il s’agit d’une méthode expérimentale et vous pouvez consulter Model merging de PEFT pour plus de détails. Consultez ce issue si vous souhaitez en savoir plus sur la motivation et la conception de cette intégration.
La méthode add_weighted_adapter permet d’utiliser des méthodes de fusion plus efficaces telles que TIES ou DARE. 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.
pip install -U -q diffusers peft
Charger un UNet correspondant à l'UNet LoRA.
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.
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.
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)Vous pouvez enregistrer et réutiliser le
ikea_peft_modelen le publiant sur le Hub, comme indiqué ci-dessous.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.
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.
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 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().
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() 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.
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() 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.
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() pour l’enregistrer localement ou de ~PushToHubMixin.push_to_hub pour l’enregistrer sur le Hub.
pipeline.unload_lora_weights()
pipeline.save_pretrained("path/to/fused-pipeline")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.
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() 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ésfusionner que s’il n’y a qu’un seul LoRA fusionné. Par exemple, cela ne fonctionnera pas avec le pipeline ci-dessus car il y a plusieurs LoRAs fusionnés. Dans ces cas, vous devrez recharger l’intégralité du modèle.
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
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.
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() sur le même module que vous avez chargé dans (pipeline.unet ou pipeline.transformer).
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() décharge les poids LoRA du pipeline afin de restaurer les poids du modèle sous-jacent.
pipeline.unload_lora_weights()
disable_lora
La méthode 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.
pipeline.disable_lora()
get_active_adapters
La méthode get_active_adapters() renvoie une liste des LoRA actifs attachés à un pipeline.
pipeline.get_active_adapters()
# ["cereal", "ikea"]get_list_adapters
La méthode 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.
pipeline.get_list_adapters()
# {"unet": ["cereal", "ikea"], "text_encoder_2": ["cereal"]}delete_adapters
La méthode delete_adapters() supprime complètement un LoRA et ses couches d'un modèle.
pipeline.delete_adapters("ikea")Étapes suivantes
- Parcourez le LoRA Studio 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.
Vous pouvez trouver d'autres LoRAs dans les Spaces FLUX LoRA the Explorer et LoRA the Explorer.
Consultez le billet de blog Fast LoRA inference for Flux with Diffusers and PEFT pour apprendre à optimiser l'inférence LoRA avec des méthodes telles que FlashAttention-3 et la quantification fp8.