# LoRA

[LoRA（低秩适应）](https://huggingface.co/papers/2106.09685)通过冻结原始权重并训练一组少量新参数，将预训练模型适配到新任务。与全量微调相比，这种适配方式速度更快、成本更低，因此适用于在新风格下生成图像等任务。

LoRA 检查点通常只有几百 MB。使用 `pipeline.load_lora_weights` 加载它们，并将 `weight_name` 设置为检查点文件名。有关共享参数，请参阅 [load_lora_weights()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights)。

```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)
```

本页中的 pipeline LoRA API 在不同模型系列中工作方式相同。在 [Stable Diffusion](../api/pipelines/stable_diffusion/overview) 和 [SDXL](../api/pipelines/stable_diffusion/stable_diffusion_xl) 中，去噪模块是 `pipeline.unet`；而在 [Flux](../api/pipelines/flux)、[Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3)、[AuraFlow](../api/pipelines/aura_flow) 和 [LTX](../api/pipelines/ltx_video) 等 DiT 风格模型中，则是 `pipeline.transformer`。同样的模式也适用于 [CogVideoX](../api/pipelines/cogvideox)、[HunyuanVideo](../api/pipelines/hunyuan_video) 和 [Wan](../api/pipelines/wan) 等视频模型。模型级 PEFT 方法使用该属性以及对应的 `prefix`（`"unet"` 或 `"transformer"`）。

`pipeline.load_lora_weights` 是将 LoRA 权重加载到去噪器（UNet 或 transformer）和文本编码器中的推荐方式。有关共享参数，请参阅 [load_lora_weights()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights)。它可以处理以下情况：

- 该检查点在去噪器和文本编码器之间共享键
- 该检查点使用独立的去噪器和文本编码器键

[load_lora_adapter()](/docs/diffusers/v0.43.0/zh/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.load_lora_adapter) 方法会在任何继承自 `PeftAdapterMixin` 的 Diffusers 模型（例如 UNet 或 transformer）上，以*模型级别*加载 LoRA 适配器。它会构建并准备适配器配置，并将权重加载到该模块中。

使用 `prefix` 来筛选目标模块（`"unet"` 或 `"transformer"`）的 state dict 键。默认值为 `"transformer"`，因此 Stable Diffusion 和 SDXL 必须传入 `prefix="unet"`。

```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) 通过将 PyTorch 模型编译为使用优化内核来加速推理。在编译之前，需要先将 LoRA 权重融合到基础模型中，然后将其卸载。

```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()
```

通常，应编译去噪器，因为它是流水线中计算量最大的组件。

```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]
```

对于 Flux 及其他 DiT 流水线，请改为编译 `pipeline.transformer`。

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

请参阅 [hotswapping](#hotswapping) 部分，了解在使用编译模型和多个 LoRA 时如何避免重新编译。

## 权重缩放

使用 [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) 上的 `adapter_weights` 参数来控制应用多少 LoRA。权重为 `0` 相当于仅使用基础模型权重，而权重为 `1` 相当于完全使用 LoRA。

在 [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) 中向 `adapter_weights` 传入一个标量，以控制 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` 是主要模式，但某些流水线也接受在调用时传入 `cross_attention_kwargs={"scale": 1.0}` 作为缩放注意力的次要方式。不使用交叉注意力的流水线通常改为暴露 `attention_kwargs`（或在 Flux 和 Stable Diffusion 3 中暴露 `joint_attention_kwargs`）。

> [!WARNING]
> [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters) 方法仅对注意力权重进行缩放。如果 LoRA 包含 ResNet 或下采样/上采样器，这些组件的缩放值将保持为 `1.0`。

传入一个字典以缩放每个文本编码器或去噪器模块。字典的键遵循流水线模块的命名。以下示例为 SDXL（`unet` 加文本编码器）。Flux 使用 `transformer` 和 `text_encoder`。SD3 使用 `transformer` 和多个文本编码器。

在此 SDXL 示例中，UNet 中的 `"down"` 块被缩放为 0.9，并且可以在 `"up"` 下的 `"block_0"` 和 `"block_1"` 中进一步指定注意力块的缩放比例。如果未指定某个块（例如 `"mid"`），则使用默认值 `1.0`。

```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]
```

### 扩展调度

在采样过程中动态调整 LoRA 缩放系数，能让您更好地控制整体构图和布局，因为某些步骤可能从增大或减小缩放系数中获益更多。

下例中的 [character LoRA](https://huggingface.co/alvarobartt/ghibli-characters-flux-lora) 以一个较高的 scale 开始，并在前 20 步中逐渐衰减，以建立角色生成。在后续步骤中，仅应用 `0.2` 的 scale，以避免将过多的 LoRA 特征添加到 LoRA 未训练过的图像其他部分。

```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]
```

## 热插拔

热切换 LoRA 是一种高效的方式，可在处理多个 LoRA 时避免多次调用 `load_lora_weights` 导致的内存累积，并且在某些情况下（如果模型已编译）还能避免重新编译。此工作流要求已加载一个 LoRA，因为新的 LoRA 权重会就地替换当前已加载的 LoRA。

```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]
> 对于目标为文本编码器的 LoRA，不支持热切换。

在 `load_lora_weights` 中设置 `hotswap=True` 以切换第二个 LoRA。使用 `adapter_name` 参数来指定要切换的 LoRA。如果在加载时省略 `adapter_name`，Diffusers 会将适配器命名为 `default_0`、`default_1` 等。使用命名适配器可以更明确地指定目标。

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

### 编译后的模型

对于已编译的模型，请使用 [enable_lora_hotswap()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) 以避免在热切换 LoRA 时触发重新编译。此方法应在加载第一个 LoRA *之前* 调用，而 `torch.compile` 应在加载第一个 LoRA *之后* 调用。

> [!TIP]
> 如果第二个 LoRA 与第一个 LoRA 具有相同的 LoRA 秩和缩放，则不一定需要调用 [enable_lora_hotswap()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) 方法。

在 [enable_lora_hotswap()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) 中，将 `target_rank` 设置为您计划加载的适配器中的最高秩（默认值为 128）。

```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]
> 将代码放入 `with torch._dynamo.config.patch(error_on_recompile=True)` 上下文管理器中，以检测模型是否被重新编译。如果按照上述所有步骤操作后模型仍被重新编译，请提交一个包含可复现示例的 [issue](https://github.com/huggingface/diffusers/issues)。

如果您预期在使用此功能进行推理时会出现不同的分辨率，请确保在编译时设置 `dynamic=True`。有关更多详细信息，请参阅 [动态形状编译](../optimization/fp16#dynamic-shape-compilation)。

在某些情况下，重新编译仍不可避免，例如当热切换的 LoRA 目标层数多于初始适配器时。建议优先加载目标层数最多的 LoRA *首先*。有关此限制的更多详细信息，请参阅 PEFT 的 [热切换](https://huggingface.co/docs/peft/main/en/package_reference/hotswap#peft.utils.hotswap.hotswap_adapter) 文档。

为什么 `target_rank` 和加载顺序很重要

[enable_lora_hotswap()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) 方法将 LoRA 缩放因子从浮点数转换为 torch.tensors，并将权重的形状填充至所需的最大形状，以便在替换权重中的数据时避免重新分配整个属性。

这正是 `target_rank` 参数重要的原因。即使使用零填充，结果也不会改变。不过，根据填充大小，计算速度可能会变慢。

由于不会添加新的 LoRA 属性，每个后续加载的 LoRA 只能针对第一个 LoRA 所针对的相同层，或这些层的一个子集。选择 LoRA 的加载顺序非常重要，因为如果各个 LoRA 针对的是互不重叠的层，最终可能会创建一个针对所有目标层并集的 dummy LoRA。

有关使用编译模型进行 LoRA 热切换的更多信息，请参阅 [LoRA fast](https://huggingface.co/blog/lora-fast) 博客文章；如需了解更多实现细节，请查看 [`hotswap.py`](https://github.com/huggingface/peft/blob/92d65cafa51c829484ad3d95cf71d09de57ff066/src/peft/utils/hotswap.py) 文件。

## 合并

可以将各个 LoRA 的权重合并，以生成多种现有风格的混合效果。合并 LoRA 有多种方法，每种方法在*如何*合并权重方面有所不同（这可能会影响生成质量）。

### set_adapters[[merge]]

[set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) 方法通过拼接加权矩阵来合并 LoRA。将 LoRA 名称传递给 [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters)，并使用 `adapter_weights` 参数来控制每个 LoRA 的缩放。例如，如果 `adapter_weights=[0.5, 0.5]`，则输出为两个 LoRA 的平均值。

> [!TIP]
> 在 [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) 中优先使用 `adapter_weights` 来控制每个合并后的 LoRA 的应用程度。有关更多详细信息，请参阅 [Weight scale](#weight-scale) 部分。

```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]
> 这是一种实验性方法，有关更多详细信息，请参阅 PEFT 的 [模型合并](https://huggingface.co/docs/peft/developer_guides/model_merging)。如果您对此次集成的动机和设计感兴趣，请查看此 [issue](https://github.com/huggingface/diffusers/issues/6892)。

`add_weighted_adapter` 方法支持更高效的合并方法，例如 [TIES](https://huggingface.co/papers/2306.01708) 或 [DARE](https://huggingface.co/papers/2311.03099)。这些合并方法会从合并后的模型中移除冗余且可能相互干扰的参数。请注意，要合并的 LoRA 秩必须具有相同的秩。下面的示例使用 SDXL 的 UNet。

请确保已安装最新稳定版的 Diffusers 和 PEFT。

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

加载与 LoRA UNet 对应的 UNet。

```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"
```

加载一个 pipeline，将 UNet 传入其中，并加载一个 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"
)
```

通过组合你加载的第一个 UNet 和流水线中的 LoRA UNet，从 LoRA 检查点创建一个 `PeftModel`。

```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]
> 您可以将 `ikea_peft_model` 推送到 Hub 以保存并重复使用，如下所示。
> ```py
> ikea_peft_model.push_to_hub("ikea_peft_model", token=TOKEN)
> ```

重复此过程，为第二个 LoRA 创建一个 `PeftModel`。

```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)
```

加载基础 UNet 模型并加载适配器。

```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"
)
```

使用 `add_weighted_adapter` 合并 LoRA，并通过 `combination_type` 指定合并方式。下面的示例使用了 `"dare_linear"` 方法（请参阅这篇[博客文章](https://huggingface.co/blog/peft_merging)以了解有关这些合并方法的更多信息），该方法会随机剪枝部分权重，然后根据 `weights` 中为每个 LoRA 设置的权重对张量执行加权求和。

使用 [set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters) 激活合并后的 LoRA。

```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

[fuse_lora()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) 方法会将 LoRA 权重直接融合到底层模型原始的 denoiser（UNet 或 transformer）以及文本编码器的权重中。由于底层模型只需加载一次，这减少了为每个 LoRA 加载底层模型的开销，从而降低了内存占用并提升了推理速度。

```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])
```

调用 [fuse_lora()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) 以将它们融合。`lora_scale` 参数用于控制使用 LoRA 权重对输出进行缩放的幅度。现在进行此调整很重要，因为在管道中将 `scale` 传递给 `cross_attention_kwargs` 是无效的。

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

由于 LoRA 权重已经与底层模型融合，请卸载这些 LoRA 权重。使用 [save_pretrained()](/docs/diffusers/v0.43.0/zh/api/pipelines/overview#diffusers.DiffusionPipeline.save_pretrained) 将融合后的 pipeline 保存到本地，或使用 `~PushToHubMixin.push_to_hub` 将其保存到 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")
```

现在，融合后的流水线可以快速加载用于推理，而无需分别加载每个 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]
```

使用 [unfuse_lora()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unfuse_lora) 可以恢复底层模型的权重，例如当你希望使用不同的 `lora_scale` 值时。只有在仅融合了一个 LoRA 的情况下才能执行解融合操作。例如，上述流水线中存在多个已融合的 LoRA，因此无法使用该方法。在这种情况下，你需要重新加载整个模型。

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

## 管理

Diffusers 提供了多种方法来帮助你管理 LoRA 的使用。如果你正在同时使用多个 LoRA，这些方法会特别有用。

### set_adapters[[manage]]

[set_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) 还会激活当前要使用的 LoRA（当存在多个已激活的 LoRA 时）。这允许您通过指定名称在不同的 LoRA 之间进行切换。

```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

使用 [save_lora_adapter()](/docs/diffusers/v0.43.0/zh/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.save_lora_adapter) 在加载到（`pipeline.unet` 或 `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

[unload_lora_weights()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unload_lora_weights) 方法会卸载流水线中的 LoRA 权重，以恢复底层模型权重。

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

### disable_lora

[disable_lora()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.disable_lora) 方法会禁用所有 LoRA（但它们仍保留在 pipeline 中），并将 pipeline 恢复到底层模型权重。

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

### get_active_adapters

[get_active_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_active_adapters) 方法返回附加到管道上的活动 LoRA 列表。

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

### get_list_adapters

[get_list_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_list_adapters) 方法返回流水线中每个组件已加载的所有 LoRA。字典的键与已加载的模块相匹配，例如 `unet` 或 `transformer` 以及任何文本编码器。

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

### delete_adapters

[delete_adapters()](/docs/diffusers/v0.43.0/zh/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.delete_adapters) 方法会从模型中彻底移除 LoRA 及其层。

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

## 后续步骤

- 浏览 [LoRA Studio](https://lorastudio.co/models) 以选择要使用的不同 LoRA，或者使用下方的 Space 将您从 Civitai 下载的常用 LoRA 上传到 Hub。

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

- You can find additional LoRAs in the [FLUX LoRA the Explorer](https://huggingface.co/spaces/multimodalart/flux-lora-the-explorer) and [LoRA the Explorer](https://huggingface.co/spaces/multimodalart/LoraTheExplorer) Spaces.

- 请阅读 [使用 Diffusers 和 PEFT 实现 Flux 的 Fast LoRA 推理](https://huggingface.co/blog/lora-fast) 博客文章，了解如何通过 FlashAttention-3 和 fp8 量化等方法优化 LoRA 推理。

