PEFT documentation

어댑터 핫스왑

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.21.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

어댑터 핫스왑

어댑터를 핫스왑하는 개념은 다음과 같습니다. 이미 여러 어댑터, 예를 들어 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

target_parameters를 통해 추가된 가중치, 즉 nn.Parameter를 직접 대상으로 하는 가중치를 핫스왑하려는 경우 재컴파일 및/또는 그래프 브레이크를 방지할 수 없음을 유의하세요. 따라서 컴파일된 모델과 핫스왑을 함께 사용할 때 target_parameters의 사용을 피하는 것이 권장됩니다.

더미 어댑터로 시작하기

어댑터 중 다른 어댑터가 필요한 모든 레이어를 대상으로 하는 것이 없다면, helpers.create_dummy_lora_config()를 사용하여 더미 어댑터를 준비하세요. 초기 기여도가 0이므로, 학습된 어댑터 가중치를 로드하기 전에 베이스 모델의 동작을 제공할 수 있습니다. 이 헬퍼는 구성만 검사하며, 베이스 모델이나 어댑터 가중치를 로드하지 않습니다.

import torch
from transformers import AutoModelForCausalLM
from peft import PeftConfig, get_peft_model
from peft.helpers import create_dummy_lora_config
from peft.utils.hotswap import hotswap_adapter, prepare_model_for_compiled_hotswap

adapter_paths = ["path-to-adapter0", "path-to-adapter1"]
configs = [PeftConfig.from_pretrained(path) for path in adapter_paths]
dummy_config = create_dummy_lora_config(configs)
print("New combined LoraConfig:")
print(dummy_config.to_dict())

base_model = AutoModelForCausalLM.from_pretrained(model_id).to(device)
model = get_peft_model(base_model, dummy_config).eval()
# Ranks are already large enough; preparation also makes scalings safe to change after compilation.
prepare_model_for_compiled_hotswap(model)
model = torch.compile(model)

with torch.inference_mode():
    base_output = model(**inputs)

for path in adapter_paths:
    hotswap_adapter(model, path, adapter_name="default", torch_device=device)
    with torch.inference_mode():
        adapted_output = model(**inputs)

더미 구성은 target_modules의 합집합과 모든 r 및 rank_pattern 값 중 최대값을 취합니다. 모든 어댑터를 커버하기 위해 exclude_modules, layers_to_transform, layers_pattern를 제거합니다. 이는 대상 레이어의 정확한 합집합보다 더 많은 어댑터 메모리를 예약할 수 있습니다. 수신되는 어댑터에 없는 모듈은 핫스왑 시 제로로 설정됩니다. 초기 추론 동안 더미 어댑터를 활성화된 상태로 유지하세요. 비활성화하면 포워드 경로가 변경되어 다시 활성화할 때 재컴파일을 트리거할 수 있습니다.

이 헬퍼는 비어 있지 않고 명시적으로 지정된 대상 모듈 목록 또는 집합을 요구합니다. 정규식 및 "all-linear"를 포함한 문자열 대상과 자동으로 추론된 대상은 지원되지 않습니다. 호환되는 hotswap 설정(일치하는 dropout, rsLoRA, alpha-pattern 설정 포함)과 함께 표준 LoRA 및 rsLoRA를 지원합니다. 변형(variants), 추가로 저장된 모듈, 학습된 bias/token, 직접 파라미터 대상, base weight를 변경하는 초기화는 거부됩니다. 모든 어댑터는 동일한 base weights를 사용해야 합니다. 구성 확인은 모델의 실제 레이어 유형을 검증할 수 없으며, 컴파일된 hotswapping의 기존 제한 사항이 여전히 적용됩니다. 그룹화 된 컨볼루션의 경우, 모델을 생성하기 전에 최대 랭크를 대상 그룹 수의 공배수로 증가시켜야 할 수 있습니다.

PEFT 체크아웃에서 다음을 사용하여 구성을 저장할 수도 있습니다:

python scripts/create-dummy-lora-for-hotswap.py path-to-adapter0 path-to-adapter1 --output-dir dummy-lora

Adapter 인수는 로컬 디렉터리 또는 Hugging Face Hub 저장소 ID를 받습니다. 기본 출력 디렉터리는 dummy-lora입니다. 이 스크립트는 어댑터 체크포인트가 아닌 adapter_config.json만 작성합니다. LoraConfig.from_pretrained("dummy-lora")로 로드한 후 get_peft_model에 전달하고, 위와 같이 모델을 준비하세요. PeftModel.from_pretrained는 어댑터 가중치가 없기 때문에 이 디렉터리를 로드할 수 없습니다. 더미 가중치도 필요하면 model.save_pretrained를 호출하세요.

주의 사항

Hotswapping은 Transformers 모델과 Diffusers 모델에서 작동합니다. 그러나 몇 가지 주의할 점이 있습니다:

  • 현재 LoRA만 제대로 지원됩니다.
  • 동일한 PEFT 방법에만 작동하므로, 예를 들어 LoRA와 LoHa를 서로 교체하는 것은 불가능합니다.
  • 교체되는 어댑터는 이전 어댑터와 동일한 레이어 또는 해당 레이어의 부분 집합을 대상으로 해야 합니다. 새로운 레이어를 대상으로 할 수 없습니다. 따라서 가능하면 가장 많은 레이어를 대상으로 하는 어댑터부터 시작하세요.
  • 가짜 LoRA 설정을 생성하려면 target_parameters가 문자열 목록이어야 하며, 정규식은 지원되지 않습니다. LoraConfig의 몇 가지 다른 파라미터도 지원되지 않으며, 이러한 파라미터가 발견되면 오류가 발생합니다. layers_to_transform와 layers_pattern를 사용하여 일부 레이어 인덱스만 대상으로 할 때, 가능한 가장 작은 오버랩을 찾으려는 시도는 하지 않고 대신 가짜 LoRA가 과잉 프로비저닝됩니다. exclude_modules를 통해 제외된 모듈에 대해서도 마찬가지입니다.

API

peft.utils.hotswap.hotswap_adapter

< >

( model: torch.nn.Modulemodel_name_or_path: stradapter_name: strtorch_device: Optional[str] = None**kwargs )

매개변수

  • model (~PeftModel) — 로드된 어댑터가 포함된 PEFT 모델입니다.
  • model_name_or_path (str) — 새 어댑터를 로드할 모델의 이름 또는 경로입니다.
  • adapter_name (str) — 교체할 어댑터의 이름, 예: "default". 교체 후에도 이름은 동일하게 유지됩니다.
  • torch_device — (str, 선택 사항, 기본값 None): 새 어댑터를 로드할 디바이스입니다.
  • **kwargs (optional) — 설정과 가중치를 로드하는 데 사용되는 추가 키워드 인자입니다.

기존 어댑터 데이터를 새 어댑터 데이터로 교체하되, 나머지는 그대로 유지합니다.

현재 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.Modulestate_dict: dict[str, torch.Tensor]adapter_name: strconfig: LoraConfigparameter_prefix: str = 'lora_' )

매개변수

  • model (nn.Module) — 로드된 어댑터가 포함된 모델입니다.
  • state_dict (dict[str, torch.Tensor]) — 새 어댑터의 state dict입니다. 동일한 모듈 등을 대상으로 하므로 호환되어야 합니다.
  • adapter_name (str) — 핫 스왑할 어댑터의 이름입니다. 예: "default". 스왑 후에도 이름은 동일하게 유지됩니다.
  • config (LoraConfig) — LoRA 어댑터의 설정입니다. 이는 어댑터의 스케일링과 랭크를 결정하는 데 사용됩니다.
  • parameter_prefix (str, 선택 사항, 기본값 "lora_") — state dict에서 어댑터의 키를 식별하는 데 사용되는 접두사입니다. LoRA의 경우 이는 "lora_"(기본값)입니다.

Raises

RuntimeError

  • RuntimeError — 기존 어댑터와 새 어댑터가 호환되지 않으면 RuntimeError가 발생합니다.

state_dict의 가중치로 모델의 어댑터 가중치를 교체합니다.

현재 LoRA만 지원됩니다.

이것은 어댑터가 호환성 검사를 마쳤고 state_dict가 PEFT와 함께 작동하도록 올바르게 매핑되었다고 가정하는 저수준 함수입니다. 이 작업을 대신 수행하는 고수준 함수를 사용하려면 hotswap_adapter를 사용하세요.

Update on GitHub