code: def batch_recurrent_experiences(
      experiences, device, phi, gamma, batch_states=batch_states
  ):
      """Batch experiences for recurrent model updates.
  
      Args:
          experiences: list of episodes. Each episode is a list
              containing between 1 and n dicts, each containing:
                - state (object): State
                - action (object): Action
                - reward (float): Reward
                - is_state_terminal (bool): True iff next state is terminal
                - next_state (object): Next state
              The list must be sorted desc by lengths to be packed by
              `torch.nn.rnn.pack_sequence` later.
          device : GPU or CPU the tensor should be placed on
          phi : Preprocessing function
          gamma: discount factor
          batch_states: function that converts a list to a batch
      Returns:
          dict of batched transitions
      """
      assert _is_sorted_desc_by_lengths(experiences)
      flat_transitions = flatten_sequences_time_first(experiences)
      batch_exp = {
          "state": [
              batch_states(
                  [transition["state"] for transition in ep],
                  device,
                  phi,
              )
              for ep in experiences
          ],
          "action": torch.as_tensor(
              [transition["action"] for transition in flat_transitions],
              device=device,
          ),
          "reward": torch.as_tensor(
              [transition["reward"] for transition in flat_transitions],
              dtype=torch.float,
              device=device,
          ),
          "next_state": [
              batch_states(
                  [transition["next_state"] for transition in ep],
                  device,
                  phi,
              )
              for ep in experiences
          ],
          "is_state_terminal": torch.as_tensor(
              [
                  transition["is_state_terminal"]
                  for transition in flat_transitions
              ],
              dtype=torch.float,
              device=device,
          ),
          "discount": torch.full(
              (len(flat_transitions),),
              gamma,
              dtype=torch.float,
              device=device,
          ),
          "recurrent_state": recurrent_state_from_numpy(
              concatenate_recurrent_states(
                  [ep[0]["recurrent_state"] for ep in experiences]
              ),
              device,
          ),
          "next_recurrent_state": recurrent_state_from_numpy(
              concatenate_recurrent_states(
                  [ep[0]["next_recurrent_state"] for ep in experiences]
              ),
              device,
          ),
      }
      # Batch next actions only when all the transitions have them
      if all(
          transition["next_action"] is not None
          for transition in flat_transitions
      ):
          batch_exp["next_action"] = torch.as_tensor(
              [
                  transition["next_action"]
                  for transition in flat_transitions
              ],
              device=device,
          )
      return batch_exp
  
imports: from abc import ABCMeta, abstractmethod, abstractproperty
  from typing import Optional
  import numpy
  import torch
  from pfrl.utils.batch_states import batch_states
  from pfrl.utils.recurrent import concatenate_recurrent_states, flatten_sequences_time_first, recurrent_state_from_numpy
label_desc: Use image node_id 4 for calling a global function with example usage: batch_recurrent_experiences(experiences, device, phi, gamma, batch_states) and returns: batch_exp