code: def set_hyperopt_defaults_(config: "ModelConfig"):
      """This function was migrated from defaults.py with the intention of setting some hyperopt defaults while the
      hyperopt section of the config object is not fully complete.
  
      Returns:
          None -> modifies trainer and hyperopt sections
      """
      if not config.hyperopt:
          return
  
      # Set default num_samples based on search space if not set by user
      if config.hyperopt.executor.num_samples is None:
          _contains_grid_search_params = (
              contains_grid_search_parameters(config.hyperopt.to_dict())
          )
          if _contains_grid_search_params:
              logger.info(
                  "Setting hyperopt num_samples to 1 to prevent duplicate trials from being run. Duplicate trials are"
                  " created when there are hyperopt parameters that use the `grid_search` search space.",
              )
              config.hyperopt.executor.num_samples = 1
          else:
              logger.info("Setting hyperopt num_samples to 10.")
              config.hyperopt.executor.num_samples = 10
  
      scheduler = config.hyperopt.executor.scheduler
      if scheduler.type == "fifo":
          # FIFO scheduler has no constraints
          return
  
      # Disable early stopping when using a scheduler. We achieve this by setting the parameter
      # to -1, which ensures the condition to apply early stopping is never met.
      early_stop = config.trainer.early_stop
      if early_stop is not None and early_stop != -1:
          warnings.warn(
              "Can't utilize `early_stop` while using a hyperopt scheduler. Setting early stop to -1."
          )
      config.trainer.early_stop = -1
  
      if isinstance(config.trainer, ECDTrainerConfig) and isinstance(
          scheduler, BaseHyperbandSchedulerConfig
      ):
          # TODO(travis): explore similar contraints for GBMs, which don't have epochs
          max_t = scheduler.max_t
          time_attr = scheduler.time_attr
          epochs = config.trainer.epochs
          if max_t is not None:
              if time_attr == "time_total_s":
                  if epochs is None:
                      # Continue training until time limit hit
                      config.trainer.epochs = sys.maxsize
                  # else continue training until either time or trainer epochs limit hit
              elif epochs is not None and epochs != max_t:
                  raise ValueError(
                      "Cannot set trainer `epochs` when using hyperopt scheduler w/different training_iteration `max_t`. "
                      "Unset one of these parameters in your config or make sure their values match."
                  )
              else:
                  # Run trainer until scheduler epochs limit hit
                  config.trainer.epochs = max_t
          elif epochs is not None:
              scheduler.max_t = epochs
  
imports: import copy
  import logging
  import sys
  import warnings
  from typing import Any, Dict, List, Mapping, Set, TYPE_CHECKING
  from marshmallow import ValidationError
  from transformers import AutoConfig
  from ludwig.api_annotations import DeveloperAPI
  from ludwig.constants import CATEGORY, COMBINED, DECODER, DEFAULTS, ENCODER, GRID_SEARCH, INPUT_FEATURES, LOSS, MODEL_ECD, MODEL_LLM, OUTPUT_FEATURES, PARAMETERS, PREPROCESSING, SEQUENCE, SPACE, TEXT, TYPE
  from ludwig.features.feature_utils import compute_feature_hash
  from ludwig.schema.features.utils import output_config_registry
  from ludwig.schema.hyperopt.scheduler import BaseHyperbandSchedulerConfig
  from ludwig.schema.llms.generation import LLMGenerationConfig
  from ludwig.schema.trainer import ECDTrainerConfig
  from ludwig.types import HyperoptConfigDict, ModelConfigDict
  from ludwig.utils.data_utils import get_sanitized_feature_name
  from ludwig.utils.llm_utils import get_context_len
label_desc: Use image node_id 8 for calling a global function with example usage: set_hyperopt_defaults_(config) without return types