def recognize_single(self, inputs: schemas.PredictInput, max_tokens_per_frame: int = 3, **kwargs):
        """
        Ref: https://arxiv.org/pdf/1801.00841.pdf
        This is a greedy decoding algorithm that greedily select the best token at each time step
        Only apply for batch size 1
        """
        with tf.name_scope(f"{self.name}_decode_greedy"):
            features, features_length = self.feature_extraction((inputs.inputs, inputs.inputs_length), training=False)
            encoded, encoded_length, next_encoder_states = self.encoder.call_next(features, features_length, inputs.previous_encoder_states)

            frame = tf.zeros([1, 1], dtype=tf.int32)
            nframes = encoded_length

            previous_tokens = inputs.previous_tokens
            token_index = tf.ones([], dtype=tf.int32) * -1
            tokens = tf.TensorArray(
                dtype=tf.int32,
                size=tf.reshape(nframes, shape=[]) * max_tokens_per_frame,
                dynamic_size=False,
                clear_after_read=False,
                element_shape=tf.TensorShape([]),
            )
            num_tokens_per_frame = tf.TensorArray(
                dtype=tf.int32,
                size=tf.reshape(nframes, shape=[]),
                dynamic_size=False,
                clear_after_read=False,
                element_shape=tf.TensorShape([]),
            )

            previous_decoder_states = inputs.previous_decoder_states

            def condition(
                _frame,
                _nframes,
                _previous_tokens,
                _token_index,
                _tokens,
                _num_tokens_per_frame,
                _max_tokens_per_frame,
                _previous_decoder_states,
            ):
                return tf.less(_frame, _nframes)

            def body(
                _frame,
                _nframes,
                _previous_tokens,
                _token_index,
                _tokens,
                _num_tokens_per_frame,
                _max_tokens_per_frame,
                _previous_decoder_states,
            ):
                _current_frame = tf.expand_dims(tf.gather_nd(encoded, _frame, batch_dims=1), axis=1)  # [1, 1, E]
                _log_softmax, _states = self.call_next(_current_frame, _previous_tokens, _previous_decoder_states)
                _current_tokens = tf.reshape(tf.argmax(_log_softmax, axis=-1, output_type=tf.int32), [1, 1])  # [1, 1, 1] -> [1, 1]

                ##################### conditions, blanks are ignored
                _equal_blank = tf.equal(_current_tokens, self.blank)  # [1, 1]

                ##################### step updates
                __frame_index = tf.reshape(_frame, shape=[])
                __equal_blank_index = tf.reshape(_equal_blank, shape=[])
                # only non-blank tokens are counted in number of tokens per frame
                _current_frame_num_tokens = tf.where(
                    __equal_blank_index,
                    _num_tokens_per_frame.read(__frame_index),
                    tf.add(_num_tokens_per_frame.read(__frame_index), 1),
                )
                _num_tokens_per_frame = _num_tokens_per_frame.write(__frame_index, _current_frame_num_tokens)
                # increase frame index if current tokens are blank or number of tokens per frame exceeds max tokens per frame
                _frame = tf.where(
                    tf.logical_or(_equal_blank, tf.greater_equal(_current_frame_num_tokens, _max_tokens_per_frame)),
                    tf.add(_frame, 1),
                    _frame,
                )
                # increase token index if current token is not blank, so that it can be appended to tokens array
                _token_index = tf.where(__equal_blank_index, _token_index, tf.add(_token_index, 1))

                ##################### content updates
                # keep previous tokens if current tokens are blank
                _current_tokens = tf.where(_equal_blank, _previous_tokens, _current_tokens)
                # keep previous states if current tokens are blank
                _states = tf.where(tf.reshape(_equal_blank, [1, 1, 1, 1]), _previous_decoder_states, _states)
                # token_index initialized as -1, so that the first recognized token will be at index 0
                # therefore only update (append) tokens when token_index >= 0
                _tokens = tf.cond(
                    tf.greater_equal(_token_index, 0),
                    lambda: _tokens.write(_token_index, tf.reshape(_current_tokens, shape=[])),
                    lambda: _tokens,
                )

                ##################### return
                return (
                    _frame,
                    _nframes,
                    _current_tokens,
                    _token_index,
                    _tokens,
                    _num_tokens_per_frame,
                    _max_tokens_per_frame,
                    _states,
                )

            (
                frame,
                nframes,
                next_tokens,
                token_index,
                tokens,
                num_tokens_per_frame,
                max_tokens_per_frame,
                next_decoder_states,
            ) = tf.while_loop(
                condition,
                body,
                loop_vars=(
                    frame,
                    nframes,
                    previous_tokens,
                    token_index,
                    tokens,
                    num_tokens_per_frame,
                    max_tokens_per_frame,
                    previous_decoder_states,
                ),
                back_prop=False,
            )

            return schemas.PredictOutput(
                tokens=tf.reshape(tokens.stack(), shape=[1, -1]),
                next_tokens=next_tokens,
                next_encoder_states=next_encoder_states,
                next_decoder_states=next_decoder_states,
            )

        Ref: https://arxiv.org/pdf/1801.00841.pdf
        This is a greedy decoding algorithm that greedily select the best token at each time step
        Only apply for batch size 1
        
tensorflow_asr/models/transducer/base_transducer.py