code: def __init__(
      self,
      config_obj: LLMModelConfig,
      random_seed=None,
      _device=None,
      **_kwargs,
  ):
      super().__init__(random_seed=random_seed)
  
      self.config_obj = config_obj
      self._random_seed = random_seed
  
      self.model_name = self.config_obj.base_model
      self.model_config = AutoConfig.from_pretrained(
          self.config_obj.base_model
      )
  
      self.model = load_pretrained_from_config(
          self.config_obj, model_config=self.model_config
      )
      self.curr_device = next(self.model.parameters()).device
      logger.info("Done.")
  
      self.context_len = get_context_len(self.model_config)
  
      # TODO(Arnav): This needs be more flexible to account for RoPE Scaling
      # When merging input IDs and target IDs for LLM fine-tuning, we want to make sure that the merged tensor is
      # not longer than the global maximum sequence length. This is provided in the preprocessing config. We never
      # want to exceed the maximum possible context length so we also check for that.
      if self.config_obj.preprocessing.global_max_sequence_length:
          global_max_sequence_length = (
              self.config_obj.preprocessing.global_max_sequence_length
          )
          self.global_max_sequence_length = (
              global_max_sequence_length
              if global_max_sequence_length <= self.context_len
              else self.context_len
          )
      else:
          self.global_max_sequence_length = self.context_len
  
      # Initialize tokenizer
      self.tokenizer = HFTokenizer(self.config_obj.base_model).tokenizer
  
      self._set_generation_config(self.config_obj.generation.to_dict())
  
      # ================ Inputs ================
      try:
          self.input_features.update(
              self.build_inputs(
                  input_feature_configs=self.config_obj.input_features
              )
          )
      except KeyError as e:
          raise KeyError(
              f"An input feature has a name that conflicts with a class attribute of torch's ModuleDict: {e}"
          ) from e
  
      # This is used to store the model inputs during the forward pass when fine-tuning LLMs. This allows us to have
      # access to the joint model inputs (input_ids and target_ids) when computing metrics. In particular, the target
      # ids are needed to correctly compute next token softmax cross entropy loss.
      self.model_inputs = None
  
      # ================ Outputs ================
      self.output_feature_type = self.config_obj.output_features[0].type
  
      self.output_features.update(
          self.build_outputs(
              output_feature_configs=self.config_obj.output_features,
              # Set the input size to the model vocab size instead of the tokenizer vocab size
              # because the model has additional "head" layers that are used to predict the next
              # token in the sequence. These head layers can add additional dimensions to the
              # logits tensor, beyond the vocab_size dimension.
              input_size=self.input_shape[-1]
              if self.output_feature_type == TEXT
              else self.model_config.vocab_size,
          )
      )
  
      # Extract the decoder object for the forward pass
      self._output_feature_decoder = ModuleWrapper(
          self.output_features.items()[0][1]
      )
  
      self.attention_masks = None
  
      clear_data_cache()
  
imports: import contextlib
  import logging
  import os
  from typing import Any, Dict, List, Optional, Tuple, Union
  import numpy
  import torch
  from transformers import AutoConfig, GenerationConfig
  from ludwig.accounting.used_tokens import get_used_tokens_for_llm
  from ludwig.constants import IGNORE_INDEX_TOKEN_ID, LOGITS, MODEL_LLM, PREDICTIONS, TEXT, USED_TOKENS
  from ludwig.features.base_feature import ModuleWrapper, OutputFeature
  from ludwig.features.feature_utils import LudwigFeatureDict
  from ludwig.features.text_feature import TextOutputFeature
  from ludwig.globals import MODEL_WEIGHTS_FILE_NAME
  from ludwig.models.base import BaseModel
  from ludwig.modules.training_hooks import NEFTuneHook
  from ludwig.schema.features.base import BaseOutputFeatureConfig, FeatureCollection
  from ludwig.schema.model_types.llm import LLMModelConfig
  from ludwig.utils.augmentation_utils import AugmentationPipelines
  from ludwig.utils.data_utils import clear_data_cache
  from ludwig.utils.llm_quantization_utils import convert_quantized_linear_to_linear
  from ludwig.utils.llm_utils import add_left_padding, generate_merged_ids, get_context_len, get_realigned_target_and_prediction_tensors_for_inference, initialize_adapter, load_pretrained_from_config, pad_target_tensor_for_fine_tuning, remove_left_padding, to_device
  from ludwig.utils.logging_utils import log_once
  from ludwig.utils.output_feature_utils import set_output_feature_tensor
  from ludwig.utils.tokenizers import HFTokenizer
  from ludwig.utils.torch_utils import reg_loss
label_desc: Use image node_id 2 to create a new LLM object from inherited base classes: BaseModel with example: obj = LLM(config_obj, random_seed, _device)