class_docstr: CTC Prefix Beam Search is based on the paper
  `First-Pass Large Vocabulary Continuous Speech Recognition using Bi-Directional Recurrent DNNs`
  by Awni Y. Hannun and al (https://arxiv.org/abs/1408.2873).
  
  The implementation keep tracks of the blank and non-blank probabilities.
  It also suppors n-gram scoring on words and SentencePiece tokens. The input
  is expected to be a log-probabilities tensor of shape [batch, time, vocab_size].
  
  Several heuristics are implemented to speed up the decoding process:
  - pruning of the beam : the beams are pruned if their score is lower than
      the best beam score minus the beam_prune_logp
  - pruning of the tokens : the tokens are pruned if their score is lower than
      the token_prune_min_logp
  - pruning of the history : the beams are pruned if they are the same over
      max_ngram history
  - skipping of the blank : the frame is skipped if the blank probability is
      higher than the blank_skip_threshold
  
  Note: The CTCPrefixBeamSearcher can be more unstable than the CTCBeamSearcher
  or the TorchAudioCTCPrefixBeamSearch searcher. Please, use it with caution
  and check the results carefully.
  
  Note: if the Acoustic Model is not trained, the Beam Search will
  take a lot of time. We do recommand to use Greedy Search during validation
  until the model is fully trained and ready to be evaluated on test sets.
  
  Note: This implementation does not provide the time alignment of the
  hypothesis. If you need it, please use the CTCBeamSearcher.
  
  Arguments
  ---------
  **kwargs
      see CTCBaseSearcher, arguments are directly passed.
  
  Example
  -------
  >>> import torch
  >>> from speechbrain.decoders import CTCPrefixBeamSearcher
  >>> probs = torch.tensor([[[0.2, 0.0, 0.8],
  ...                   [0.4, 0.0, 0.6]]])
  >>> log_probs = torch.log(probs)
  >>> lens = torch.tensor([1.0])
  >>> blank_index = 2
  >>> vocab_list = ['a', 'b', '-']
  >>> searcher = CTCPrefixBeamSearcher(blank_index=blank_index, vocab_list=vocab_list)
  >>> hyps = searcher(probs, lens)
class_docstr_tok: ["CTC","Prefix","Beam","Search","is","based","on","the","paper","`","First-Pass","Large","Vocabulary","Continuous","Speech","Recognition","using","Bi-Directional","Recurrent","DNNs","`","by","Awni","Y.","Hannun","and","al","(","https",":","\/\/arxiv.org\/abs\/1408.2873",")",".","The","implementation","keep","tracks","of","the","blank","and","non-blank","probabilities",".","It","also","suppors","n-gram","scoring","on","words","and","SentencePiece","tokens",".","The","input","is","expected","to","be","a","log-probabilities","tensor","of","shape","[","batch",",","time",",","vocab_size","]",".","Several","heuristics","are","implemented","to","speed","up","the","decoding","process",":","-","pruning","of","the","beam",":","the","beams","are","pruned","if","their","score","is","lower","than","the","best","beam","score","minus","the","beam_prune_logp","-","pruning","of","the","tokens",":","the","tokens","are","pruned","if","their","score","is","lower","than","the","token_prune_min_logp","-","pruning","of","the","history",":","the","beams","are","pruned","if","they","are","the","same","over","max_ngram","history","-","skipping","of","the","blank",":","the","frame","is","skipped","if","the","blank","probability","is","higher","than","the","blank_skip_threshold","Note",":","The","CTCPrefixBeamSearcher","can","be","more","unstable","than","the","CTCBeamSearcher","or","the","TorchAudioCTCPrefixBeamSearch","searcher",".","Please",",","use","it","with","caution","and","check","the","results","carefully",".","Note",":","if","the","Acoustic","Model","is","not","trained",",","the","Beam","Search","will","take","a","lot","of","time",".","We","do","recommand","to","use","Greedy","Search","during","validation","until","the","model","is","fully","trained","and","ready","to","be","evaluated","on","test","sets",".","Note",":","This","implementation","does","not","provide","the","time","alignment","of","the","hypothesis",".","If","you","need","it",",","please","use","the","CTCBeamSearcher",".","Arguments","--","--","--","--","-","*","*","kwargs","see","CTCBaseSearcher",",","arguments","are","directly","passed",".","Example","--","--","--","-",">",">",">","import","torch",">",">",">","from","speechbrain.decoders","import","CTCPrefixBeamSearcher",">",">",">","probs","=","torch.tensor","(","[","[","[","0.2",",","0.0",",","0.8","]",",","...","[","0.4",",","0.0",",","0.6","]","]","]",")",">",">",">","log_probs","=","torch.log","(","probs",")",">",">",">","lens","=","torch.tensor","(","[","1.0","]",")",">",">",">","blank_index","=","2",">",">",">","vocab_list","=","[","'","a","'",",","'","b","'",",","'-","'","]",">",">",">","searcher","=","CTCPrefixBeamSearcher","(","blank_index=blank_index",",","vocab_list=vocab_list",")",">",">",">","hyps","=","searcher","(","probs",",","lens",")"]
docstr: Create a new beam and add it to the list of beams.
  
  Arguments
  ---------
  frame_index : int
      The index of the current frame.
  new_prefix : str
      The new prefix.
  new_token : str
      The new token.
  new_token_index : int
      The index of the new token.
  beams : list
      The list of beams.
  p : float
      The probability of the new token.
  previous_beam : CTCBeam
      The previous beam.
  
  Returns
  -------
  new_beam : CTCBeam
      The new beam.
docstr_tok: ["Create","a","new","beam","and","add","it","to","the","list","of","beams",".","Arguments","--","--","--","--","-","frame_index",":","int","The","index","of","the","current","frame",".","new_prefix",":","str","The","new","prefix",".","new_token",":","str","The","new","token",".","new_token_index",":","int","The","index","of","the","new","token",".","beams",":","list","The","list","of","beams",".","p",":","float","The","probability","of","the","new","token",".","previous_beam",":","CTCBeam","The","previous","beam",".","Returns","--","--","--","-","new_beam",":","CTCBeam","The","new","beam","."]
code: def _get_new_beam(
      self,
      frame_index: int,
      new_prefix: str,
      new_token: str,
      new_token_index: int,
      beams: List[CTCBeam],
      p: float,
      previous_beam: CTCBeam,
  ) -> CTCBeam:
      """Create a new beam and add it to the list of beams.
  
      Arguments
      ---------
      frame_index : int
          The index of the current frame.
      new_prefix : str
          The new prefix.
      new_token : str
          The new token.
      new_token_index : int
          The index of the new token.
      beams : list
          The list of beams.
      p : float
          The probability of the new token.
      previous_beam : CTCBeam
          The previous beam.
  
      Returns
      -------
      new_beam : CTCBeam
          The new beam.
      """
      for beam in beams:
          if beam.text == new_prefix:
              if p and p > beam.p:
                  beam.p = p
              return beam
  
      if not self.is_spm and new_token_index == self.space_index:
          new_frame_list = (
              previous_beam.text_frames
              if previous_beam.partial_word == ""
              else previous_beam.text_frames
              + [previous_beam.partial_frames]
          )
  
          # if we extend the beam with a space, we need to reset the partial word
          # and move it to the next word
          new_beam = CTCBeam(
              text=new_prefix,
              full_text=previous_beam.full_text,
              next_word=previous_beam.partial_word,
              partial_word="",
              last_token=new_token,
              last_token_index=new_token_index,
              text_frames=new_frame_list,
              partial_frames=(-1, -1),
              score=-math.inf,
              score_ctc=-math.inf,
              p_b=-math.inf,
          )
      elif self.is_spm and new_token[:1] == self.spm_token:
          # remove the spm token at the beginning of the token
          clean_token = new_token[1:]
  
          new_frame_list = (
              previous_beam.text_frames
              if previous_beam.partial_word == ""
              else previous_beam.text_frames
              + [previous_beam.partial_frames]
          )
  
          # If the beginning of the token is the spm_token
          # then it means that we are extending the beam with a new word.
          # We need to change the new_word with the partial_word
          # and reset the partial_word with the new token
          new_prefix = previous_beam.text + " " + clean_token
          new_beam = CTCBeam(
              text=new_prefix,
              full_text=previous_beam.full_text,
              next_word=previous_beam.partial_word,
              partial_word=clean_token,
              last_token=new_token,
              last_token_index=new_token_index,
              text_frames=new_frame_list,
              partial_frames=(frame_index, frame_index + 1),
              score=-math.inf,
              score_ctc=-math.inf,
              p_b=-math.inf,
          )
      elif new_token_index == previous_beam.last_token_index:
          new_end_frame = frame_index + 1
  
          new_part_frames = (
              previous_beam.partial_frames
              if new_token_index == self.blank_index
              else (previous_beam.partial_frames[0], new_end_frame)
          )
  
          # if repeated token, we only change the score
          new_beam = CTCBeam(
              text=new_prefix,
              full_text=previous_beam.full_text,
              next_word="",
              partial_word=previous_beam.partial_word,
              last_token=new_token,
              last_token_index=new_token_index,
              text_frames=previous_beam.text_frames,
              partial_frames=new_part_frames,
              score=-math.inf,
              score_ctc=-math.inf,
              p_b=-math.inf,
          )
      else:
          new_part_frames = (
              (frame_index, frame_index + 1)
              if previous_beam.partial_frames[0] < 0
              else (previous_beam.partial_frames[0], frame_index + 1)
          )
  
          # last case, we are extending the partial_word with a new token
          new_beam = CTCBeam(
              text=new_prefix,
              full_text=previous_beam.full_text,
              next_word="",
              partial_word=previous_beam.partial_word + new_token,
              last_token=new_token,
              last_token_index=new_token_index,
              text_frames=previous_beam.text_frames,
              partial_frames=new_part_frames,
              score=-math.inf,
              score_ctc=-math.inf,
              p_b=-math.inf,
          )
      beams.append(new_beam)
      if previous_beam:
          new_beam.p = previous_beam.p
      return new_beam
  
imports: from itertools import groupby
  from speechbrain.dataio.dataio import length_to_mask
  import math
  import dataclasses
  import numpy
  import heapq
  import logging
  import torch
  import warnings
  from typing import Dict, List, Optional, Union, Any, Tuple
label_desc: Use image node_id 3 for calling the CTCPrefixBeamSearcher obj's underlying member method code with example usage: obj._get_new_beam(frame_index, new_prefix, new_token, new_token_index, beams, p, previous_beam) and returns: new_beam, beam