class_docstr: Generic Adapter Mixin that can augment any torch.nn.Module with Adapter module support.
  
  This mixin class adds a hierarchical way to add any type of Adapter modules to a pre-existing module.
  Since Models are inherently also nn.Module, this mixin can be attached to any Model or Module.
  This mixin class adds several utility methods which are utilized or overridden as necessary.
  
  An Adapter module is any Pytorch nn.Module that possess a few properties :
  
      -   It's input and output dimension are the same, while the hidden dimension need not be the same.
      -   The final layer of the Adapter module is zero-initialized, so that the residual connection to the adapter
              yields the original output.
  
  This mixin adds the following instance variables to the class this inherits it:
  
      -   `adapter_layer`: A torch.nn.ModuleDict(), whose keys are the names of the adapter (globally unique),
              and values are the Adapter nn.Module().
      -   `adapter_cfg`: A OmegaConf DictConfig object that holds the config of the adapters that are initialized.
      -   `adapter_name`: A str resolved name which is unique key globally, but more than one modules may share
              this name.
      -   `adapter_global_cfg_key`: A str representing a key in the model config that can be provided by the user.
              The value resolves to `global_cfg`, and can be overridden via `model.cfg.adapters.global_cfg.*`.
      -   `adapter_metadata_cfg_key`: A str representing a key in the model config that is used to preserve the
              metadata of the adapter config.
  
  .. note::
  
      This module is **not** responsible for maintaining its config. Subclasses must ensure config is updated
      or preserved as needed. It is the responsibility of the subclasses to propagate the most up to date config to
      lower layers.
class_docstr_tok: ["Generic","Adapter","Mixin","that","can","augment","any","torch.nn.Module","with","Adapter","module","support",".","This","mixin","class","adds","a","hierarchical","way","to","add","any","type","of","Adapter","modules","to","a","pre-existing","module",".","Since","Models","are","inherently","also","nn.Module",",","this","mixin","can","be","attached","to","any","Model","or","Module",".","This","mixin","class","adds","several","utility","methods","which","are","utilized","or","overridden","as","necessary",".","An","Adapter","module","is","any","Pytorch","nn.Module","that","possess","a","few","properties",":","-","It","'s","input","and","output","dimension","are","the","same",",","while","the","hidden","dimension","need","not","be","the","same",".","-","The","final","layer","of","the","Adapter","module","is","zero-initialized",",","so","that","the","residual","connection","to","the","adapter","yields","the","original","output",".","This","mixin","adds","the","following","instance","variables","to","the","class","this","inherits","it",":","-","`","adapter_layer","`",":","A","torch.nn.ModuleDict","(",")",",","whose","keys","are","the","names","of","the","adapter","(","globally","unique",")",",","and","values","are","the","Adapter","nn.Module","(",")",".","-","`","adapter_cfg","`",":","A","OmegaConf","DictConfig","object","that","holds","the","config","of","the","adapters","that","are","initialized",".","-","`","adapter_name","`",":","A","str","resolved","name","which","is","unique","key","globally",",","but","more","than","one","modules","may","share","this","name",".","-","`","adapter_global_cfg_key","`",":","A","str","representing","a","key","in","the","model","config","that","can","be","provided","by","the","user",".","The","value","resolves","to","`","global_cfg","`",",","and","can","be","overridden","via","`","model.cfg.adapters.global_cfg.","*","`",".","-","`","adapter_metadata_cfg_key","`",":","A","str","representing","a","key","in","the","model","config","that","is","used","to","preserve","the","metadata","of","the","adapter","config",".","..","note",":",":","This","module","is","*","*","not","*","*","responsible","for","maintaining","its","config",".","Subclasses","must","ensure","config","is","updated","or","preserved","as","needed",".","It","is","the","responsibility","of","the","subclasses","to","propagate","the","most","up","to","date","config","to","lower","layers","."]
docstr: Add an Adapter module to this module.
  
  Args:
      name: A globally unique name for the adapter. Will be used to access, enable and disable adapters.
      cfg: A DictConfig or Dataclass that contains at the bare minimum `__target__` to instantiate a
          new Adapter module.
docstr_tok: ["Add","an","Adapter","module","to","this","module",".","Args",":","name",":","A","globally","unique","name","for","the","adapter",".","Will","be","used","to","access",",","enable","and","disable","adapters",".","cfg",":","A","DictConfig","or","Dataclass","that","contains","at","the","bare","minimum","`","__target__","`","to","instantiate","a","new","Adapter","module","."]
code: def add_adapter(
      self, name: str, cfg: Union[DictConfig, AdapterConfig], **kwargs
  ):
      """
      Add an Adapter module to this module.
  
      Args:
          name: A globally unique name for the adapter. Will be used to access, enable and disable adapters.
          cfg: A DictConfig or Dataclass that contains at the bare minimum `__target__` to instantiate a
              new Adapter module.
      """
      if not isinstance(cfg, DictConfig):
          cfg = DictConfig(cfg)
  
      adapter_types = self.get_accepted_adapter_types()
      _pass_types = False
      if len(adapter_types) > 0:
          test = model_utils.import_class_by_path(cfg._target_)
          for _type in adapter_types:
              # TODO: (@adithyare) should revisit if subclass is the best check...
              if issubclass(test, _type):
                  _pass_types = True
                  break
          if not _pass_types:
              raise ValueError(
                  f"Config: \n{OmegaConf.to_yaml(cfg)}\n"
                  f"It creates adapter class {test} \n"
                  f"that is not in the list of accepted adapter types.\n"
                  f"Accepted adapters: {[t for t in adapter_types]}"
              )
  
      # Convert to DictConfig from dict or Dataclass
      if is_dataclass(cfg):
          cfg = OmegaConf.structured(cfg)
  
      if not isinstance(cfg, DictConfig):
          cfg = DictConfig(cfg)
  
      # Add adapter_layer ModuleDict() if not present.
      if not hasattr(self, "adapter_layer"):
          self.adapter_layer = nn.ModuleDict()
  
      # Add adapter_cfg if it doesnt exist or hasnt been assigned yet.
      if not hasattr(self, "adapter_cfg"):
          self.adapter_cfg = OmegaConf.create({})
  
      # Resolve the module name and adapter name (if module name is provided)
      _, adapter_name = self.resolve_adapter_module_name_(name)
  
      # Add adapter_name to this module for later identification
      self.adapter_name = adapter_name
  
      # Assert that name is globally unique to all adapters.
      if adapter_name in self.adapter_layer:
          raise ValueError(
              f"Adapter with name `{name}` already exists ! Adapter names = {list(self.adapter_layer.keys())}"
          )
  
      # Assert that name is not `adapter_global_cfg_key`
      if adapter_name == self.adapter_global_cfg_key:
          raise ValueError(
              f"Adapters cannot have the reserved name : `{self.adapter_global_cfg_key}`"
          )
  
      # Update internal config and instantiate the Adapter module
      with open_dict(cfg), open_dict(self.adapter_cfg):
          adapter_enabled = cfg.pop("enabled", True)
          self.adapter_layer[adapter_name] = instantiate(cfg, **kwargs)
  
          cfg["enabled"] = adapter_enabled
          self.adapter_cfg[adapter_name] = cfg
  
imports: import inspect
  from abc import ABC
  from dataclasses import dataclass, is_dataclass
  from typing import List, Optional, Set, Tuple, Union
  import torch
  import torch.nn
  from hydra.utils import instantiate
  from omegaconf import DictConfig, OmegaConf, open_dict
  from nemo.utils import logging, model_utils
label_desc: Use image node_id 1 for calling the AdapterModuleMixin obj's underlying member method code with example usage: obj.add_adapter(name, cfg) without return types