code: def build_q_losses(
      policy: Policy, model, _, train_batch: SampleBatch
  ) -> TensorType:
      """Constructs the loss for DQNTorchPolicy.
  
      Args:
          policy: The Policy to calculate the loss for.
          model (ModelV2): The Model to calculate the loss for.
          train_batch: The training data.
  
      Returns:
          TensorType: A single loss tensor.
      """
  
      config = policy.config
      # Q-network evaluation.
      q_t, q_logits_t, q_probs_t, _ = compute_q_values(
          policy,
          model,
          {"obs": train_batch[SampleBatch.CUR_OBS]},
          explore=False,
          is_training=True,
      )
  
      # Target Q-network evaluation.
      q_tp1, q_logits_tp1, q_probs_tp1, _ = compute_q_values(
          policy,
          policy.target_models[model],
          {"obs": train_batch[SampleBatch.NEXT_OBS]},
          explore=False,
          is_training=True,
      )
  
      # Q scores for actions which we know were selected in the given state.
      one_hot_selection = F.one_hot(
          train_batch[SampleBatch.ACTIONS].long(), policy.action_space.n
      )
      q_t_selected = torch.sum(
          torch.where(
              q_t > FLOAT_MIN, q_t, torch.tensor(0.0, device=q_t.device)
          )
          * one_hot_selection,
          1,
      )
      q_logits_t_selected = torch.sum(
          q_logits_t * torch.unsqueeze(one_hot_selection, -1), 1
      )
  
      # compute estimate of best possible value starting from state at t + 1
      if config["double_q"]:
          (
              q_tp1_using_online_net,
              q_logits_tp1_using_online_net,
              q_dist_tp1_using_online_net,
              _,
          ) = compute_q_values(
              policy,
              model,
              {"obs": train_batch[SampleBatch.NEXT_OBS]},
              explore=False,
              is_training=True,
          )
          q_tp1_best_using_online_net = torch.argmax(
              q_tp1_using_online_net, 1
          )
          q_tp1_best_one_hot_selection = F.one_hot(
              q_tp1_best_using_online_net, policy.action_space.n
          )
          q_tp1_best = torch.sum(
              torch.where(
                  q_tp1 > FLOAT_MIN,
                  q_tp1,
                  torch.tensor(0.0, device=q_tp1.device),
              )
              * q_tp1_best_one_hot_selection,
              1,
          )
          q_probs_tp1_best = torch.sum(
              q_probs_tp1
              * torch.unsqueeze(q_tp1_best_one_hot_selection, -1),
              1,
          )
      else:
          q_tp1_best_one_hot_selection = F.one_hot(
              torch.argmax(q_tp1, 1), policy.action_space.n
          )
          q_tp1_best = torch.sum(
              torch.where(
                  q_tp1 > FLOAT_MIN,
                  q_tp1,
                  torch.tensor(0.0, device=q_tp1.device),
              )
              * q_tp1_best_one_hot_selection,
              1,
          )
          q_probs_tp1_best = torch.sum(
              q_probs_tp1
              * torch.unsqueeze(q_tp1_best_one_hot_selection, -1),
              1,
          )
  
      loss_fn = (
          huber_loss
          if policy.config["td_error_loss_fn"] == "huber"
          else l2_loss
      )
  
      q_loss = QLoss(
          q_t_selected,
          q_logits_t_selected,
          q_tp1_best,
          q_probs_tp1_best,
          train_batch[PRIO_WEIGHTS],
          train_batch[SampleBatch.REWARDS],
          train_batch[SampleBatch.TERMINATEDS].float(),
          config["gamma"],
          config["n_step"],
          config["num_atoms"],
          config["v_min"],
          config["v_max"],
          loss_fn,
      )
  
      # Store values for stats function in model (tower), such that for
      # multi-GPU, we do not override them during the parallel loss phase.
      model.tower_stats["td_error"] = q_loss.td_error
      # TD-error tensor in final stats
      # will be concatenated and retrieved for each individual batch item.
      model.tower_stats["q_loss"] = q_loss
  
      return q_loss.loss
  
imports: from typing import Dict, List, Tuple
  import gymnasium
  import ray
  from ray.rllib.algorithms.dqn.dqn_tf_policy import PRIO_WEIGHTS, Q_SCOPE, Q_TARGET_SCOPE, postprocess_nstep_and_prio
  from ray.rllib.algorithms.dqn.dqn_torch_model import DQNTorchModel
  from ray.rllib.models.catalog import ModelCatalog
  from ray.rllib.models.modelv2 import ModelV2
  from ray.rllib.models.torch.torch_action_dist import get_torch_categorical_class_with_temperature, TorchDistributionWrapper
  from ray.rllib.policy.policy import Policy
  from ray.rllib.policy.policy_template import build_policy_class
  from ray.rllib.policy.sample_batch import SampleBatch
  from ray.rllib.policy.torch_mixins import LearningRateSchedule, TargetNetworkMixin
  from ray.rllib.utils.error import UnsupportedSpaceException
  from ray.rllib.utils.exploration.parameter_noise import ParameterNoise
  from ray.rllib.utils.framework import try_import_torch
  from ray.rllib.utils.torch_utils import apply_grad_clipping, concat_multi_gpu_td_errors, FLOAT_MIN, huber_loss, l2_loss, reduce_mean_ignore_inf, softmax_cross_entropy_with_logits
  from ray.rllib.utils.typing import TensorType, AlgorithmConfigDict
label_desc: Use image node_id 3 for calling a global function with example usage: build_q_losses(policy, model, _, train_batch) and returns: q_loss