class_docstr: MegatronGPTLoRAModel is a model that combines a base model (GPTSFTModel) with a low-rank adapters.
  The lora adapters will be added in `nemo/collections/nlp/modules/common/megatron/attention.py`
  The implementation is based on Hu et al. nemo/collections/nlp/modules/common/megatron/attention.py
  
  A single low-rank feedfowrad layer is used in parallel with the KQV projection layer.
  TODO: Add support to also include an option to adda low-rank adapter in the output projection layer.
code: def __init__(
      self,
      cfg: DictConfig,
      trainer: Trainer,
  ):
      self.peft_name_keys = [
          AdapterName.LORA_KQV_ADAPTER,
      ]
      lora_cfg = cfg.peft.lora_tuning
      if cfg.get("kv_channels", None) is None:
          assert (
              cfg.hidden_size % cfg.num_attention_heads == 0
          ), "hidden_size must be divisible by num_attention_heads if kv_channels is None"
          kv_channels = cfg.hidden_size // cfg.num_attention_heads
      else:
          kv_channels = cfg.kv_channels
      projection_size = kv_channels * cfg.num_attention_heads
      num_query_groups = cfg.get("num_query_groups", None)
      if num_query_groups is None:
          num_query_groups = cfg.num_attention_heads
      qkv_projection_size = (
          projection_size + 2 * kv_channels * num_query_groups
      )
  
      adapter_cfg = LoraKQVAdapterConfig(
          in_features=cfg.hidden_size,
          out_features=qkv_projection_size,
          dim=lora_cfg.adapter_dim,
          norm_position=None,
          norm_type=None,
          activation="identity",
          column_init_method=lora_cfg.get(
              "column_init_method", "normal"
          ),
          row_init_method=lora_cfg.get("row_init_method", "zero"),
          gather_output=False,
          dropout=lora_cfg.adapter_dropout,
      )
  
      self.name_key_to_cfg = {}
      self.name_key_to_mcore_mixins = (
          {}
      )  # maps peft_key to a list of tuples (mcore_target, mcore_mixin)
      for k in self.peft_name_keys:
          self.name_key_to_cfg[k] = adapter_cfg
          self.name_key_to_mcore_mixins[k] = [
              ("self_attention", MCoreSelfAttentionMixin)
          ]
      self.layer_selection = lora_cfg.get("layer_selection", None)
      if self.layer_selection is None:
          self.layer_selection = list(range(1, cfg.num_layers + 1))
      super().__init__(cfg, trainer)
  
imports: from omegaconf.dictconfig import DictConfig
  from pytorch_lightning.trainer.trainer import Trainer
  from nemo.collections.nlp.models.language_modeling.megatron_gpt_sft_model import MegatronGPTSFTModel
  from nemo.collections.nlp.modules.common.megatron.adapters.mcore_mixins import MCoreGPTEmbeddingMixin, MCoreSelfAttentionMixin, MCoreTransformerLayerMixin, swap_mcore_mixin
  from nemo.collections.nlp.modules.common.megatron.adapters.parallel_adapters import AdapterName, InfusedAdapterConfig, LoraKQVAdapterConfig, LoraKQVAdapterWeightTyingConfig, MLPInfusedAdapterConfig, ParallelLinearAdapterConfig, ParallelLinearAdapterWeightTyingConfig, PromptEncoderAdapterConfig
  from nemo.core.classes.mixins import adapter_mixins
  from nemo.utils import logging, model_utils
  from nemo.utils.decorators import deprecated
label_desc: Use image node_id 1 to create a new MegatronGPTLoRAModel object from inherited base classes: MegatronGPTLayerwisePEFTModel with example: obj = MegatronGPTLoRAModel(cfg, trainer)