def get_prompt(self, state: State) -> PromptResult:
        """This method is the same as get_response. Only difference is that 

        1. we do not get a list of reasons (because there is not enough time)
        2. we only chose to solicit an opinion if user didn't have an opinion on it before, or 
        3. we will solicit a reason if user told us before that they like or dislike a phrase
        
        :param state: the current state
        :type state: State
        :return: a result chirpy can use
        :rtype: PromptResult
        """
        self.initialize_turn()
        if state.last_turn_prompt:
            return emptyPrompt(state)
        phrase, priority, transition_phrase = self.select_phrase_for_prompt(state)
        if phrase is None:
            return emptyPrompt(state)
        utterance = self.state_manager.current_state.text
        additional_features = self.populate_features(state, utterance)
        additional_features.detected_phrases = tuple([phrase for phrase in additional_features.detected_phrases if phrase not in state.phrases_done])

        # Then need to advance the state using the utterance
        state_p = state_actions.next_state(state, utterance, additional_features)
        if state_p is None:
            # Special handling for prompt: Add phrase and sentiment
            state_p = state.reset_state()
            state_p.cur_phrase = phrase
            user_sentiments_history = dict(state_p.user_sentiment_history)
            state_p.cur_sentiment = user_sentiments_history[phrase] if phrase in user_sentiments_history else 2
        if state_p.cur_sentiment != 2:
            action = Action(solicit_reason=True)
        else:
            action = Action(solicit_opinion=True)
        # Then need to utterancify the action
        text, phrase, reason = fancy_utterancify_prompt(state_p, action, [], [], [], state_p.cur_phrase not in state.detected_opinionated_phrases, 
                                                        self.state_manager.current_state.choose_least_repetitive) # type: ignore
        # Then need to fill the rest of the fields of state_p (through mutation)
        state_p = state_actions.fill_state_on_action(state_p, action, text, phrase, additional_features, reason, 
            self.opinionable_phrases, self.opinionable_entities)

        state_p.last_turn_prompt, state_p.last_turn_select = True, False
        wiki_entity = None
        if self.opinionable_phrases[phrase].good_for_wiki:
            wiki_entity = get_entity_by_wiki_name(self.opinionable_phrases[phrase].wiki_entity_name)
        state.last_turn_prompt, state.last_turn_select = False, False

        text = ' '.join((transition_phrase, text))
            
        return PromptResult(text, priority, state, wiki_entity, conditional_state=state_p)
Ejemplo n.º 2
0
    def get_prompt(self, state: State) -> PromptResult:
        #try:
        #    return IntroductoryTreelet(self).get_can_start_response(state)
        #except CantRespondError:
        try:
            # If this is a smooth transition from one turn hack on BLM
            if self.state_manager.current_state.smooth_handoff == SmoothHandoff.ONE_TURN_TO_WIKI_GF:
                return IntroduceEntityTreelet(self).get_prompt(state, True)
            else:
                return OpenQuestionTreelet(self).get_prompt(state)
        except CantPromptError:
            try:
                if self.state_manager.current_state.experiments.look_up_experiment_value(
                        'convpara'):
                    try:
                        return ConvParaTILTreelet(self).get_prompt(state)
                    except CantRespondError:
                        return TILTreelet(self).get_prompt(state)
                else:
                    return TILTreelet(self).get_prompt(state)
            except CantPromptError:
                try:
                    return HandleSectionTreelet(self).get_prompt(state)
                except CantPromptError:
                    try:
                        return IntroduceEntityTreelet(self).get_prompt(state)
                    except:
                        pass

        return emptyPrompt(state)
Ejemplo n.º 3
0
    def get_prompt(self, state: State) -> PromptResult:

        # Init all treelets
        name2initializedtreelet = {treelet_name: treelet_class(self) for treelet_name, treelet_class in NAME2TREELET.items()}

        # Complete a smooth handoff if required
        if self.state_manager.current_state.smooth_handoff == SmoothHandoff.LAUNCH_TO_NEURALCHAT:
            launch_prompt_result = self.get_launch_prompt(name2initializedtreelet, state)
            if launch_prompt_result:
                return launch_prompt_result

        # Otherwise, get starter question prompts from all unused treelets
        unused_treelet_names = [treelet_name for treelet_name in name2initializedtreelet if not state.treelet_has_been_used(treelet_name)]  # list of treelet names
        logger.primary_info(f'Getting starter question prompts from these unused treelets:\n{unused_treelet_names}')
        treeletname2promptresult = {treelet_name: name2initializedtreelet[treelet_name].get_prompt(state) for treelet_name in unused_treelet_names}
        treeletname2promptresult = {treelet_name: prompt_result for treelet_name, prompt_result in treeletname2promptresult.items() if prompt_result is not None}
        logger.primary_info("Got these starter questions from neural chat treelets:\n{}".format('\n'.join([f"{treelet_name}: {prompt_result}" for treelet_name, prompt_result in treeletname2promptresult.items()])))

        # Sample one of highest priority and return
        if treeletname2promptresult:
            top_priority = max([prompt_result.type for prompt_result in treeletname2promptresult.values()])
            treeletname2promptresult = {treelet_name: prompt_result for treelet_name, prompt_result in treeletname2promptresult.items() if prompt_result.type==top_priority}
            logger.primary_info(f"Restricting to just these results with top_priority={top_priority.name}: {treeletname2promptresult.keys()}")

            # If a treelet is specified by test args, choose that. Otherwise randomly sample.
            sampled_prompt = choose_treelet_result(treeletname2promptresult, self.state_manager.current_state)
            return sampled_prompt
        else:
            logger.primary_info(f'Neural Chat has no more unused treelets left, so giving no prompt')
            return emptyPrompt(state)
Ejemplo n.º 4
0
 def get_prompt(self, state: dict) -> PromptResult:
     try:
         response = self._get_prompt(state)
     except Exception as err:
         tb = traceback.print_tb(err.__traceback__)
         logger.error(
             "MUSIC RG is returning an emptyPrompt, because of {}, with the traceback: {}"
             .format(err, tb))
         response = emptyPrompt(state)
     return response
Ejemplo n.º 5
0
    def get_prompt(self, state: State, state_manager) -> PromptResult:
        """Ask the first unasked question for state.cur_category_name"""

        category_name = state.cur_category_name
        question = state.get_first_unasked_question(
            category_name)  # CategoryQuestion or None
        if question:
            question_str = question.question
            response = "{} {}".format(choice(BRIDGES), question_str)
            cur_entity = get_entity_by_wiki_name(question.cur_entity_wiki_name,
                                                 state_manager.current_state)
            conditional_state = ConditionalState(HandleAnswerTreelet.__name__,
                                                 category_name, None,
                                                 question_str, False)
            return PromptResult(text=response,
                                prompt_type=PromptType.CURRENT_TOPIC,
                                state=state,
                                cur_entity=cur_entity,
                                expected_type=question.expected_type,
                                conditional_state=conditional_state)
        else:
            return emptyPrompt(state)
Ejemplo n.º 6
0
    def _get_prompt(self, state: dict) -> PromptResult:
        prompt = None

        # Check if there is a treelet that can respond to the user initiated cur_entity, if it exists.
        cur_entity = self.state_manager.current_state.entity_tracker.cur_entity
        if cur_entity and cur_entity not in state.discussed_entities:
            entity_treelet_name = self._get_treelet_name_for_entity(cur_entity)
            if entity_treelet_name:
                prompt = self.treelets[entity_treelet_name].get_prompt(
                    state, trigger_entity=cur_entity)

        # Check if there is a random treelet that can respond.
        if not prompt: prompt = self._get_random_prompt(state)

        # If we have a prompt, pick a connector.
        if not prompt:
            prompt = emptyPrompt(state)
        else:
            # change_signal = self.state_manager.choose_least_repetitive(TOPIC_CHANGING_SIGNALS)
            change_signal = random.choice(TOPIC_CHANGING_SIGNALS)
            prompt.text = "{} {}".format(change_signal, prompt.text)
            prompt.text = prompt.text

        return prompt
 def get_prompt(self, state: State) -> PromptResult:
     return emptyPrompt(state)
Ejemplo n.º 8
0
 def get_prompt(self, state):
     return emptyPrompt(state)
Ejemplo n.º 9
0
 def get_prompt(self,
                state: State,
                conditional_state: ConditionalState = None,
                trigger_entity: WikiEntity = None) -> PromptResult:
     return emptyPrompt(state)
 def get_prompt(self, state: dict) -> PromptResult:
     return emptyPrompt(state=state)
Ejemplo n.º 11
0
    def get_prompt(self, state: State) -> PromptResult:
        """
        Randomly choose an undiscussed generic category and ask its first question.
        """

        # If this is a smooth transition from movies, get a prompt for tv category from the Introductory treelet
        '''
        if self.state_manager.current_state.smooth_handoff == SmoothHandoff.MOVIES_TO_CATEGORIES:
            logger.primary_info('Getting prompt from tv IntroductoryTreelet.')
            state.cur_category_name = 'TVCategory'
            question = state.get_first_unasked_question(state.cur_category_name)
            if question is None:
                logger.warning('Unable to complete smooth handoff from movies to categories because we have no unasked tv questions left')
            else:
                new_entity = get_entity_by_wiki_name(question.cur_entity_wiki_name, self.state_manager.current_state)
                conditional_state = ConditionalState(HandleAnswerTreelet.__name__, state.cur_category_name, None, question.question, False)
                result = PromptResult(question.question, PromptType.FORCE_START, state, cur_entity=new_entity,
                                      expected_type=question.expected_type, conditional_state=conditional_state)
                return result
        '''
        # If the user is requesting a category, get a prompt for that category from the Introductory treelet
        utterance = self.state_manager.current_state.text.lower()
        user_initiated_category, user_has_posnav = get_user_initiated_category(
            utterance, self.state_manager.current_state)
        if user_initiated_category is not None:
            state.cur_category_name = user_initiated_category
            logger.primary_info(
                f'Getting prompt from {IntroductoryTreelet.__name__}')
            prompt_result = self.treeletname2treelet[
                IntroductoryTreelet.__name__].get_prompt(
                    state, self.state_manager)
            if prompt_result.text is not None and not user_has_posnav:
                logger.primary_info(
                    "Setting prompt type to CONTEXTUAL as the user does not have posnav"
                )
                prompt_result.type = PromptType.CONTEXTUAL
            if prompt_result:
                return prompt_result

        # Ask any remaining unasked generic category questions
        category_name, question = state.get_random_generic_undiscussed_category_question(
        )
        if category_name and question:
            logger.primary_info(
                f"Randomly chose an undiscussed generic category {category_name}. Asking its first question as a generic prompt."
            )
            new_entity = get_entity_by_wiki_name(
                question.cur_entity_wiki_name,
                self.state_manager.current_state)
            conditional_state = ConditionalState(HandleAnswerTreelet.__name__,
                                                 category_name, None,
                                                 question.question, False)
            transition = self.state_manager.current_state.choose_least_repetitive(
                QUESTION_CONNECTORS)
            result = PromptResult(transition + question.question,
                                  PromptType.GENERIC,
                                  state,
                                  cur_entity=new_entity,
                                  expected_type=question.expected_type,
                                  conditional_state=conditional_state)

            return result

        # Otherwise return nothing
        return emptyPrompt(state)