class_docstr: Extension of the standard TFModelV2 for SAC.
  
  To customize, do one of the following:
  - sub-class SACTFModel and override one or more of its methods.
  - Use SAC's `q_model_config` and `policy_model` keys to tweak the default model
    behaviors (e.g. fcnet_hiddens, conv_filters, etc..).
  - Use SAC's `q_model_config->custom_model` and `policy_model->custom_model` keys
    to specify your own custom Q-model(s) and policy-models, which will be
    created within this SACTFModel (see `build_policy_model` and
    `build_q_model`.
  
  Note: It is not recommended to override the `forward` method for SAC. This
  would lead to shared weights (between policy and Q-nets), which will then
  not be optimized by either of the critic- or actor-optimizers!
  
  Data flow:
      `obs` -> forward() (should stay a noop method!) -> `model_out`
      `model_out` -> get_policy_output() -> pi(actions|obs)
      `model_out`, `actions` -> get_q_values() -> Q(s, a)
      `model_out`, `actions` -> get_twin_q_values() -> Q_twin(s, a)
docstr: Returns Q-values, given the output of self.__call__().
  
  This implements Q(s, a) -> [single Q-value] for the continuous case and
  Q(s) -> [Q-values for all actions] for the discrete case.
  
  Args:
      model_out: Feature outputs from the model layers
          (result of doing `self.__call__(obs)`).
      actions (Optional[TensorType]): Continuous action batch to return
          Q-values for. Shape: [BATCH_SIZE, action_dim]. If None
          (discrete action case), return Q-values for all actions.
  
  Returns:
      TensorType: Q-values tensor of shape [BATCH_SIZE, 1].
docstr_tok: ["Returns","Q-values",",","given","the","output","of","self.__call__","(",")",".","This","implements","Q","(","s",",","a",")","-",">","[","single","Q-value","]","for","the","continuous","case","and","Q","(","s",")","-",">","[","Q-values","for","all","actions","]","for","the","discrete","case",".","Args",":","model_out",":","Feature","outputs","from","the","model","layers","(","result","of","doing","`","self.__call__","(","obs",")","`",")",".","actions","(","Optional","[","TensorType","]",")",":","Continuous","action","batch","to","return","Q-values","for",".","Shape",":","[","BATCH_SIZE",",","action_dim","]",".","If","None","(","discrete","action","case",")",",","return","Q-values","for","all","actions",".","Returns",":","TensorType",":","Q-values","tensor","of","shape","[","BATCH_SIZE",",","1","]","."]
code: def get_q_values(
      self, model_out: TensorType, actions: Optional[TensorType] = None
  ) -> TensorType:
      """Returns Q-values, given the output of self.__call__().
  
      This implements Q(s, a) -> [single Q-value] for the continuous case and
      Q(s) -> [Q-values for all actions] for the discrete case.
  
      Args:
          model_out: Feature outputs from the model layers
              (result of doing `self.__call__(obs)`).
          actions (Optional[TensorType]): Continuous action batch to return
              Q-values for. Shape: [BATCH_SIZE, action_dim]. If None
              (discrete action case), return Q-values for all actions.
  
      Returns:
          TensorType: Q-values tensor of shape [BATCH_SIZE, 1].
      """
      return self._get_q_value(model_out, actions, self.q_net)
  
imports: import gymnasium
  from gymnasium.spaces import Box, Discrete
  import numpy
  import tree
  from typing import Dict, List, Optional
  from ray.rllib.models.catalog import ModelCatalog
  from ray.rllib.models.tf.tf_modelv2 import TFModelV2
  from ray.rllib.utils.annotations import override
  from ray.rllib.utils.framework import try_import_tf
  from ray.rllib.utils.spaces.simplex import Simplex
  from ray.rllib.utils.typing import ModelConfigDict, TensorType, TensorStructType
label_desc: Use image node_id 5 for calling the SACTFModel obj's underlying member method code with example usage: obj.get_q_values(model_out, actions) and returns: self