code: def save_ludwig_model_for_inference(
      save_path: str,
      model: "BaseModel",
      config: ModelConfigDict,
      training_set_metadata: TrainingSetMetadataDict,
      device: Optional[TorchDevice] = None,
      model_only: bool = False,
  ) -> None:
      """Saves a LudwigModel (a BaseModel model, config, and training_set_metadata) for inference."""
      if device is None:
          logger.info(
              f'No device specified. Saving using device "{DEVICE}".'
          )
          device = DEVICE
  
      stage_to_filenames = {
          stage: get_filename_from_stage(stage, device)
          for stage in [PREPROCESSOR, PREDICTOR, POSTPROCESSOR]
      }
  
      stage_to_module = _init_inference_stages_from_ludwig_model(
          model, config, training_set_metadata, device, scripted=True
      )
      if model_only:
          stage_to_module[PREDICTOR].save(
              os.path.join(save_path, stage_to_filenames[PREDICTOR])
          )
      else:
          config_path = os.path.join(
              save_path, MODEL_HYPERPARAMETERS_FILE_NAME
          )
          if not os.path.exists(config_path):
              save_json(config_path, config)
              logger.info(f"Saved model config to {config_path}")
  
          training_set_metadata_path = os.path.join(
              save_path, TRAIN_SET_METADATA_FILE_NAME
          )
          if not os.path.exists(training_set_metadata_path):
              save_json(
                  training_set_metadata_path, training_set_metadata
              )
              logger.info(
                  f"Saved training set metadata to {training_set_metadata_path}"
              )
  
          for stage, module in stage_to_module.items():
              module.save(
                  os.path.join(save_path, stage_to_filenames[stage])
              )
              logger.info(
                  f"Saved torchscript module for {stage} to {stage_to_filenames[stage]}."
              )
  
imports: import logging
  import os
  from typing import Any, Dict, Optional, TYPE_CHECKING, Union
  import pandas
  import torch
  from torch import nn
  from ludwig.constants import NAME, POSTPROCESSOR, PREDICTOR, PREPROCESSOR, TYPE
  from ludwig.data.postprocessing import convert_dict_to_df
  from ludwig.data.preprocessing import load_metadata
  from ludwig.features.feature_registries import get_input_type_registry
  from ludwig.features.feature_utils import get_module_dict_key_from_name, get_name_from_module_dict_key
  from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME, TRAIN_SET_METADATA_FILE_NAME
  from ludwig.types import ModelConfigDict, TrainingSetMetadataDict
  from ludwig.utils import output_feature_utils
  from ludwig.utils.data_utils import load_json, save_json
  from ludwig.utils.inference_utils import get_filename_from_stage, to_inference_module_input_from_dataframe
  from ludwig.utils.misc_utils import get_from_registry
  from ludwig.utils.output_feature_utils import get_feature_name_from_concat_name, get_tensor_name_from_concat_name
  from ludwig.utils.torch_utils import DEVICE
  from ludwig.utils.types import TorchDevice, TorchscriptPreprocessingInput
label_desc: Use image node_id 1 for calling a global function with example usage: save_ludwig_model_for_inference(save_path, model, config, training_set_metadata, device, model_only) without return types