# LoRA

[LoRA (Low-Rank Adaptation)](https://huggingface.co/papers/2106.09685) адаптирует предобученную модель к новой задаче, замораживая исходные веса и обучая небольшой набор новых параметров. Адаптация проходит быстрее и дешевле, чем полная дообучение, что делает её практичной для задач, таких как генерация изображений в новом стиле.

Чекпоинты LoRA обычно занимают всего несколько сотен МБ. Загрузите их с помощью `pipeline.load_lora_weights` и установите для `weight_name` имя файла чекпоинта. Общие параметры описаны в [load_lora_weights()](/docs/diffusers/v0.43.0/ru/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)
```

API для LoRA в пайплайнах на этой странице работают одинаково для всех семейств моделей. Модуль денойзинга — это `pipeline.unet` в [Stable Diffusion](../api/pipelines/stable_diffusion/overview) и [SDXL](../api/pipelines/stable_diffusion/stable_diffusion_xl), а `pipeline.transformer` в моделях DiT-типа, таких как [Flux](../api/pipelines/flux), [Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3), [AuraFlow](../api/pipelines/aura_flow) и [LTX](../api/pipelines/ltx_video). Тот же паттерн применяется к видео-моделям, таким как [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/ru/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights). Этот метод поддерживает следующие случаи:

- чекпоинт разделяет ключи между денойзером и текстовыми кодировщиками
- чекпоинт использует отдельные ключи для денойзера и текстового энкодера

Метод [load_lora_adapter()](/docs/diffusers/v0.43.0/ru/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.load_lora_adapter) загружает адаптер LoRA на уровне *модели* для любой модели Diffusers, наследующей `PeftAdapterMixin`, например UNet или трансформер. Он формирует и настраивает конфигурацию адаптера, а затем загружает веса в соответствующий модуль.

Используйте `prefix` для фильтрации ключей state dict целевого модуля (`"unet"` или `"transformer"`). По умолчанию установлено значение `"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()
```

Обычно компилируют denoiser, поскольку это наиболее вычислительно затратный компонент пайплайна.

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

## Масштаб весов

Используйте параметр `adapter_weights` в [set_adapters()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters), чтобы управлять степенью применения LoRA. Значение `0` эквивалентно использованию только весов базовой модели, а значение `1` — полному применению LoRA.

Передайте скаляр в `adapter_weights` при вызове [set_adapters()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters), чтобы управлять силой применения 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` (или `joint_attention_kwargs` в Flux и Stable Diffusion 3).

> [!WARNING]
> Метод [set_adapters()](/docs/diffusers/v0.43.0/ru/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters) масштабирует только веса внимания. Если в LoRA есть ResNet или down/up-сэмплеры, эти компоненты сохраняют значение масштаба `1.0`.

Передайте словарь для масштабирования каждого блока текстового энкодера или денойзера. Ключи словаря соответствуют модулям пайплайна. Пример ниже — SDXL (`unet` плюс текстовые энкодеры). Flux использует `transformer` и `text_encoder`. SD3 использует `transformer` и несколько текстовых энкодеров.

В этом примере SDXL блок `"down"` в UNet масштабируется коэффициентом 0.9, а масштабы блоков внимания можно дополнительно указать в `"block_0"` и `"block_1"` внутри `"up"`. Если блок, например `"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) в примере ниже начинает работу с более высоким масштабом, который постепенно снижается в течение первых 20 шагов для формирования генерации персонажа. На последующих шагах применяется только масштаб `0.2`, чтобы избежать чрезмерного добавления признаков 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 заменяют существующие загруженные веса на месте.

```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, нацеленных на текстовый энкодер.

Установите `hotswap=True` в `load_lora_weights`, чтобы заменить второй 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/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap), чтобы избежать повторной компиляции при горячей замене LoRA. Этот метод следует вызывать *до* загрузки первой LoRA, а `torch.compile` — *после* загрузки первой LoRA.

> [!TIP]
> Метод [enable_lora_hotswap()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) не всегда необходим, если второй LoRA использует те же ранги и масштабы LoRA, что и первый.

Внутри [enable_lora_hotswap()](/docs/diffusers/v0.43.0/ru/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/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) преобразует коэффициент масштабирования LoRA из чисел с плавающей точкой в torch.tensors и дополняет форму весов до наибольшей требуемой формы, чтобы избежать повторного присваивания всего атрибута при замене данных в весах.

Именно поэтому аргумент `target_rank` важен. Результаты не изменяются, даже если значения дополнены нулями. Однако вычисления могут выполняться медленнее в зависимости от размера дополнения.

Поскольку новые атрибуты LoRA не добавляются, каждый последующий LoRA может нацеливаться только на те же слои, что и первый LoRA, или на подмножество этих слоёв. Выбор порядка загрузки LoRA имеет значение, так как, если LoRA нацелены на непересекающиеся наборы слоёв, вы можете в итоге создать фиктивный 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/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) объединяет LoRA, конкатенируя их взвешенные матрицы. Передайте имена LoRA в [set_adapters()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) и используйте параметр `adapter_weights` для управления масштабированием каждого LoRA. Например, если `adapter_weights=[0.5, 0.5]`, на выходе получится среднее значение обоих LoRA.

> [!TIP]
> Используйте `adapter_weights` в [set_adapters()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters), чтобы управлять степенью применения каждого объединённого LoRA. Подробности — в разделе [Масштаб весов](#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]
> Это экспериментальный метод, подробнее о нём можно узнать в разделе [Слияние моделей](https://huggingface.co/docs/peft/developer_guides/model_merging) PEFT. Если вас интересует мотивация и принципы проектирования этой интеграции, посмотрите эту [задачу](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 должны быть идентичны для слияния. В приведённом ниже руководстве используется UNet модели SDXL.

Убедитесь, что установлены последние стабильные версии Diffusers и PEFT.

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

Загрузите UNet, соответствующий LoRA 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"
```

Загрузите конвейер, передайте в него 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"
)
```

Создайте `PeftModel` из контрольной точки LoRA, объединив первый загруженный вами UNet и LoRA UNet из конвейера.

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

Повторите этот процесс и создайте `PeftModel` для второго 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)
```

Загрузите базовую модель 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"
)
```

Соедините LoRA с помощью `add_weighted_adapter` и укажите способ их объединения с помощью `combination_type`. В примере ниже используется метод `"dare_linear"` (подробнее об этих методах объединения читайте в этой [статье](https://huggingface.co/blog/peft_merging)), который случайно удаляет часть весов, а затем выполняет взвешенную сумму тензоров на основе заданных в `weights` весов каждого LoRA.

Активируйте объединённые LoRA с помощью [set_adapters()](/docs/diffusers/v0.43.0/ru/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

Метод [fuse_lora()](/docs/diffusers/v0.43.0/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) объединяет веса LoRA непосредственно с весами исходного денойзера (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/ru/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, поскольку они уже слиты с базовой моделью. Сохраните слитый пайплайн с помощью [save_pretrained()](/docs/diffusers/v0.43.0/ru/api/pipelines/overview#diffusers.DiffusionPipeline.save_pretrained) для локального сохранения или `~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/ru/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/ru/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/ru/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/ru/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/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.disable_lora) отключает все LoRA (но они по-прежнему сохраняются в конвейере) и восстанавливает конвейер до весов базовой модели.

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

### get_active_adapters

Метод [get_active_adapters()](/docs/diffusers/v0.43.0/ru/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/ru/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/ru/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.delete_adapters) полностью удаляет LoRA и его слои из модели.

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

## Дальнейшие шаги

- Просматривайте [LoRA Studio](https://lorastudio.co/models), чтобы выбрать различные LoRA, или загрузите свои любимые LoRA с Civitai на Hub с помощью Space ниже.

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

- Ознакомьтесь с блогом [Быстрый вывод LoRA для Flux с Diffusers и PEFT](https://huggingface.co/blog/lora-fast), чтобы узнать, как оптимизировать вывод LoRA с помощью методов, таких как FlashAttention-3 и квантование fp8.

