code: def select_model(
      config: DictConfig,
      df_preprocessor: MultiModalFeaturePreprocessor,
      strict: Optional[bool] = True,
  ):
      """
      Filter model config through the detected modalities in the training data.
      If MultiModalFeaturePreprocessor can't detect some modality,
      this function will remove the models that use this modality. This function is to
      maximize the user flexibility in defining the config.
      For example, if one uses the default, including hf_text and timm_image, as the model config template
      but the training data don't have images, this function will filter out timm_image.
  
      Parameters
      ----------
      config
          A DictConfig object. The model config should be accessible by "config.model"
      df_preprocessor
          A MultiModalFeaturePreprocessor object, which has called .fit() on the training data.
          Column names of the same modality are grouped into one list. If a modality's list is empty,
          it means the training data don't have this modality.
      strict
          If False, allow retaining one model when partial modalities are available for that model.
  
      Returns
      -------
      Config with some unused models removed.
      """
      data_status = {}
      for per_modality in ALL_MODALITIES:
          data_status[per_modality] = False
      if len(df_preprocessor.image_feature_names) > 0:
          data_status[IMAGE] = True
      if len(df_preprocessor.text_feature_names) > 0:
          data_status[TEXT] = True
      if len(df_preprocessor.categorical_feature_names) > 0:
          data_status[CATEGORICAL] = True
      if len(df_preprocessor.numerical_feature_names) > 0:
          data_status[NUMERICAL] = True
      if len(df_preprocessor.ner_feature_names) > 0:
          data_status[TEXT_NER] = True
      if len(df_preprocessor.document_feature_names) > 0:
          data_status[DOCUMENT] = True
      if len(df_preprocessor.semantic_segmentation_feature_names) > 0:
          data_status[SEMANTIC_SEGMENTATION_IMG] = True
  
      names = config.model.names
      if isinstance(names, str):
          names = [names]
      selected_model_names = []
      fusion_model_name = []
      for model_name in names:
          model_config = getattr(config.model, model_name)
          strict = getattr(model_config, "requires_all_dtypes", strict)
          if not model_config.data_types:
              fusion_model_name.append(model_name)
              continue
          model_data_status = [
              data_status[d_type] for d_type in model_config.data_types
          ]
          if all(model_data_status):
              selected_model_names.append(model_name)
          else:
              if any(model_data_status) and not strict:
                  selected_model_names.append(model_name)
              else:
                  delattr(config.model, model_name)
  
      if len(selected_model_names) == 0:
          raise ValueError("No model is available for this dataset.")
      # only allow no more than 1 fusion model
      if len(fusion_model_name) > 1:
          raise ValueError(
              f"More than one fusion models `{fusion_model_name}` are detected, but only one is allowed."
          )
  
      if len(selected_model_names) > 1:
          assert len(fusion_model_name) == 1
          selected_model_names.extend(fusion_model_name)
      elif len(fusion_model_name) == 1 and hasattr(
          config.model, fusion_model_name[0]
      ):
          delattr(config.model, fusion_model_name[0])
  
      config.model.names = selected_model_names
      logger.debug(f"selected models: {selected_model_names}")
      for model_name in selected_model_names:
          logger.debug(
              f"model dtypes: {getattr(config.model, model_name).data_types}"
          )
  
      # clean up unused model configs
      model_keys = list(config.model.keys())
      for model_name in model_keys:
          if model_name not in selected_model_names + ["names"]:
              delattr(config.model, model_name)
  
      return config
  
file_path: autogluon/multimodal/src/autogluon/multimodal/utils/model.py
imports: import functools
  import json
  import logging
  import warnings
  from typing import Dict, List, Optional, Tuple, Union
  import timm
  from omegaconf import DictConfig, OmegaConf
  from torch import Tensor, nn
  from ..constants import ALL_MODALITIES, AUTOMM, CATEGORICAL, CATEGORICAL_MLP, CLIP, DOCUMENT, DOCUMENT_TRANSFORMER, FT_TRANSFORMER, FUSION_MLP, FUSION_NER, FUSION_TRANSFORMER, HF_TEXT, IMAGE, MMDET_IMAGE, MMOCR_TEXT_DET, MMOCR_TEXT_RECOG, NER, NER_TEXT, NUMERICAL, NUMERICAL_MLP, OVD, PEFT_ADDITIVE_STRATEGIES, SAM, SEMANTIC_SEGMENTATION_IMG, T_FEW, TEXT, TEXT_NER, TIMM_IMAGE, XYXY
  from ..data import MultiModalFeaturePreprocessor
  from ..models import CategoricalMLP, CLIPForImageText, DocumentTransformer, FT_Transformer, HFAutoModelForNER, HFAutoModelForTextPrediction, MMDetAutoModelForObjectDetection, MMOCRAutoModelForTextDetection, MMOCRAutoModelForTextRecognition, MultimodalFusionMLP, MultimodalFusionNER, MultimodalFusionTransformer, NumericalMLP, OVDModel, SAMForSemanticSegmentation, TFewModel, TimmAutoModelForImagePrediction
  from ..models.utils import inject_adaptation_to_linear_layer
label_desc: Use image node_id 1 for calling a global function with example usage: select_model(config, df_preprocessor, strict) and returns: config