PEFT 文档

热插拔适配器

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

热插拔适配器

热插拔适配器的想法如下:我们可以同时加载多个适配器,例如两个 LoRA。但有时,我们想要加载一个 LoRA,然后将其权重就地替换为另一个适配器的 LoRA 权重。现在可以通过 hotswap_adapter 函数实现。

一般来说,这应该比删除一个适配器并在其位置加载适配器更快,后者是在不进行热插拔的情况下实现相同最终结果的方法。热插拔的另一个优点是,如果 PEFT 模型已经使用 torch.compile 编译,它可以防止重新编译。这可以节省大量时间。

不使用 torch.compile 的示例

import torch
from transformers import AutoModelForCausalLM
from peft import PeftModel
from peft.utils.hotswap import hotswap_adapter

model_id = ...
inputs = ...
device = ...
model = AutoModelForCausalLM.from_pretrained(model_id).to(device)

# load lora 0
model = PeftModel.from_pretrained(model, <path-adapter-0>)
with torch.inference_mode():
    output_adapter_0 = model(inputs)

# replace the "default" lora adapter with the new one
hotswap_adapter(model, <path-adapter-1>, adapter_name="default", torch_device=device)
with torch.inference_mode():
    output_adapter_1 = model(inputs).logits

使用 torch.compile 的示例

import torch
from transformers import AutoModelForCausalLM
from peft import PeftModel
from peft.utils.hotswap import hotswap_adapter, prepare_model_for_compiled_hotswap

model_id = ...
inputs = ...
device = ...
max_rank = ...  # maximum rank among all LoRA adapters that will be used
model = AutoModelForCausalLM.from_pretrained(model_id).to(device)

# load lora 0
model = PeftModel.from_pretrained(model, <path-adapter-0>)
# Prepare the model to allow hotswapping even if ranks/scalings of 2nd adapter differ.
# You can skip this step if all ranks and scalings are identical.
prepare_model_for_compiled_hotswap(model, target_rank=max_rank)
model = torch.compile(model)
with torch.inference_mode():
    output_adapter_0 = model(inputs)

# replace the "default" lora adapter with the new one
hotswap_adapter(model, <path-adapter-1>, adapter_name="default", torch_device=device)
with torch.inference_mode():
    output_adapter_1 = model(inputs).logits

注意事项

热插拔适用于 transformers 模型和 diffusers 模型。但是,有一些注意事项

  • 目前,仅正确支持 LoRA。
  • 它仅适用于相同的 PEFT 方法,因此例如不能交换 LoRA 和 LoHa。
  • 正在换入的适配器必须以与先前适配器相同的层或这些层的子集为目标。它不能以新层为目标。因此,如果可能,请从以最多层为目标的适配器开始。

peft.utils.hotswap.hotswap_adapter

< >

( model model_name_or_path adapter_name torch_device = None **kwargs )

参数

  • model (~PeftModel) — 带有已加载适配器的 PEFT 模型。
  • model_name_or_path (str) — 要从中加载新适配器的模型名称或路径。
  • adapter_name (str) — 要交换的适配器的名称,例如 "default"。交换后名称将保持不变。
  • torch_device — (str, 可选,默认为 None): 要将新适配器加载到的设备。
  • **kwargs (可选) — 用于加载配置和权重的其他关键字参数。

用新的适配器数据替换旧的适配器数据,其余部分保持不变。

截至目前,仅支持 LoRA。

当您想要用新适配器替换已加载的适配器时,此函数非常有用。适配器名称将保持不变,但权重和其他参数将被交换出去。

如果适配器不兼容,例如目标层不同或 alpha 值不同,则会引发错误。

示例

>>> import torch
>>> from transformers import AutoModelForCausalLM
>>> from peft import PeftModel
>>> from peft.utils.hotswap import hotswap_adapter

>>> model_id = ...
>>> inputs = ...
>>> device = ...
>>> model = AutoModelForCausalLM.from_pretrained(model_id).to(device)

>>> # load lora 0
>>> model = PeftModel.from_pretrained(model, "path-adapter-0")
>>> model = torch.compile(model)  # optionally compile the model
>>> with torch.inference_mode():
...     output_adapter_0 = model(inputs)

>>> # replace the "default" lora adapter with the new one
>>> hotswap_adapter(model, "path-adapter-1", adapter_name="default", torch_device=device)
>>> with torch.inference_mode():
...     output_adapter_1 = model(inputs).logits

peft.utils.hotswap.hotswap_adapter_from_state_dict

< >

( model: torch.nn.Module state_dict: dict[str, torch.Tensor] adapter_name: str config: LoraConfig parameter_prefix: str = 'lora_' )

参数

  • model (nn.Module) — 带有已加载适配器的模型。
  • state_dict (dict[str, torch.Tensor]) — 新适配器的状态字典,需要兼容(目标模块等)。
  • adapter_name (str) — 应该热插拔的适配器的名称,例如 "default"。交换后名称将保持不变。
  • config (LoraConfig) — LoRA 适配器的配置。这用于确定适配器的缩放比例和秩。
  • parameter_prefix (str, 可选,默认为 "lora_") — 用于标识状态字典中适配器键的前缀。对于 LoRA,这将是 "lora_"(默认值)。

引发

RuntimeError

  • RuntimeError — 如果旧适配器和新适配器不兼容,则会引发 RuntimeError。

使用 state_dict 中的权重替换模型中的适配器权重。

截至目前,仅支持 LoRA。

这是一个底层函数,它假定适配器已经检查过兼容性,并且 state_dict 已被正确映射以与 PEFT 一起使用。对于为您执行此操作的高级函数,请改用 hotswap_adapter

< > 在 GitHub 上更新