Take in an integer-vectorized (i.e., index) vector, and predict the maximally
        likely response, returning it as an integer-vectorized (i.e., index) vector.

def predict(self, x):
        """
        Take in an integer-vectorized (i.e., index) vector, and predict the maximally
        likely response, returning it as an integer-vectorized (i.e., index) vector.
        """
        recurrent_unit = self.config['recurrent-unit-type']
        
        # encode the input seq into a context vector
        if recurrent_unit == 'lstm':
            context_state = self.encoder.predict(np.array(x))
        elif recurrent_unit == 'gru':
            hidden_state = self.encoder.predict(np.array(x))
            context_state = [hidden_state]
        else:
            raise Exception('Invalid recurrent unit type: {}'.format(recurrent_unit))
        
        # create an empty target sequence, seeded with the start character
        y = self.vectorizer.vectorize_utterance([self.config['start']])
        response = []
        
        # i = 0
        while True:
            
            # decode the current sequence + current context into a
            # conditional distribution over next token:
            output_token_probs = None
            if recurrent_unit == 'lstm':
                output_token_probs, h, c = self.decoder.predict([y] + context_state)
                context_state = [h, c]
            elif recurrent_unit == 'gru':
                output_token_probs, hidden_state = self.decoder.predict([y] + context_state)
                context_state = [hidden_state]
            else:
                raise Exception('Invalid recurrent unit type: {}'.format(recurrent_unit))
            
            # sample a token from the output distribution (currently using maximum-likelihoo -- i.e., argmax)
            sampled_token = np.argmax(output_token_probs[0, -1, :])
            
            # add the sampled token to our output string
            response += [sampled_token]
            
            # exit condition: either we've
            # - hit the max length (self.data.output_max_len), or
            # - decoded a stop token ('\n')
            if (sampled_token == self.vectorizer.ie.transform([self.config['stop']]) or 
                len(response) >= self.config['max-utterance-length']):
                break
                
            # update the np array (target seq)
            y = np.array([sampled_token]) # np.concatenate((y, [sampled_token]))
            
        return response