code: def _upgrade_encoder_decoder_params(
      feature: FeatureConfigDict, input_feature: bool
  ) -> FeatureConfigDict:
      """
      This function nests un-nested encoder/decoder parameters to conform with the new config structure for 0.6
      Args:
          feature (Dict): Feature to nest encoder/decoder params for.
          input_feature (Bool): Whether this feature is an input feature or not.
      """
      if TYPE not in feature:
          return feature
  
      try:
          if input_feature:
              module_type = ENCODER
              feature_cls = get_from_registry(
                  feature[TYPE], get_input_type_registry()
              )
          else:
              module_type = DECODER
              feature_cls = get_from_registry(
                  feature[TYPE], get_output_type_registry()
              )
      except ValueError:
          logging.exception(
              "Failed to obtain encoder / decoder from registry"
          )
          return feature
  
      feature_schema_cls = feature_cls.get_schema_cls()
      feature_keys = feature_schema_cls.get_valid_field_names()
  
      # These keys have been renamed from the form below to `fc_<key>` in the new config
      fc_layer_keys = [
          "fc_layers",
          "output_size",
          "use_bias",
          "weights_initializer",
          "bias_initializer",
          "norm",
          "norm_params",
          "activation",
          "dropout",
      ]
  
      module = feature.get(module_type, {})
  
      warn = False
      if isinstance(module, str):
          module = {TYPE: module}
          feature[module_type] = module
          warn = True
  
      nested_params = []
      for k, v in feature.items():
          if k not in feature_keys:
              module[k] = v
              if k in fc_layer_keys and module_type == DECODER:
                  module[f"fc_{k}"] = v
              nested_params.append(k)
              warn = True
  
      if module:
          if module_type in feature:
              feature[module_type].update(module)
          else:
              feature[module_type] = module
  
      for k in nested_params:
          del feature[k]
  
      if warn:
          warnings.warn(
              f"{module_type} specific parameters should now be nested within a dictionary under the '{module_type}' "
              f"parameter. Support for un-nested {module_type} specific parameters will be removed in v0.7",
              DeprecationWarning,
          )
      return feature
  
imports: import copy
  import logging
  import warnings
  from typing import Any, Callable, Dict, List, Union
  from ludwig.api_annotations import DeveloperAPI
  from ludwig.constants import AUDIO, BIAS, CLASS_WEIGHTS, COLUMN, CONV_BIAS, CONV_USE_BIAS, DECODER, DEFAULT_BIAS, DEFAULT_USE_BIAS, DEFAULTS, ENCODER, EVAL_BATCH_SIZE, EXECUTOR, FORCE_SPLIT, HEIGHT, HYPEROPT, IMAGE, INPUT_FEATURES, LOSS, MISSING_VALUE_STRATEGY, MODEL_ECD, MODEL_GBM, MODEL_TYPE, NAME, NUM_SAMPLES, NUMBER, OUTPUT_FEATURES, PARAMETERS, PREPROCESSING, PROBABILITIES, RANDOM, RAY, SAMPLER, SCHEDULER, SEARCH_ALG, SEQUENCE, SPLIT, SPLIT_PROBABILITIES, STRATIFY, TEXT, TIMESERIES, TRAINER, TRAINING, TYPE, USE_BIAS, WIDTH
  from ludwig.features.feature_registries import get_base_type_registry, get_input_type_registry, get_output_type_registry
  from ludwig.globals import LUDWIG_VERSION
  from ludwig.schema.defaults.gbm import GBMDefaultsConfig
  from ludwig.schema.encoders.utils import get_encoder_cls
  from ludwig.types import FeatureConfigDict, FeatureTypeDefaultsDict, HyperoptConfigDict, ModelConfigDict, PreprocessingConfigDict, TrainerConfigDict, TrainingSetMetadataDict
  from ludwig.utils.metric_utils import TrainerMetric
  from ludwig.utils.misc_utils import get_from_registry, merge_dict
  from ludwig.utils.version_transformation import VersionTransformation, VersionTransformationRegistry
label_desc: Use image node_id 14 for calling a global function with example usage: _upgrade_encoder_decoder_params(feature, input_feature) and returns: feature, feature, feature