code: def _get_model(
      X: Tensor,
      Y: Tensor,
      Yvar: Tensor,
      task_feature: Optional[int] = None,
      fidelity_features: Optional[List[int]] = None,
      use_input_warping: bool = False,
      covar_module: Optional[Kernel] = None,
      prior: Optional[Dict[str, Any]] = None,
      **kwargs: Any,
  ) -> GPyTorchModel:
      """Instantiate a model of type depending on the input data.
  
      Args:
          X: A `n x d` tensor of input features.
          Y: A `n x m` tensor of input observations.
          Yvar: A `n x m` tensor of input variances (NaN if unobserved).
          task_feature: The index of the column pertaining to the task feature
              (if present).
          fidelity_features: List of columns of X that are fidelity parameters.
          covar_module: Optional. A data kernel of GP model.
          prior: Optional[Dict]. A dictionary that contains the specification of
              GP model prior. Currently, the keys include:
              - covar_module_prior: prior on covariance matrix e.g.
                  {"lengthscale_prior": GammaPrior(3.0, 6.0)}.
              - type: type of prior on task covariance matrix e.g.`LKJCovariancePrior`.
              - sd_prior: A scalar prior over nonnegative numbers, which is used for the
                  default LKJCovariancePrior task_covar_prior.
              - eta: The eta parameter on the default LKJ task_covar_prior.
  
      Returns:
          A GPyTorchModel (unfitted).
      """
      Yvar = Yvar.clamp_min(MIN_OBSERVED_NOISE_LEVEL)
      is_nan = torch.isnan(Yvar)
      any_nan_Yvar = torch.any(is_nan)
      all_nan_Yvar = torch.all(is_nan)
      if any_nan_Yvar and not all_nan_Yvar:
          if task_feature:
              # TODO (jej): Replace with inferred noise before making perf judgements.
              Yvar[Yvar != Yvar] = MIN_OBSERVED_NOISE_LEVEL
          else:
              raise ValueError(
                  "Mix of known and unknown variances indicates valuation function "
                  "errors. Variances should all be specified, or none should be."
              )
      if use_input_warping:
          if Y.shape[-1] > 1 and X.ndim > 2:
              raise UnsupportedError(
                  "Input warping is not supported for batched multi output models."
              )
          warp_tf = get_warping_transform(
              d=X.shape[-1],
              task_feature=task_feature,
              batch_shape=X.shape[:-2],
          )
      else:
          warp_tf = None
      if fidelity_features is None:
          fidelity_features = []
      if len(fidelity_features) == 0:
          # only pass linear_truncated arg if there are fidelities
          kwargs = {
              k: v for k, v in kwargs.items() if k != "linear_truncated"
          }
      # construct kernel based on customized prior if covar_module is None
      prior_dict = prior or {}
      covar_module_prior_dict = prior_dict.pop(
          "covar_module_prior", None
      )
      if (covar_module_prior_dict is not None) and (
          covar_module is None
      ):
          covar_module = _get_customized_covar_module(
              covar_module_prior_dict=covar_module_prior_dict,
              ard_num_dims=X.shape[-1],
              aug_batch_shape=_get_aug_batch_shape(X, Y),
              task_feature=task_feature,
          )
  
      if len(fidelity_features) > 0:
          if task_feature:
              raise NotImplementedError(
                  "multi-task multi-fidelity models not yet available"
              )
          # at this point we can assume that there is only a single fidelity parameter
          gp = SingleTaskMultiFidelityGP(
              train_X=X,
              train_Y=Y,
              data_fidelity=fidelity_features[0],
              input_transform=warp_tf,
              **kwargs,
          )
      elif task_feature is None:
          gp = SingleTaskGP(
              train_X=X,
              train_Y=Y,
              train_Yvar=None if all_nan_Yvar else Yvar,
              covar_module=covar_module,
              input_transform=warp_tf,
              **kwargs,
          )
      else:
          # instantiate multitask GP
          all_tasks, _, _ = MultiTaskGP.get_all_tasks(X, task_feature)
          num_tasks = len(all_tasks)
          task_covar_prior = None
          if len(prior_dict) > 0:
              prior_type = prior_dict.get("type", None)
              if issubclass(prior_type, LKJCovariancePrior):
                  sd_prior = prior_dict.get(
                      "sd_prior", GammaPrior(1.0, 0.15)
                  )
                  sd_prior._event_shape = torch.Size([num_tasks])
                  eta = prior_dict.get("eta", 0.5)
                  if not isinstance(eta, float) and not isinstance(
                      eta, int
                  ):
                      raise ValueError(
                          f"eta must be a real number, your eta was {eta}"
                      )
                  task_covar_prior = LKJCovariancePrior(
                      num_tasks, eta, sd_prior
                  )
  
              else:
                  raise NotImplementedError(
                      "Currently only LKJ prior is supported,"
                      f"your prior type was {prior_type}."
                  )
  
          gp = MultiTaskGP(
              train_X=X,
              train_Y=Y,
              train_Yvar=None if all_nan_Yvar else Yvar,
              task_feature=task_feature,
              covar_module=covar_module,
              rank=kwargs.get("rank"),
              task_covar_prior=task_covar_prior,
              input_transform=warp_tf,
          )
      return gp
  
imports: import functools
  from copy import deepcopy
  from random import randint
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Type, Union
  import torch
  from ax.models.model_utils import best_observed_point, get_observed
  from ax.models.torch.utils import _to_inequality_constraints
  from ax.models.torch_base import TorchModel
  from ax.models.types import TConfig
  from botorch.acquisition import get_acquisition_function
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.fixed_feature import FixedFeatureAcquisitionFunction
  from botorch.acquisition.objective import ConstrainedMCObjective, GenericMCObjective
  from botorch.acquisition.utils import get_infeasible_cost
  from botorch.exceptions.errors import UnsupportedError
  from botorch.fit import fit_gpytorch_mll
  from botorch.models.gp_regression import SingleTaskGP
  from botorch.models.gp_regression_fidelity import SingleTaskMultiFidelityGP
  from botorch.models.gpytorch import GPyTorchModel
  from botorch.models.model import Model
  from botorch.models.model_list_gp_regression import ModelListGP
  from botorch.models.multitask import MultiTaskGP
  from botorch.models.transforms.input import Warp
  from botorch.optim.optimize import optimize_acqf
  from botorch.utils import get_objective_weights_transform, get_outcome_constraint_transforms
  from botorch.utils.multi_objective.scalarization import get_chebyshev_scalarization
  from botorch.utils.transforms import is_ensemble
  from gpytorch.kernels import MaternKernel, ScaleKernel
  from gpytorch.kernels.kernel import Kernel
  from gpytorch.mlls.exact_marginal_log_likelihood import ExactMarginalLogLikelihood
  from gpytorch.mlls.leave_one_out_pseudo_likelihood import LeaveOneOutPseudoLikelihood
  from gpytorch.mlls.sum_marginal_log_likelihood import SumMarginalLogLikelihood
  from gpytorch.priors import Prior
  from gpytorch.priors.lkj_prior import LKJCovariancePrior
  from gpytorch.priors.torch_priors import GammaPrior, LogNormalPrior
  from torch import Tensor
label_desc: Use image node_id 12 for calling a global function with example usage: _get_model(X, Y, Yvar, task_feature, fidelity_features, use_input_warping, covar_module, prior) and returns: gp