# LoRA

[LoRA (Low-Rank Adaptation)](https://huggingface.co/papers/2106.09685) điều chỉnh một mô hình được huấn luyện trước cho một tác vụ mới bằng cách đóng băng các trọng số gốc và huấn luyện một tập hợp nhỏ các tham số mới. Quá trình điều chỉnh nhanh hơn và rẻ hơn so với fine-tuning toàn bộ, giúp phương pháp này trở nên thực tế cho các tác vụ như tạo ảnh theo phong cách mới.

Checkpoint LoRA thường chỉ nặng vài trăm MB. Hãy tải chúng bằng `pipeline.load_lora_weights` và đặt `weight_name` thành tên tệp checkpoint. Xem [load_lora_weights()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights) để biết các tham số chung.

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

Các API pipeline LoRA trên trang này hoạt động giống nhau giữa các họ model. Module denoising là `pipeline.unet` trên [Stable Diffusion](../api/pipelines/stable_diffusion/overview) và [SDXL](../api/pipelines/stable_diffusion/stable_diffusion_xl), và là `pipeline.transformer` trên các model kiểu DiT như [Flux](../api/pipelines/flux), [Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3), [AuraFlow](../api/pipelines/aura_flow) và [LTX](../api/pipelines/ltx_video). Mẫu hình tương tự cũng áp dụng cho các model video như [CogVideoX](../api/pipelines/cogvideox), [HunyuanVideo](../api/pipelines/hunyuan_video) và [Wan](../api/pipelines/wan). Các phương pháp PEFT ở cấp model sử dụng thuộc tính đó cùng với `prefix` tương ứng (`"unet"` hoặc `"transformer"`).

`pipeline.load_lora_weights` là cách được khuyến nghị để nạp trọng số LoRA vào denoiser (UNet hoặc transformer) và các text encoder. Xem [load_lora_weights()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.StableDiffusionLoraLoaderMixin.load_lora_weights) để biết các tham số chung. Nó có thể xử lý các trường hợp sau:

- checkpoint chia sẻ các khóa giữa denoiser và các text encoder
- checkpoint sử dụng các khóa denoiser và text-encoder riêng biệt

Phương thức [load_lora_adapter()](/docs/diffusers/main/vi/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.load_lora_adapter) nạp một bộ thích ứng LoRA ở cấp *mô hình* trên bất kỳ mô hình Diffusers nào kế thừa từ `PeftAdapterMixin`, chẳng hạn như UNet hoặc transformer. Nó xây dựng và chuẩn bị cấu hình bộ thích ứng, sau đó nạp trọng số vào module đó.

Sử dụng `prefix` để lọc các khóa state dict cho module đích (`"unet"` hoặc `"transformer"`). Mặc định là `"transformer"`, do đó Stable Diffusion và SDXL phải truyền `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) tăng tốc độ suy luận bằng cách biên dịch mô hình PyTorch để sử dụng các kernel được tối ưu hóa. Trước khi biên dịch, cần phải hợp nhất trọng số LoRA vào mô hình cơ sở và gỡ bỏ chúng trước.

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

Thông thường, hãy biên dịch denoiser vì đây là thành phần tiêu tốn nhiều tài nguyên tính toán nhất trong 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]
```

Đối với Flux và các pipeline DiT khác, hãy biên dịch `pipeline.transformer` thay vào đó.

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

Tham khảo phần [hotswapping](#hotswapping) để tìm hiểu cách tránh biên dịch lại khi làm việc với các mô hình đã biên dịch và nhiều LoRA.

## Thang đo trọng số

Sử dụng tham số `adapter_weights` trong [set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) để kiểm soát mức độ áp dụng của LoRA. Trọng số `0` tương đương với việc chỉ sử dụng trọng số của mô hình cơ sở, còn trọng số `1` tương đương với việc sử dụng hoàn toàn LoRA.

Truyền một giá trị vô hướng vào `adapter_weights` trong [set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) để kiểm soát mức độ mạnh của việc áp dụng 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` là mẫu chính, nhưng một số pipeline cũng chấp nhận `cross_attention_kwargs={"scale": 1.0}` trong lời gọi như một cách phụ để điều chỉnh attention. Các pipeline không sử dụng cross-attention thường phơi bày `attention_kwargs` thay thế (hoặc `joint_attention_kwargs` trên Flux và Stable Diffusion 3).

> [!WARNING]
> Phương thức [set_adapters()](/docs/diffusers/main/vi/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.set_adapters) chỉ điều chỉnh trọng số chú ý. Nếu một LoRA có ResNets hoặc bộ giảm mẫu và tăng mẫu, các thành phần này giữ giá trị tỷ lệ là `1.0`.

Truyền một từ điển để mở rộng từng khối text encoder hoặc denoiser. Các khóa trong từ điển tuân theo các module của pipeline. Ví dụ bên dưới là SDXL (`unet` cùng các text encoder). Flux sử dụng `transformer` và `text_encoder`. SD3 sử dụng `transformer` và nhiều text encoder.

Trong ví dụ SDXL này, khối `"down"` trong UNet được nhân với 0.9 và bạn có thể chỉ định thêm tỷ lệ cho các khối attention trong `"block_0"` và `"block_1"` dưới `"up"`. Nếu một khối như `"mid"` không được chỉ định, giá trị mặc định `1.0` sẽ được sử dụng.

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

### Lịch trình mở rộng

Việc điều chỉnh động thang đo LoRA trong quá trình lấy mẫu giúp bạn kiểm soát tốt hơn bố cục và tổng thể của hình ảnh, vì một số bước có thể được hưởng lợi nhiều hơn từ việc tăng hoặc giảm thang đo.

[character LoRA](https://huggingface.co/alvarobartt/ghibli-characters-flux-lora) trong ví dụ dưới đây bắt đầu với một scale cao hơn, sau đó giảm dần trong 20 bước đầu tiên để thiết lập việc tạo nhân vật. Ở các bước sau, chỉ áp dụng scale `0.2` để tránh thêm quá nhiều đặc trưng của LoRA vào các phần khác của hình ảnh mà LoRA không được huấn luyệ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]
```

## Hotswapping

Hotswapping LoRAs là một cách hiệu quả để làm việc với nhiều LoRA trong khi tránh việc tích lũy bộ nhớ từ nhiều lần gọi `load_lora_weights` và trong một số trường hợp, tránh việc biên dịch lại, nếu mô hình đã được biên dịch. Quy trình làm việc này yêu cầu một LoRA đã được nạp vì trọng số LoRA mới sẽ được thay thế tại chỗ cho LoRA hiện có đã được nạp.

```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]
> Chức năng Hotswapping không được hỗ trợ cho các LoRA nhắm vào text encoder.

Đặt `hotswap=True` trên `load_lora_weights` để thay thế LoRA thứ hai. Sử dụng tham số `adapter_name` để chỉ định LoRA cần thay thế. Nếu bạn bỏ qua `adapter_name` khi tải, Diffusers sẽ đặt tên cho các adapter là `default_0`, `default_1`, và tiếp tục như vậy. Các adapter có tên sẽ dễ nhắm đến một cách rõ ràng hơn.

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

### Các mô hình đã biên dịch

Đối với các mô hình đã biên dịch, hãy sử dụng [enable_lora_hotswap()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) để tránh việc biên dịch lại khi hotswap các LoRA. Phương thức này nên được gọi *trước* khi nạp LoRA đầu tiên và `torch.compile` nên được gọi *sau* khi nạp LoRA đầu tiên.

> [!TIP]
> Phương thức [enable_lora_hotswap()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) không phải lúc nào cũng cần thiết nếu LoRA thứ hai nhắm đến các rank và scales LoRA giống hệt với LoRA đầu tiên.

Trong [enable_lora_hotswap()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap), đặt `target_rank` bằng rank cao nhất trong số các adapter bạn dự định tải (mặc định là 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]
> Di chuyển mã của bạn vào trong trình quản lý ngữ cảnh `with torch._dynamo.config.patch(error_on_recompile=True)` để phát hiện xem mô hình có bị biên dịch lại hay không. Nếu mô hình vẫn bị biên dịch lại dù bạn đã thực hiện tất cả các bước ở trên, vui lòng mở một [issue](https://github.com/huggingface/diffusers/issues) kèm theo một ví dụ có thể tái hiện được.

Nếu bạn dự kiến độ phân giải thay đổi trong quá trình suy luận với tính năng này, hãy đảm bảo đặt `dynamic=True` khi biên dịch. Tham khảo [biên dịch hình dạng động](../optimization/fp16#dynamic-shape-compilation) để biết thêm chi tiết.

Vẫn còn một số kịch bản mà việc biên dịch lại là không thể tránh khỏi, chẳng hạn như khi LoRA được hotswap nhắm đến nhiều lớp hơn so với adapter ban đầu. Hãy cố gắng tải LoRA nhắm đến nhiều lớp nhất *trước tiên*. Để biết thêm chi tiết về hạn chế này, hãy tham khảo tài liệu [hotswapping](https://huggingface.co/docs/peft/main/en/package_reference/hotswap#peft.utils.hotswap.hotswap_adapter) của PEFT.

Tại sao `target_rank` và thứ tự nạp lại quan trọng

Phương thức [enable_lora_hotswap()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.enable_lora_hotswap) chuyển hệ số tỷ lệ LoRA từ float sang torch.tensors và đệm (pad) hình dạng của trọng số lên hình dạng lớn nhất cần thiết để tránh việc gán lại toàn bộ thuộc tính khi dữ liệu trong trọng số được thay thế.

Đây là lý do tại sao đối số `target_rank` lại quan trọng. Kết quả không thay đổi ngay cả khi các giá trị được đệm bằng số không. Tuy nhiên, quá trình tính toán có thể chậm hơn tùy thuộc vào kích thước đệm.

Vì không có thuộc tính LoRA mới nào được thêm vào, mỗi LoRA tiếp theo chỉ được phép nhắm đến cùng các lớp, hoặc một tập con của các lớp, mà LoRA đầu tiên nhắm đến. Việc chọn thứ tự nạp LoRA là quan trọng vì nếu các LoRA nhắm đến các lớp không giao nhau, bạn có thể kết thúc với việc tạo ra một LoRA giả nhắm đến tập hợp của tất cả các lớp đích.

Xem bài đăng trên blog [LoRA fast](https://huggingface.co/blog/lora-fast) để biết thêm về việc hotswap LoRA với các mô hình đã được biên dịch, và để xem chi tiết triển khai, hãy xem tệp [`hotswap.py`](https://github.com/huggingface/peft/blob/92d65cafa51c829484ad3d95cf71d09de57ff066/src/peft/utils/hotswap.py).

## Merge

Trọng số từ mỗi LoRA có thể được gộp lại để tạo ra sự pha trộn của nhiều phong cách hiện có. Có một số phương pháp để gộp LoRA, mỗi phương pháp khác nhau ở *cách* các trọng số được gộp (có thể ảnh hưởng đến chất lượng tạo ra).

### set_adapters[[merge]]

Phương thức [set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) kết hợp các LoRA bằng cách nối các ma trận có trọng số của chúng. Truyền tên các LoRA vào [set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) và sử dụng tham số `adapter_weights` để kiểm soát việc mở rộng của từng LoRA. Ví dụ, nếu `adapter_weights=[0.5, 0.5]`, kết quả đầu ra sẽ là trung bình của cả hai LoRA.

> [!TIP]
> Ưu tiên sử dụng `adapter_weights` trong [set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) để kiểm soát mức độ áp dụng của từng LoRA đã hợp nhất. Xem phần [Weight scale](#weight-scale) để biết thêm chi tiết.

```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]
> Đây là một phương pháp thử nghiệm và bạn có thể tham khảo [Model merging](https://huggingface.co/docs/peft/developer_guides/model_merging) của PEFT để biết thêm chi tiết. Hãy xem [issue](https://github.com/huggingface/diffusers/issues/6892) này nếu bạn quan tâm đến động lực và thiết kế đằng sau tích hợp này.

Phương thức [add_weighted_adapter](https://huggingface.co/docs/peft/main/en/package_reference/lora#peft.LoraModel.add_weighted_adapter) cho phép sử dụng các phương pháp gộp hiệu quả hơn như [TIES](https://huggingface.co/papers/2306.01708) hoặc [DARE](https://huggingface.co/papers/2311.03099). Các phương pháp gộp này loại bỏ các tham số dư thừa và có khả năng gây nhiễu trong các mô hình đã gộp. Lưu ý rằng các rank của LoRA cần có cùng rank để có thể gộp. Bài hướng dẫn bên dưới sử dụng UNet của SDXL.

Hãy đảm bảo rằng phiên bản ổn định mới nhất của Diffusers và PEFT đã được cài đặt.

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

Tải một UNet tương ứng với 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"
```

Tải một pipeline, truyền UNet vào nó và tải một 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"
)
```

Tạo một [PeftModel](https://huggingface.co/docs/peft/main/en/package_reference/peft_model#peft.PeftModel) từ checkpoint LoRA bằng cách kết hợp UNet đầu tiên bạn đã tải và LoRA UNet từ 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]
> Bạn có thể lưu và tái sử dụng `ikea_peft_model` bằng cách đẩy nó lên Hub như minh họa bên dưới.
> ```py
> ikea_peft_model.push_to_hub("ikea_peft_model", token=TOKEN)
> ```

Lặp lại quy trình này và tạo một [PeftModel](https://huggingface.co/docs/peft/main/en/package_reference/peft_model#peft.PeftModel) cho LoRA thứ hai.

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

Tải một mô hình UNet cơ sở và tải các adapter.

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

Gộp các LoRA bằng [add_weighted_adapter](https://huggingface.co/docs/peft/main/en/package_reference/lora#peft.LoraModel.add_weighted_adapter) và chỉ định cách bạn muốn gộp chúng bằng `combination_type`. Ví dụ bên dưới sử dụng phương pháp `"dare_linear"` (xem [bài đăng trên blog](https://huggingface.co/blog/peft_merging) này để tìm hiểu thêm về các phương pháp gộp này), phương pháp này sẽ cắt bỏ ngẫu nhiên một số trọng số và sau đó thực hiện tổng có trọng số của các tensor dựa trên trọng số được đặt cho từng LoRA trong `weights`.

Kích hoạt các LoRA đã hợp nhất bằng [set_adapters()](/docs/diffusers/main/vi/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

Phương thức [fuse_lora()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) hợp nhất trọng số LoRA trực tiếp với trọng số của bộ khử nhiễu gốc (UNet hoặc transformer) và bộ mã hóa văn bản của mô hình nền. Điều này làm giảm chi phí tải mô hình nền cho mỗi LoRA vì mô hình chỉ được tải một lần, từ đó giảm mức sử dụng bộ nhớ và tăng tốc độ suy luận.

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

Gọi [fuse_lora()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.fuse_lora) để hợp nhất chúng. Tham số `lora_scale` kiểm soát mức độ nhân kết quả với trọng số LoRA. Việc điều chỉnh này là quan trọng ngay bây giờ vì việc truyền `scale` vào `cross_attention_kwargs` sẽ không hoạt động trong pipeline.

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

Gỡ bỏ trọng số LoRA vì chúng đã được hợp nhất với mô hình nền. Lưu pipeline đã hợp nhất bằng cách sử dụng [save_pretrained()](/docs/diffusers/main/vi/api/pipelines/overview#diffusers.DiffusionPipeline.save_pretrained) để lưu cục bộ hoặc `~PushToHubMixin.push_to_hub` để lưu lên 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")
```

Pipeline đã được hợp nhất giờ có thể được tải nhanh chóng để suy luận mà không cần phải tải riêng từng 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]
```

Sử dụng [unfuse_lora()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unfuse_lora) để khôi phục trọng số của mô hình gốc, chẳng hạn khi bạn muốn sử dụng một giá trị `lora_scale` khác. Bạn chỉ có thể thực hiện unfuse nếu có đúng một LoRA đã được fuse. Ví dụ, thao tác này sẽ không hoạt động với pipeline ở trên vì có nhiều LoRA đã được fuse. Trong những trường hợp như vậy, bạn sẽ cần tải lại toàn bộ mô hình.

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

## Quản lý

Diffusers cung cấp một số phương pháp giúp bạn quản lý việc làm việc với LoRA. Các phương pháp này đặc biệt hữu ích nếu bạn đang làm việc với nhiều LoRA.

### set_adapters[[manage]]

[set_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.set_adapters) cũng kích hoạt LoRA hiện tại để sử dụng nếu có nhiều LoRA đang hoạt động. Điều này cho phép bạn chuyển đổi giữa các LoRA khác nhau bằng cách chỉ định tên của chúng.

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

Lưu một adapter bằng [save_lora_adapter()](/docs/diffusers/main/vi/api/loaders/peft#diffusers.loaders.PeftAdapterMixin.save_lora_adapter) trên cùng module mà bạn đã nạp vào (`pipeline.unet` hoặc `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

Phương thức [unload_lora_weights()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.unload_lora_weights) sẽ gỡ bỏ các trọng số LoRA trong pipeline để khôi phục các trọng số của mô hình gốc.

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

### disable_lora

Phương thức [disable_lora()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.disable_lora) tắt tất cả các LoRA (nhưng chúng vẫn được giữ trong pipeline) và khôi phục pipeline về trọng số mô hình gốc.

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

### get_active_adapters

Phương thức [get_active_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_active_adapters) trả về danh sách các LoRA đang hoạt động được gắn vào một pipeline.

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

### get_list_adapters

Phương thức [get_list_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.get_list_adapters) trả về tất cả các LoRA đã được nạp cho từng thành phần trong pipeline. Các khóa trong từ điển khớp với các module đã được nạp, chẳng hạn như `unet` hoặc `transformer` và bất kỳ text encoder nào.

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

### delete_adapters

Phương thức [delete_adapters()](/docs/diffusers/main/vi/api/loaders/lora#diffusers.loaders.lora_base.LoraBaseMixin.delete_adapters) xóa hoàn toàn một LoRA cùng các lớp của nó khỏi mô hình.

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

## Các bước tiếp theo

- Duyệt [LoRA Studio](https://lorastudio.co/models) để xem các LoRA khác nhau có thể sử dụng, hoặc bạn có thể tải lên Hub các LoRA yêu thích từ Civitai bằng Space bên dưới.

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

- Bạn có thể tìm thêm các LoRA khác trong các Space [FLUX LoRA the Explorer](https://huggingface.co/spaces/multimodalart/flux-lora-the-explorer) và [LoRA the Explorer](https://huggingface.co/spaces/multimodalart/LoraTheExplorer).

- Xem bài viết trên blog [Fast LoRA inference for Flux with Diffusers and PEFT](https://huggingface.co/blog/lora-fast) để tìm hiểu cách tối ưu hóa suy luận LoRA bằng các phương pháp như FlashAttention-3 và lượng tử hóa fp8.

