# SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project from collections.abc import Iterable from typing import TYPE_CHECKING, overload import torch import torch.nn as nn from transformers import PretrainedConfig from vllm.config.lora import LoRAConfig if TYPE_CHECKING: from vllm.lora.punica_wrapper import PunicaWrapperBase class BaseLayerWithLoRA(nn.Module): def __getattr__(self, name): d = self.__dict__ if name in d.get("_parameters", ()): return d["_parameters"][name] if name in d.get("_buffers", ()): return d["_buffers"][name] if name in d.get("_modules", ()): return d["_modules"][name] # Forward public misses to ``base_layer``; private names are framework # bookkeeping and must stay local. if not name.startswith("_"): base_layer = d.get("_modules", {}).get("base_layer") if base_layer is not None: return getattr(base_layer, name) raise AttributeError( f"{type(self).__name__!r} object has no attribute {name!r}" ) def load_weights( self, weights: Iterable[tuple[str, torch.Tensor]] ) -> Iterable[str]: """Load checkpoint weights into the wrapped base layer.""" base_load_weights = getattr(self.base_layer, "load_weights", None) if callable(base_load_weights): return base_load_weights(weights) from vllm.model_executor.models.utils import AutoWeightsLoader return AutoWeightsLoader(self.base_layer).load_weights(weights) @overload def slice_lora_a( self, lora_a: list[torch.Tensor | None] ) -> list[torch.Tensor | None]: ... @overload def slice_lora_a(self, lora_a: torch.Tensor) -> torch.Tensor: ... def slice_lora_a( self, lora_a: torch.Tensor | list[torch.Tensor | None] ) -> torch.Tensor | list[torch.Tensor | None]: """Slice lora a if splitting for tensor parallelism.""" ... @overload def slice_lora_b( self, lora_b: list[torch.Tensor | None] ) -> list[torch.Tensor | None]: ... @overload def slice_lora_b(self, lora_b: torch.Tensor) -> torch.Tensor: ... def slice_lora_b( self, lora_b: torch.Tensor | list[torch.Tensor | None] ) -> torch.Tensor | list[torch.Tensor | None]: """Slice lora b if splitting with tensor parallelism.""" ... def create_lora_weights( self, max_loras: int, lora_config: LoRAConfig, model_config: PretrainedConfig | None = None, ) -> None: """Initializes lora matrices.""" ... def reset_lora(self, index: int): """Resets the lora weights at index back to 0.""" ... def set_lora( self, index: int, lora_a: torch.Tensor | list[torch.Tensor], lora_b: torch.Tensor | list[torch.Tensor], ): """Overwrites lora tensors at index.""" ... def set_mapping( self, punica_wrapper, ): self.punica_wrapper: PunicaWrapperBase = punica_wrapper @classmethod def can_replace_layer( cls, source_layer: nn.Module, lora_config: LoRAConfig, packed_modules_list: list, model_config: PretrainedConfig | None = None, ) -> bool: """Returns True if the layer can be replaced by this LoRA layer.""" raise NotImplementedError