def METHOD_NAME(self) -> Dict[str, np.ndarray]:
    """
    Updates model using buffer.
    :param max_batches: The maximum number of batches to use per update.
    :return: The loss of the update.
    """
    # Don't continue training if the learning rate has reached 0, to reduce training time.
    decay_lr = self.decay_learning_rate.get_value(self.policy.get_current_step())
    if self.current_lr <= 1e-10:  # Unlike in TF, this never actually reaches 0.
        return {"Losses/Pretraining Loss": 0}
    batch_losses = []
    possible_demo_batches = (
        self.demonstration_buffer.num_experiences // self.n_sequences
    )
    possible_batches = possible_demo_batches
    max_batches = self.samples_per_update // self.n_sequences
    n_epoch = self.num_epoch
    for _ in range(n_epoch):
        self.demonstration_buffer.shuffle(
            sequence_length=self.policy.sequence_length
        )
        if max_batches == 0:
            num_batches = possible_batches
        else:
            num_batches = min(possible_batches, max_batches)
        for i in range(num_batches // self.policy.sequence_length):
            demo_update_buffer = self.demonstration_buffer
            start = i * self.n_sequences * self.policy.sequence_length
            end = (i + 1) * self.n_sequences * self.policy.sequence_length
            mini_batch_demo = demo_update_buffer.make_mini_batch(start, end)
            run_out = self._update_batch(mini_batch_demo, self.n_sequences)
            loss = run_out["loss"]
            batch_losses.append(loss)
    ModelUtils.update_learning_rate(self.optimizer, decay_lr)
    self.current_lr = decay_lr
    self.has_updated = True
    update_stats = {"Losses/Pretraining Loss": np.mean(batch_losses)}
    return update_stats