code: def create_fusion_data_processors(
      config: DictConfig,
      model: nn.Module,
      requires_label: Optional[bool] = True,
      requires_data: Optional[bool] = True,
      advanced_hyperparameters: Optional[Dict] = None,
  ):
      """
      Create the data processors for late-fusion models. This function creates one processor for
      each modality of each model. For example, if one model config contains BERT, ViT, and CLIP, then
      BERT would have its own text processor, ViT would have its own image processor, and CLIP would have
      its own text and image processors. This is to support training arbitrary combinations of single-modal
      and multimodal models since two models may share the same modality but have different processing. Text
      sequence length is a good example. BERT's sequence length is generally 512, while CLIP uses sequences of
      length 77.
  
      Parameters
      ----------
      config
          A DictConfig object. The model config should be accessible by "config.model".
      model
          The model object.
  
      Returns
      -------
      A dictionary with modalities as the keys. Each modality has a list of processors.
      Note that "label" is also treated as a modality for convenience.
      """
      data_processors = {
          IMAGE: [],
          TEXT: [],
          CATEGORICAL: [],
          NUMERICAL: [],
          LABEL: [],
          ROIS: [],
          TEXT_NER: [],
          DOCUMENT: [],
          OVD: [],
          SEMANTIC_SEGMENTATION_IMG: [],
      }
  
      model_dict = {model.prefix: model}
  
      if model.prefix.lower().startswith("fusion"):
          for per_model in model.model:
              model_dict[per_model.prefix] = per_model
  
      assert sorted(list(model_dict.keys())) == sorted(
          config.model.names
      )
  
      for per_name, per_model in model_dict.items():
          model_config = getattr(config.model, per_model.prefix)
          if model_config.data_types is not None:
              data_types = model_config.data_types.copy()
          else:
              data_types = None
  
          if per_name == NER_TEXT:
              # create a multimodal processor for NER.
              data_processors[TEXT_NER].append(
                  create_data_processor(
                      data_type=TEXT_NER,
                      config=config,
                      model=per_model,
                  )
              )
              requires_label = False
              if data_types is not None and TEXT_NER in data_types:
                  data_types.remove(TEXT_NER)
          elif per_name.lower().startswith(MMLAB_MODELS):
              # create a multimodal processor for NER.
              data_processors[ROIS].append(
                  create_data_processor(
                      data_type=ROIS,
                      config=config,
                      model=per_model,
                  )
              )
              if data_types is not None and IMAGE in data_types:
                  data_types.remove(IMAGE)
          elif per_name == OVD:
              # create a multimodal processor for OVD.
              data_processors[OVD].append(
                  create_data_processor(
                      data_type=OVD,
                      config=config,
                      model=per_model,
                  )
              )
              if data_types is not None and IMAGE in data_types:
                  data_types.remove(IMAGE)
          elif per_name == SAM:
              data_processors[SEMANTIC_SEGMENTATION_IMG].append(
                  create_data_processor(
                      data_type=SEMANTIC_SEGMENTATION_IMG,
                      config=config,
                      model=per_model,
                  )
              )
              if (
                  data_types is not None
                  and SEMANTIC_SEGMENTATION_IMG in data_types
              ):
                  data_types.remove(SEMANTIC_SEGMENTATION_IMG)
              requires_label = False
  
          if requires_label:
              # each model has its own label processor
              label_processor = create_data_processor(
                  data_type=LABEL,
                  config=config,
                  model=per_model,
              )
              data_processors[LABEL].append(label_processor)
  
          if (
              requires_data and data_types and per_name != OVD
          ):  # currently OVD does not require additional processors
              for data_type in data_types:
                  per_data_processor = create_data_processor(
                      data_type=data_type,
                      model=per_model,
                      config=config,
                      advanced_hyperparameters=advanced_hyperparameters,
                  )
                  data_processors[data_type].append(per_data_processor)
  
      # Only keep the modalities with non-empty processors.
      data_processors = {
          k: v for k, v in data_processors.items() if len(v) > 0
      }
  
      if TEXT_NER in data_processors and LABEL in data_processors:
          # LabelProcessor is not needed for NER tasks as annotations are handled in NerProcessor.
          data_processors.pop(LABEL)
      return data_processors
  
imports: import copy
  import logging
  import os
  import warnings
  from typing import Dict, List, Optional, Tuple, Union
  import pandas
  from omegaconf import DictConfig, OmegaConf
  from torch import nn
  from autogluon.core.utils import default_holdout_frac, generate_train_test_split_combined
  from autogluon.core.utils.loaders import load_pd
  from ..constants import BINARY, CATEGORICAL, DEFAULT_SHOT, DOCUMENT, FEW_SHOT, IMAGE, IMAGE_PATH, LABEL, MMLAB_MODELS, MULTICLASS, NER, NER_ANNOTATION, NER_TEXT, NUMERICAL, OVD, REGRESSION, ROIS, SAM, SEMANTIC_SEGMENTATION_IMG, TEXT, TEXT_NER
  from ..data import CategoricalProcessor, DocumentProcessor, ImageProcessor, LabelProcessor, MixupModule, MMDetProcessor, MMOcrProcessor, MultiModalFeaturePreprocessor, NerLabelEncoder, NerProcessor, NumericalProcessor, OVDProcessor, SemanticSegImageProcessor, TextProcessor
  from ..data.infer_types import is_image_column
label_desc: Use image node_id 3 for calling a global function with example usage: create_fusion_data_processors(config, model, requires_label, requires_data, advanced_hyperparameters) and returns: data_processors