class_docstr: Adapter Mixin that can augment a ModelPT subclass with Adapter support.
  
  This mixin class should be used only with a top level ModelPT subclass.
  This mixin class adds several utility methods which should be subclassed and overriden to
  propagated to the submodules 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_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.*`.
  
  .. note::
  
      This module **is** responsible for maintaining its config. At the ModelPT level, it will access and
      write Adapter config information to `self.cfg.adapters`.
class_docstr_tok: ["Adapter","Mixin","that","can","augment","a","ModelPT","subclass","with","Adapter","support",".","This","mixin","class","should","be","used","only","with","a","top","level","ModelPT","subclass",".","This","mixin","class","adds","several","utility","methods","which","should","be","subclassed","and","overriden","to","propagated","to","the","submodules","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_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.","*","`",".","..","note",":",":","This","module","*","*","is","*","*","responsible","for","maintaining","its","config",".","At","the","ModelPT","level",",","it","will","access","and","write","Adapter","config","information","to","`","self.cfg.adapters","`","."]
docstr: Utility method that saves only the adapter module(s), and not the entire model itself.
  This allows the sharing of adapters which are often just a fraction of the size of the full model,
  enabling easier deliver.
  
  .. note::
  
      The saved file is a pytorch compatible pickle file, containing the state dicts of the adapter(s),
      as well as a binary representation of the adapter config.
  
  Args:
      filepath: A str filepath where the .pt file that will contain the adapter state dict.
      name: Optional name of the adapter that will be saved to this file. If None is passed,
          all adapters will be saved to the file. The name can be either the global name (adapter_name),
          or the module level name (module:adapter_name).
docstr_tok: ["Utility","method","that","saves","only","the","adapter","module","(","s",")",",","and","not","the","entire","model","itself",".","This","allows","the","sharing","of","adapters","which","are","often","just","a","fraction","of","the","size","of","the","full","model",",","enabling","easier","deliver",".","..","note",":",":","The","saved","file","is","a","pytorch","compatible","pickle","file",",","containing","the","state","dicts","of","the","adapter","(","s",")",",","as","well","as","a","binary","representation","of","the","adapter","config",".","Args",":","filepath",":","A","str","filepath","where","the",".pt","file","that","will","contain","the","adapter","state","dict",".","name",":","Optional","name","of","the","adapter","that","will","be","saved","to","this","file",".","If","None","is","passed",",","all","adapters","will","be","saved","to","the","file",".","The","name","can","be","either","the","global","name","(","adapter_name",")",",","or","the","module","level","name","(","module",":","adapter_name",")","."]
code: def save_adapters(self, filepath: str, name: str = None):
      """
      Utility method that saves only the adapter module(s), and not the entire model itself.
      This allows the sharing of adapters which are often just a fraction of the size of the full model,
      enabling easier deliver.
  
      .. note::
  
          The saved file is a pytorch compatible pickle file, containing the state dicts of the adapter(s),
          as well as a binary representation of the adapter config.
  
      Args:
          filepath: A str filepath where the .pt file that will contain the adapter state dict.
          name: Optional name of the adapter that will be saved to this file. If None is passed,
              all adapters will be saved to the file. The name can be either the global name (adapter_name),
              or the module level name (module:adapter_name).
      """
      if not hasattr(self, "cfg") or "adapters" not in self.cfg:
          raise AttributeError(
              "No adapters have been added to this model, so no adapters can be saved."
          )
  
      output_dict = {}
  
      # Normalize the name to a list of strings
      if isinstance(name, str):
          name = [name]
  
      if name is None:
          name = self.cfg.adapters.keys()
  
      # Assert that the config must be present to save and restore the adapters.
      if not hasattr(self.cfg, "adapters"):
          raise ValueError(
              "The model has no adapter config, therefore it cannot save any adapter. "
              "Please first add one or more adapters to generate the config."
          )
  
      # For each adapter name (either global adapter or module adapters)
      for adapter_name in name:
          if adapter_name != self.adapter_global_cfg_key:
              # Resolve the adapter name into its components
              (
                  module_name,
                  adapter_name,
              ) = self.resolve_adapter_module_name_(adapter_name)
  
              # Reconstruct a module adapter's original name. For global adapters, the '' is preserved.
              if module_name == "":
                  key = adapter_name
              else:
                  key = f"{module_name}:{adapter_name}"
              output_dict[key] = []
  
              # Search all modules with the following criterion -
              # It must be an implementation of AdapterModuleMixin.
              # It must have the attribute `adapter_name`.
              # It must match the adapter name provided by the user.
              for module in self.modules():
                  if isinstance(module, AdapterModuleMixin):
                      # If all match, extract the state dict into a list of state dicts.
                      # This is because one name can be shared within one model by multiple adapters bearing
                      # a common name. This can occur when the adapter is common to a module which has multiple
                      # layers and blocks, all of which require an adapter.
                      adapter_module = module.get_adapter_module(
                          adapter_name
                      )
                      if adapter_module is not None:
                          # If the module was found, then extract the entire adapter ModuleDict state_dict(),
                          # Then select only the parts of the state dict that correspond to the current adapter_name.
                          # This is done so that it preserves the relation ship of the module name : parameters
                          # inside of the state dict.
                          # It will be normalized in the corresponding `load_adapters()` call.
                          adapter_state_dict = (
                              module.adapter_layer.state_dict()
                          )
                          state_dict = {}
                          for k, v in adapter_state_dict.items():
                              if adapter_name in k:
                                  state_dict[k] = v
  
                          output_dict[key].append(state_dict)
  
      # Preserve the binary OmegaConf dictionary of the model's adapter config
      output_dict["__cfg__"] = self.cfg.adapters
  
      # Finally, save the adapter state dict(s).
      torch.save(output_dict, filepath)
  
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 7 for calling the AdapterModelPTMixin obj's underlying member method code with example usage: obj.save_adapters(filepath, name) without return types