text: from ncc.models.ncc_model import NccEncoderDecoderModel
  from ncc.modules.embedding import Embedding
  from ncc.modules.code2vec.lstm_encoder import LSTMEncoder
  from ncc.modules.seq2seq.lstm_decoder import LSTMDecoder
  from ncc.models import register_model
  from ncc.utils import utils
  
  DEFAULT_MAX_SOURCE_POSITIONS = 1e5
  DEFAULT_MAX_TARGET_POSITIONS = 1e5
  
  from ncc.modules.code2vec.ncc_encoder import NccEncoder
  
  
  class NBOWEncoder(NccEncoder):
      """LSTM encoder."""
  
      def __init__(
          self, dictionary, embed_dim=512, hidden_size=512, num_layers=1,
          dropout_in=0.1, dropout_out=0.1, bidirectional=False,
          left_pad=True, pretrained_embed=None, padding_idx=None,
          max_source_positions=DEFAULT_MAX_SOURCE_POSITIONS
      ):
          super().__init__(dictionary)
          self.num_layers = num_layers
          self.dropout_in = dropout_in
          self.dropout_out = dropout_out
          self.bidirectional = bidirectional
          self.hidden_size = hidden_size
          self.max_source_positions = max_source_positions
  
          num_embeddings = len(dictionary)
          self.padding_idx = padding_idx if padding_idx is not None else dictionary.pad()
          if pretrained_embed is None:
              self.embed_tokens = Embedding(num_embeddings, embed_dim, self.padding_idx)
          else:
              self.embed_tokens = pretrained_embed
  
      def forward(self, src_tokens, src_lengths):
          # embed tokens
          x = self.embed_tokens(src_tokens)
          # x = F.dropout(x, p=self.dropout_out, training=self.training)
  
          # B x T x C -> T x B x C
          x = x.transpose(0, 1)
          encoder_padding_mask = src_tokens.eq(self.padding_idx).t()
          return {
              'encoder_out': (x,),
              'encoder_padding_mask': encoder_padding_mask if encoder_padding_mask.any() else None
          }
  
          # return {
          #     'encoder_out': (x, final_hiddens, final_cells),
          #     'encoder_padding_mask': encoder_padding_mask if encoder_padding_mask.any() else None
          # }
  
      def reorder_encoder_out(self, encoder_out, new_order):
          encoder_out['encoder_out'] = tuple(
              eo.index_select(1, new_order)
              for eo in encoder_out['encoder_out']
          )
          if encoder_out['encoder_padding_mask'] is not None:
              encoder_out['encoder_padding_mask'] = \
                  encoder_out['encoder_padding_mask'].index_select(1, new_order)
          return encoder_out
  
      def max_positions(self):
          """Maximum input length supported by the encoder."""
          return self.max_source_positions
  
  
  @register_model('debug')
  class DebugModel(NccEncoderDecoderModel):
      """
      A debug Model
      """
  
      def __init__(self, encoder, decoder):
          super().__init__(encoder, decoder)
  
      @classmethod
      def build_model(cls, args, config, task):
          """Build a new model instance."""
          # make sure that all args are properly defaulted (in case there are any new ones)
          # base_architecture(args)
          max_source_positions = args['model']['max_source_positions'] if args['model']['max_source_positions'] \
              else DEFAULT_MAX_SOURCE_POSITIONS
          max_target_positions = args['model']['max_target_positions'] if args['model']['max_target_positions'] \
              else DEFAULT_MAX_TARGET_POSITIONS
  
          def load_pretrained_embedding_from_file(embed_path, dictionary, embed_dim):
              num_embeddings = len(dictionary)
              padding_idx = dictionary.pad()
              embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx)
              embed_dict = utils.parse_embedding(embed_path)
              utils.print_embed_overlap(embed_dict, dictionary)
              return utils.load_embedding(embed_dict, dictionary, embed_tokens)
  
          if args['model']['encoder_embed']:
              pretrained_encoder_embed = load_pretrained_embedding_from_file(
                  args['model']['encoder_embed_path'], task.source_dictionary, args['model']['encoder_embed_dim'])
          else:
              num_embeddings = len(task.source_dictionary)
              pretrained_encoder_embed = Embedding(
                  num_embeddings, args['model']['encoder_embed_dim'], task.source_dictionary.pad()
              )
  
          if args['model']['share_all_embeddings']:
              # double check all parameters combinations are valid
              if task.source_dictionary != task.target_dictionary:
                  raise ValueError('--share-all-embeddings requires a joint dictionary')
              if args['model']['decoder_embed_path'] and (
                  args['model']['decoder_embed_path'] != args['model']['encoder_embed_path']):
                  raise ValueError(
                      '--share-all-embed not compatible with --decoder-embed-path'
                  )
              if args['model']['encoder_embed_dim'] != args['model']['decoder_embed_dim']:
                  raise ValueError(
                      '--share-all-embeddings requires --encoder-embed-dim to '
                      'match --decoder-embed-dim'
                  )
              pretrained_decoder_embed = pretrained_encoder_embed
              args['model']['share_decoder_input_output_embed'] = True
          else:
              # separate decoder input embeddings
              pretrained_decoder_embed = None
              if args['model']['decoder_embed']:
                  pretrained_decoder_embed = load_pretrained_embedding_from_file(
                      args['model']['decoder_embed'],
                      task.target_dictionary,
                      args['model']['decoder_embed_dim']
                  )
          # one last double check of parameter combinations
          if args['model']['share_decoder_input_output_embed'] and (
              args['model']['decoder_embed_dim'] != args['model']['decoder_out_embed_dim']):
              raise ValueError(
                  '--share-decoder-input-output-embeddings requires '
                  '--decoder-embed-dim to match --decoder-out-embed-dim'
              )
  
          if args['model']['encoder_freeze_embed']:
              pretrained_encoder_embed.weight.requires_grad = False
          if args['model']['decoder_freeze_embed']:
              pretrained_decoder_embed.weight.requires_grad = False
  
          encoder = NBOWEncoder(
              dictionary=task.source_dictionary,
              embed_dim=args['model']['encoder_embed_dim'],
              hidden_size=args['model']['encoder_hidden_size'],
              num_layers=args['model']['encoder_layers'],
              dropout_in=args['model']['encoder_dropout_in'],
              dropout_out=args['model']['encoder_dropout_out'],
              bidirectional=bool(args['model']['encoder_bidirectional']),
              left_pad=args['task']['left_pad_source'],
              pretrained_embed=pretrained_encoder_embed,
              max_source_positions=max_source_positions
          )
          decoder = LSTMDecoder(
              dictionary=task.target_dictionary,
              embed_dim=args['model']['decoder_embed_dim'],
              hidden_size=args['model']['decoder_hidden_size'],
              out_embed_dim=args['model']['decoder_out_embed_dim'],
              num_layers=args['model']['decoder_layers'],
              dropout_in=args['model']['decoder_dropout_in'],
              dropout_out=args['model']['decoder_dropout_out'],
              attention=args['model']['decoder_attention'],
              encoder_output_units=encoder.output_units,
              pretrained_embed=pretrained_decoder_embed,
              share_input_output_embed=args['model']['share_decoder_input_output_embed'],
              adaptive_softmax_cutoff=(
                  args['model']['adaptive_softmax_cutoff']
                  if args['criterion'] == 'adaptive_loss' else None
              ),
              max_target_positions=max_target_positions
          )
          return cls(encoder, decoder)
  