def create_encoder_config(args: argparse.Namespace,
                          max_seq_len_source: int,
                          max_seq_len_target: int,
                          config_conv: Optional[encoder.ConvolutionalEmbeddingConfig],
                          num_embed_source: int) -> Tuple[encoder.EncoderConfig, int]:
    """
    Create the encoder config.

    :param args: Arguments as returned by argparse.
    :param max_seq_len_source: Maximum source sequence length.
    :param max_seq_len_target: Maximum target sequence length.
    :param config_conv: The config for the convolutional encoder (optional).
    :param num_embed_source: The size of the source embedding.
    :return: The encoder config and the number of hidden units of the encoder.
    """
    encoder_num_layers, _ = args.num_layers
    config_encoder = None  # type: Optional[Config]

    if args.decoder_only:
        if args.encoder in (C.TRANSFORMER_TYPE, C.TRANSFORMER_WITH_CONV_EMBED_TYPE):
            encoder_num_hidden = args.transformer_model_size[0]
        elif args.encoder == C.CONVOLUTION_TYPE:
            encoder_num_hidden = args.cnn_num_hidden
        else:
            encoder_num_hidden = args.rnn_num_hidden
        config_encoder = encoder.EmptyEncoderConfig(num_embed=num_embed_source,
                                                    num_hidden=encoder_num_hidden)
    elif args.encoder in (C.TRANSFORMER_TYPE, C.TRANSFORMER_WITH_CONV_EMBED_TYPE):
        encoder_transformer_preprocess, _ = args.transformer_preprocess
        encoder_transformer_postprocess, _ = args.transformer_postprocess
        encoder_transformer_model_size = args.transformer_model_size[0]

        total_source_factor_size = sum(args.source_factors_num_embed)
        if args.source_factors_combine == C.SOURCE_FACTORS_COMBINE_CONCAT and total_source_factor_size > 0:
            logger.info("Encoder transformer-model-size adjusted to account for source factor embeddings: %d -> %d" % (
                encoder_transformer_model_size, num_embed_source + total_source_factor_size))
            encoder_transformer_model_size = num_embed_source + total_source_factor_size
        config_encoder = transformer.TransformerConfig(
            model_size=encoder_transformer_model_size,
            attention_heads=args.transformer_attention_heads[0],
            feed_forward_num_hidden=args.transformer_feed_forward_num_hidden[0],
            act_type=args.transformer_activation_type,
            num_layers=encoder_num_layers,
            dropout_attention=args.transformer_dropout_attention,
            dropout_act=args.transformer_dropout_act,
            dropout_prepost=args.transformer_dropout_prepost,
            positional_embedding_type=args.transformer_positional_embedding_type,
            preprocess_sequence=encoder_transformer_preprocess,
            postprocess_sequence=encoder_transformer_postprocess,
            max_seq_len_source=max_seq_len_source,
            max_seq_len_target=max_seq_len_target,
            conv_config=config_conv,
            lhuc=args.lhuc is not None and (C.LHUC_ENCODER in args.lhuc or C.LHUC_ALL in args.lhuc))
        encoder_num_hidden = encoder_transformer_model_size
    elif args.encoder == C.CONVOLUTION_TYPE:
        cnn_kernel_width_encoder, _ = args.cnn_kernel_width
        cnn_config = convolution.ConvolutionConfig(kernel_width=cnn_kernel_width_encoder,
                                                   num_hidden=args.cnn_num_hidden,
                                                   act_type=args.cnn_activation_type,
                                                   weight_normalization=args.weight_normalization)
        cnn_num_embed = num_embed_source
        if args.source_factors_combine == C.SOURCE_FACTORS_COMBINE_CONCAT:
            cnn_num_embed += sum(args.source_factors_num_embed)
        config_encoder = encoder.ConvolutionalEncoderConfig(num_embed=cnn_num_embed,
                                                            max_seq_len_source=max_seq_len_source,
                                                            cnn_config=cnn_config,
                                                            num_layers=encoder_num_layers,
                                                            positional_embedding_type=args.cnn_positional_embedding_type)

        encoder_num_hidden = args.cnn_num_hidden
    else:
        encoder_rnn_dropout_inputs, _ = args.rnn_dropout_inputs
        encoder_rnn_dropout_states, _ = args.rnn_dropout_states
        encoder_rnn_dropout_recurrent, _ = args.rnn_dropout_recurrent
        config_encoder = encoder.RecurrentEncoderConfig(
            rnn_config=rnn.RNNConfig(cell_type=args.rnn_cell_type,
                                     num_hidden=args.rnn_num_hidden,
                                     num_layers=encoder_num_layers,
                                     dropout_inputs=encoder_rnn_dropout_inputs,
                                     dropout_states=encoder_rnn_dropout_states,
                                     dropout_recurrent=encoder_rnn_dropout_recurrent,
                                     residual=args.rnn_residual_connections,
                                     first_residual_layer=args.rnn_first_residual_layer,
                                     forget_bias=args.rnn_forget_bias,
                                     lhuc=args.lhuc is not None and (C.LHUC_ENCODER in args.lhuc or C.LHUC_ALL in args.lhuc)),
            conv_config=config_conv,
            reverse_input=args.rnn_encoder_reverse_input)
        encoder_num_hidden = args.rnn_num_hidden

    return config_encoder, encoder_num_hidden
Create the encoder config.

    :param args: Arguments as returned by argparse.
    :param max_seq_len_source: Maximum source sequence length.
    :param max_seq_len_target: Maximum target sequence length.
    :param config_conv: The config for the convolutional encoder (optional).
    :param num_embed_source: The size of the source embedding.
    :return: The encoder config and the number of hidden units of the encoder.