code: def test_add_adapter_with_invertible(self):
      model = self.get_model().base_model
      model.eval()
      if not isinstance(
          model, InvertibleAdaptersMixin
      ) and not isinstance(model, InvertibleAdaptersWrapperMixin):
          self.skipTest("Model does not support invertible adapters.")
  
      for adapter_config in [SeqBnInvConfig(), DoubleSeqBnInvConfig()]:
          with self.subTest(
              model_class=model.__class__.__name__,
              config=adapter_config.__class__.__name__,
          ):
              name = adapter_config.__class__.__name__
              model.add_adapter(name, config=adapter_config)
              model.set_active_adapters([name])
  
              # adapter is correctly added to config
              self.assertTrue(name in model.adapters_config)
              self.assertEqual(
                  adapter_config, model.adapters_config.get(name)
              )
  
              # invertible adapter is correctly added and returned
              self.assertTrue(name in model.invertible_adapters)
              self.assertEqual(
                  model.invertible_adapters[name],
                  model.get_invertible_adapter(),
              )
  
              # all invertible adapter weights should be activated for training
              for param in model.invertible_adapters[name].parameters():
                  self.assertTrue(param.requires_grad)
  
              # Set a hook before the invertible adapter to make sure it's actually called twice:
              # Once after the embedding layer and once in the prediction head.
              calls = 0
  
              def forward_pre_hook(module, input):
                  nonlocal calls
                  calls += 1
  
              model.get_invertible_adapter().register_forward_pre_hook(
                  forward_pre_hook
              )
  
              # check forward pass
              input_data = self.get_input_samples(config=model.config)
              model.to(torch_device)
              adapter_output = model(**input_data)
              # make sure the output is different without invertible adapter
              del model.invertible_adapters[name]
              self.assertFalse(name in model.invertible_adapters)
              adapter_output_no_inv = model(**input_data)
              self.assertEqual(
                  len(adapter_output), len(adapter_output_no_inv)
              )
              self.assertFalse(
                  torch.equal(
                      adapter_output[0], adapter_output_no_inv[0]
                  )
              )
              # We expect one call to invertible adapter
              self.assertEqual(1, calls)
  
imports: import copy
  import tempfile
  import torch
  import adapters
  from adapters import ADAPTER_CONFIG_MAP, ADAPTER_MODEL_MAPPING, AutoAdapterModel, BatchSplit, DoubleSeqBnConfig, DoubleSeqBnInvConfig, Fuse, InvertibleAdaptersMixin, InvertibleAdaptersWrapperMixin, MAMConfig, SeqBnConfig, SeqBnInvConfig
  from adapters.heads.language_modeling import CausalLMHead
  from transformers import MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING, CLIPConfig
  from transformers.testing_utils import require_torch, torch_device
  from .base import AdapterMethodBaseTestMixin, create_twin_models
label_desc: Use image node_id 5 for calling the BottleneckAdapterTestMixin obj's underlying member method code with example usage: obj.test_add_adapter_with_invertible() without return types