class_docstr: Does Bayesian optimization with Latent Context Embedding Additive (LCE-A) GP.
  The parameter space decomposition must be provided.
  
  Args:
      decomposition: Keys are context names. Values are the lists of parameter
          names belong to the context, e.g.
          {'context1': ['p1_c1', 'p2_c1'],'context2': ['p1_c2', 'p2_c2']}.
      gp_model_args: Dictionary of kwargs to pass to GP model training.
          - train_embedding: Boolen. If true, we will train context embedding;
          otherwise, we use pre-trained embeddings from embds_feature_dict only.
          Default is True.
code: def __init__(
      self,
      decomposition: Dict[str, List[str]],
      # pyre-fixme[24]: Generic type `dict` expects 2 type parameters, use
      #  `typing.Dict` to avoid runtime subscripting errors.
      cat_feature_dict: Optional[Dict] = None,
      # pyre-fixme[24]: Generic type `dict` expects 2 type parameters, use
      #  `typing.Dict` to avoid runtime subscripting errors.
      embs_feature_dict: Optional[Dict] = None,
      # pyre-fixme[24]: Generic type `dict` expects 2 type parameters, use
      #  `typing.Dict` to avoid runtime subscripting errors.
      context_weight_dict: Optional[Dict] = None,
      embs_dim_list: Optional[List[int]] = None,
      gp_model_args: Optional[Dict[str, Any]] = None,
  ) -> None:
      # add validation for input decomposition
      for param_list in list(decomposition.values()):
          assert len(param_list) == len(
              list(decomposition.values())[0]
          ), "Each Context should contain same number of parameters"
      self.decomposition = decomposition
      self.cat_feature_dict = cat_feature_dict
      self.embs_feature_dict = embs_feature_dict
      self.context_weight_dict = context_weight_dict
      self.embs_dim_list = embs_dim_list
      # pyre-fixme[4]: Attribute must be annotated.
      self.gp_model_args = (
          gp_model_args if gp_model_args is not None else {}
      )
      self.feature_names: List[str] = []
      # pyre-fixme[4]: Attribute must be annotated.
      self.train_embedding = self.gp_model_args.get(
          "train_embedding", True
      )
      super().__init__(
          model_constructor=self.get_and_fit_model,
          acqf_constructor=ei_or_nei,  # pyre-ignore
      )
  
imports: from logging import Logger
  from typing import Any, cast, Dict, List, Optional, Tuple, Union
  from ax.core.search_space import SearchSpaceDigest
  from ax.core.types import TCandidateMetadata
  from ax.models.torch.alebo import ei_or_nei
  from ax.models.torch.botorch import BotorchModel
  from ax.models.torch.cbo_sac import generate_model_space_decomposition
  from ax.models.torch_base import TorchModel, TorchOptConfig
  from ax.utils.common.docutils import copy_doc
  from ax.utils.common.logger import get_logger
  from botorch.fit import fit_gpytorch_mll
  from botorch.models.contextual import LCEAGP
  from botorch.models.gpytorch import GPyTorchModel
  from botorch.models.model_list_gp_regression import ModelListGP
  from botorch.utils.datasets import SupervisedDataset
  from gpytorch.mlls.exact_marginal_log_likelihood import ExactMarginalLogLikelihood
  from torch import Tensor
label_desc: Use image node_id 1 to create a new LCEABO object from inherited base classes: BotorchModel with example: obj = LCEABO(decomposition, cat_feature_dict, embs_feature_dict, context_weight_dict, embs_dim_list, gp_model_args)