code: def add_aggregate_noise(
      clipped_grads: list[tf.Tensor],
      batch_size: tf.Tensor,
      l2_norm_clip: float,
      noise_multiplier: float,
      loss_reduction: Optional[Literal["mean", "sum"]] = None,
      loss_model: Optional[tf.keras.Model] = None,
  ) -> Sequence[tf.Tensor]:
      """Adds noise to a collection of clipped gradients.
  
      The magnitude of the noise depends on the aggregation strategy of the
      input model's loss function.
  
      Args:
        clipped_grads: A list of `tf.Tensor`s representing the clipped gradients.
        batch_size: The batch size. Used for normalizing the noise when
          `loss_reduction` is 'sum'.
        l2_norm_clip: Clipping norm (max L2 norm of each gradient).
        noise_multiplier: Ratio of the standard deviation to the clipping norm.
        loss_reduction: An string description of how the loss is reduced over
          examples. Currently supports 'mean' and 'sum'. If `None`, then the
          aggregation type must be inferred from `input_model.loss`.
        loss_model: An optional `tf.keras.Model` used to infer the loss reduction
          strategy from if `loss_reduction` is `None`.
  
      Returns:
        A list of tensors containing the clipped gradients, but with the right
        amount of Gaussian noise added to them (depending on the reduction
        strategy of the loss function).
  
      Raises:
        ValueError: If both `loss_model` and `loss_reduction` are `None` or if
          they are both not `None`.
      """
      if loss_reduction is None and loss_model is None:
          raise ValueError(
              "Exactly one of `loss_reduction` and `loss_model` must be populated."
              " Instead, both arguments were `None`."
          )
      if loss_reduction is not None and loss_model is not None:
          raise ValueError(
              "Exactly one of `loss_reduction` and `loss_model` must be populated."
              " Instead, both arguments were not `None`."
          )
  
      if loss_reduction is None and loss_model is not None:
          implicit_mean_reductions = [
              tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE,
              tf.keras.losses.Reduction.AUTO,
          ]
          model_reduction = loss_model.loss.reduction
          loss_reduction = (
              "mean"
              if model_reduction in implicit_mean_reductions
              else "sum"
          )
          if model_reduction == tf.keras.losses.Reduction.AUTO:
              logging.info(
                  "Assuming that the model loss reduction is `SUM_OVER_BATCH_SIZE`."
              )
  
      scale = l2_norm_clip
      if loss_reduction == "mean":
          scale /= tf.cast(batch_size, tf.float32)
  
      def add_noise(g):
          return g + tf.random.normal(
              tf.shape(g), mean=0.0, stddev=noise_multiplier * scale
          )
  
      return tf.nest.map_structure(add_noise, clipped_grads)
  
file_path: privacy/tensorflow_privacy/privacy/fast_gradient_clipping/gradient_clipping_utils.py
imports: from collections.abc import Sequence, Set
  from typing import Any, Literal, Optional
  from absl import logging
  import tensorflow
  from tensorflow_privacy.privacy.fast_gradient_clipping import layer_registry
  from tensorflow_privacy.privacy.fast_gradient_clipping import type_aliases
label_desc: Use image node_id 4 for calling a global function with example usage: add_aggregate_noise(clipped_grads, batch_size, l2_norm_clip, noise_multiplier, loss_reduction, loss_model) and returns: tf, unknown