Esempio n. 1
0
 def create_rg_result_ask_another_song_of_musician(self,
                                                   state,
                                                   musician_entity,
                                                   conditional_blacklist=[]
                                                   ):
     blacklist = state.discussed_entities + conditional_blacklist
     song_entity = MusicianTreelet.get_song_of_musician(
         musician_entity, blacklist)
     if song_entity and WikiEntityInterface.is_in_entity_group(
             song_entity.wiki_entity, WikiEntityInterface.EntityGroup.SONG):
         question = self.choose(QUESTION_OTHER_SONG)
         musician_placeholder = f'MUSICIAN_{WikiEntityInterface.ENTITY_PLACEHOLDER}'
         song_placeholder = f'SONG_{WikiEntityInterface.ENTITY_PLACEHOLDER}'
         question = question.replace(musician_placeholder,
                                     musician_entity.pref_label)
         question = question.replace(song_placeholder,
                                     song_entity.pref_label)
         rg_result = self.prepare_rg_result(question, state)
         rg_result.conditional_state.discussed_entities = conditional_blacklist + [
             song_entity.wiki_entity
         ]
         rg_result.conditional_state.needs_internal_prompt = False
         rg_result.conditional_state.asked_question = 'QuestionAnotherSongOfMusician'
         rg_result.conditional_state.next_treelet = self.name
         rg_result.conditional_state.discussed_entities.append(
             song_entity.wiki_entity)
         rg_result.cur_entity = song_entity.wiki_entity
         return rg_result
     return None
Esempio n. 2
0
    def _handle_answer_whose_song(self, state, triggered_answers):
        question_name = 'QuestionWhoseSong'
        musician_wiki_entity = self.state_manager.current_state.entity_linker.best_ent_of_type(
            WikiEntityInterface.EntityGroup.MUSICIAN)
        if not musician_wiki_entity or musician_wiki_entity.name is WikiEntityInterface.PageName.MUSICIAN:
            if question_name in triggered_answers and 'answer' in triggered_answers[
                    question_name]:
                musician_name = triggered_answers[question_name]['answer']
                musician_wiki_entity = WikiEntityInterface.link_span(
                    musician_name)

        rg_result = None
        if musician_wiki_entity and WikiEntityInterface.is_in_entity_group(
                musician_wiki_entity,
                WikiEntityInterface.EntityGroup.MUSICIAN):
            musician_entity = MusicEntity(
                pref_label=musician_wiki_entity.common_name,
                wiki_entity=musician_wiki_entity)
            rg_result = self.create_rg_result_ask_another_song_of_musician(
                state, musician_entity)
            if rg_result:
                response = self.choose(ACKNOWLEDGE_WHOSE_SONG)
                rg_result.text = f"{response} {rg_result.text}"

        if not rg_result:
            response = self.choose(ACKNOWLEDGE_COULDNT_GET_MUSICIAN)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False

        return rg_result
Esempio n. 3
0
    def get_prompt(self, state, conditional_state=None, trigger_entity = None):
        question_candidates = [q for q in list(QUESTION_TEMPLATES.keys()) if q not in state.asked_questions]
        is_correct_entity_group = trigger_entity and WikiEntityInterface.is_in_entity_group(trigger_entity, WikiEntityInterface.EntityGroup.MUSICIAN)
        undiscussed_titles = [title for title in EXAMPLE_MUSICIAN_WIKI_PAGES.keys() if
                              not WikiEntityInterface.is_title_in_entities(title, state.discussed_entities)]

        # Prepare prompt.
        prompt = self.prepare_prompt_result('Placeholder', state,
                                            priority=PromptType.GENERIC,
                                            cur_entity=None,
                                            conditional_state=conditional_state)
        prompt.conditional_state.turn_treelet_history.append(self.name)
        prompt.conditional_state.next_treelet = self.name
        prompt.conditional_state.needs_internal_prompt = False

        # Give current topic response if possible.
        if trigger_entity and is_correct_entity_group:
            prompt.priority = PromptType.CURRENT_TOPIC
            prompt.cur_entity = trigger_entity
            prompt.conditional_state.musician_entity = MusicEntity(pref_label=trigger_entity.common_name, wiki_entity=trigger_entity)
            prompt.conditional_state.discussed_entities.append(trigger_entity)
            prompt.conditional_state.asked_question = 'QuestionLikedMusicianTemplate' # This is the handler function for the question we are asking.
            prompt.conditional_state.acknowledged_entity = True
            acknowledgment = random.choice(['', self.choose(ACKNOWLEDGE_MENTIONED_MUSICIAN)])
            question = self.choose(QUESTION_DO_YOU_LIKE)
            response = "{} {}".format(acknowledgment, question)
            prompt.text = response.replace(WikiEntityInterface.ENTITY_PLACEHOLDER, trigger_entity.common_name)
            return prompt

        # Generic response.
        if question_candidates:
            prompt.priority = PromptType.GENERIC
            prompt.cur_entity = WikiEntityInterface.get_by_name(WikiEntityInterface.PageName.MUSICIAN)
            prompt.expected_type = WikiEntityInterface.EntityGroup.MUSICIAN
            question_name = random.choice(question_candidates)
            prompt.conditional_state.asked_question = question_name
            question = self.construct_response_from_templates(QUESTION_TEMPLATES, question_name, question=True)
            transition = random.choice(NO_ENTITY_TRANSITIONS)
            prompt.text = " ".join((transition, question))
            return prompt

        # Ask a question about a musician we know about.
        if undiscussed_titles:
            selected_title = undiscussed_titles[0]
            cur_entity = WikiEntityInterface.get_by_name(selected_title)
            if cur_entity:
                prompt.priority = PromptType.GENERIC
                prompt.cur_entity = cur_entity
                prompt.conditional_state.musician_entity = MusicEntity(pref_label=cur_entity.common_name, wiki_entity=cur_entity)
                prompt.conditional_state.discussed_entities.append(cur_entity)
                prompt.conditional_state.asked_question = 'QuestionLikedMusicianTemplate' # This is the handler function for the question we are asking.
                question = self.choose(QUESTION_DO_YOU_LIKE_POPULAR)
                question = Pronoun.replace_pronouns(question, EXAMPLE_MUSICIAN_WIKI_PAGES[selected_title])
                question = question.replace(WikiEntityInterface.ENTITY_PLACEHOLDER, cur_entity.common_name)
                transition = random.choice(ENTITY_TRANSITIONS)
                prompt.text = " ".join((transition, question))
                return prompt

        # We ran out of prompts.
        return None
Esempio n. 4
0
    def get_response_trigger_phrase(self, state, trigger_phrase = None):
        utterance = self.state_manager.current_state.text
        triggered_templates = self.process_templates(QUESTION_TEMPLATES, utterance)
        sentiment_answers = self.process_templates(SENTIMENT_TEMPLATES, utterance)
        triggered_templates = {**triggered_templates, **sentiment_answers}
        undiscussed_titles = [title for title in EXAMPLE_MUSICIAN_WIKI_PAGES.keys() if
                              not WikiEntityInterface.is_title_in_entities(title, state.discussed_entities)]
        trigger_entity = None
        if trigger_phrase:
            trigger_entity = WikiEntityInterface.link_span(trigger_phrase)
            if trigger_entity and not WikiEntityInterface.is_in_entity_group(trigger_entity, WikiEntityInterface.EntityGroup.MUSICIAN):
                trigger_entity = None

        if 'QuestionLikedMusicianTemplate' in triggered_templates:
            response = self._handle_question_like(state, triggered_templates)
        elif trigger_entity:
            response = self.get_response_trigger_entity(state, trigger_entity)
        elif undiscussed_titles:
            selected_title = undiscussed_titles[0]
            cur_entity = WikiEntityInterface.get_by_name(selected_title)
            question = self.choose(QUESTION_DO_YOU_LIKE_POPULAR)
            question = Pronoun.replace_pronouns(question, EXAMPLE_MUSICIAN_WIKI_PAGES[selected_title])
            question = question.replace(WikiEntityInterface.ENTITY_PLACEHOLDER, cur_entity.common_name)
            response = self.prepare_rg_result(question, state, cur_entity=cur_entity)
            response.conditional_state.musician_entity = MusicEntity(pref_label=cur_entity.common_name, wiki_entity=cur_entity)
            response.conditional_state.discussed_entities.append(cur_entity)
            response.conditional_state.asked_question = 'QuestionLikedMusicianTemplate' # This is the handler function for the question we are asking.
            response.conditional_state.next_treelet = self.name
            response.conditional_state.needs_internal_prompt = False
        else:
            response = self._handle_expression_chat_musician(state, None)
        return response
Esempio n. 5
0
    def _handle_answer_favorite_question(self, state, triggered_answers):
        question_name = 'QuestionFavoriteSongTemplate'

        # Prepare responses
        if self.is_no_answer(
        ) or 'NegativeTemplate' in triggered_answers or 'DontKnowTemplate' in triggered_answers:
            response = self.choose(ACKNOWLEDGE_FAVORITE_SONG_NEGATIVE)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.needs_prompt = True
        else:
            # Check if the user mentioned a song.
            song_wiki_entity = None

            if not song_wiki_entity and question_name in triggered_answers and 'answer' in triggered_answers[
                    question_name]:
                song_name = triggered_answers[question_name]['answer']
                song_wiki_entity = WikiEntityInterface.link_span(song_name)

            # If the user mentioned a song, ask a follow up question.
            if song_wiki_entity and WikiEntityInterface.is_in_entity_group(
                    song_wiki_entity, WikiEntityInterface.EntityGroup.SONG):
                response = self.choose(ACKNOWLEDGE_FAVORITE_SONG)
                followup = self.choose(QUESTION_WHY_DO_YOU_LIKE)
                response = "{} {}".format(response, followup)
                rg_result = self.prepare_rg_result(response, state)

                song_entity = MusicEntity(
                    pref_label=song_wiki_entity.common_name,
                    wiki_entity=song_wiki_entity)
                musician_entity = MusicianTreelet.get_musician(
                    song_wiki_entity.name)

                rg_result.conditional_state.song_entity = song_entity
                rg_result.conditional_state.musician_entity = musician_entity
                rg_result.text = response.replace(
                    WikiEntityInterface.ENTITY_PLACEHOLDER,
                    song_wiki_entity.common_name)
                rg_result.cur_entity = song_wiki_entity
                rg_result.conditional_state.discussed_entities.append(
                    song_wiki_entity)
                rg_result.conditional_state.needs_internal_prompt = False
                rg_result.conditional_state.next_treelet = self.name
                rg_result.conditional_state.asked_question = 'QuestionWhyDoYouLikeSong'
            # We don't know which song the user mentioned.
            elif state.num_repeats < REPEAT_THRESHOLD:
                response = self.choose(QUESTION_COULD_YOU_REPEAT)
                rg_result = self.prepare_rg_result(response, state)
                rg_result.conditional_state.repeated_question = True
                rg_result.conditional_state.needs_internal_prompt = False
                rg_result.conditional_state.next_treelet = self.name
                rg_result.conditional_state.asked_question = 'QuestionWhyDoYouLikeSong'
            else:
                response = self.choose(ACKNOWLEDGE_COULDNT_GET_SONG)
                rg_result = self.prepare_rg_result(response, state)
                rg_result.conditional_state.needs_internal_prompt = False

        return rg_result
Esempio n. 6
0
 def _get_treelet_name_for_entity(self, entity):
     entity_treelet_name = None
     for treelet_name, treelet in self.treelets.items():
         for entity_group in treelet.trigger_entity_groups:
             if WikiEntityInterface.is_in_entity_group(
                     entity, entity_group):
                 if not entity_treelet_name:
                     entity_treelet_name = treelet_name
     return entity_treelet_name
Esempio n. 7
0
    def _handle_answer_like_question(self, state, triggered_answers):
        question_name = 'QuestionLikedMusicianTemplate'

        if 'NegativeTemplate' in triggered_answers or 'DontKnowTemplate' in triggered_answers:
            response = self.choose(ACKNOWLEDGE_LIKED_MUSICIAN_NEGATIVE)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.needs_prompt = True
        else:
            # Check if the user mentioned a musician.
            musician_wiki_entity = self.state_manager.current_state.entity_linker.best_ent_of_type(
                WikiEntityInterface.EntityGroup.MUSICIAN)
            if state.musician_entity: musician_wiki_entity = state.musician_entity.wiki_entity

            if not musician_wiki_entity and question_name in triggered_answers and 'answer' in triggered_answers[question_name]:
                musician_name = triggered_answers[question_name]['answer']
                musician_wiki_entity = WikiEntityInterface.link_span(musician_name)

            # If we know the musician.
            if musician_wiki_entity and WikiEntityInterface.is_in_entity_group(musician_wiki_entity, WikiEntityInterface.EntityGroup.MUSICIAN):
                if state.acknowledged_entity:
                    response = self.choose(ACKNOWLEDGE_LIKED_MUSICIAN)
                else:
                    response = self.choose(ACKNOWLEDGE_MENTIONED_MUSICIAN)
                response = response.replace(WikiEntityInterface.ENTITY_PLACEHOLDER, musician_wiki_entity.common_name)
                rg_result = self.prepare_rg_result(response, state)
                rg_result.conditional_state.discussed_entities.append(musician_wiki_entity)
                musician_entity = MusicEntity(pref_label=musician_wiki_entity.common_name, wiki_entity=musician_wiki_entity)
                song_entity = self.get_song_of_musician(musician_entity, state.discussed_entities)
                if song_entity:
                    expression = self.choose(EXPRESS_INTEREST_OTHER_SONG)
                    expression = expression.replace(f"SONG_{WikiEntityInterface.ENTITY_PLACEHOLDER}", song_entity.pref_label)
                    expression = expression.replace(f"MUSICIAN_{WikiEntityInterface.ENTITY_PLACEHOLDER}", musician_entity.pref_label)
                    question = self.choose(QUESTION_OTHER_SONGS)
                    question = question.replace(WikiEntityInterface.ENTITY_PLACEHOLDER, musician_entity.pref_label)
                    rg_result.text = f"{response} {expression} {question}"
                    rg_result.cur_entity = song_entity.wiki_entity
                    rg_result.conditional_state.needs_internal_prompt = False
                    rg_result.conditional_state.next_treelet = self.name
                    rg_result.conditional_state.asked_question = 'QuestionWhichOfTheirSongsDoYouLike'
            elif state.num_repeats < REPEAT_THRESHOLD:
                response = self.choose(QUESTION_COULD_YOU_REPEAT)
                rg_result = self.prepare_rg_result(response, state)
                rg_result.conditional_state.repeated_question = True
                rg_result.conditional_state.needs_internal_prompt = False
                rg_result.conditional_state.next_treelet = self.name
                rg_result.conditional_state.asked_question = 'QuestionLikedMusicianTemplate'
            else:
                response = self.choose(ACKNOWLEDGE_COULDNT_GET_MUSICIAN)
                rg_result = self.prepare_rg_result(response, state)
                rg_result.priority = ResponsePriority.WEAK_CONTINUE
                rg_result.conditional_state.needs_internal_prompt = False

        return rg_result
Esempio n. 8
0
    def get_response_trigger_phrase(self, state, trigger_phrase=None):
        utterance = self.state_manager.current_state.text
        triggered_templates = self.process_templates(QUESTION_TEMPLATES,
                                                     utterance)
        sentiment_answers = self.process_templates(SENTIMENT_TEMPLATES,
                                                   utterance)
        triggered_templates = {**triggered_templates, **sentiment_answers}
        undiscussed_items = [
            title for title in EXAMPLE_SONG_WIKI_PAGES
            if not WikiEntityInterface.is_title_in_entities(
                title, state.discussed_entities)
        ]
        trigger_entity = None
        if trigger_phrase:
            trigger_entity = WikiEntityInterface.link_span(trigger_phrase)
            if trigger_entity and not WikiEntityInterface.is_in_entity_group(
                    trigger_entity, WikiEntityInterface.EntityGroup.SONG):
                trigger_entity = None

        response = None
        if 'QuestionFavoriteSongTemplate' in triggered_templates:
            response = self._handle_question_favorite(state,
                                                      triggered_templates)
        elif trigger_entity:
            response = self.get_response_trigger_entity(state, trigger_entity)
        elif undiscussed_items:
            song_title, song_kid = undiscussed_items[0]
            cur_entity = WikiEntityInterface.get_by_name(song_title)
            if cur_entity:
                question = self.choose(QUESTION_DO_YOU_LIKE_POPULAR)
                question = question.replace(
                    WikiEntityInterface.ENTITY_PLACEHOLDER,
                    cur_entity.common_name)
                response = self.prepare_rg_result(question,
                                                  state,
                                                  cur_entity=cur_entity)
                response.conditional_state.song_entity = MusicEntity(
                    pref_label=cur_entity.common_name,
                    wiki_entity=cur_entity,
                    kid=song_kid)
                response.conditional_state.discussed_entities.append(
                    cur_entity)
                response.conditional_state.asked_question = 'QuestionWhyDoYouLikeSong'  # This is the handler function for the question we are asking.
                response.conditional_state.next_treelet = self.name
                response.conditional_state.needs_internal_prompt = False

        if not response:
            response = self._handle_expression_chat_song(state, None)

        return response
Esempio n. 9
0
    def get_musician(song_name):

        # Try to find the musician from the Wiki overview.
        musician_name = WikiEntityInterface.extract_musician_name_from_song_overview(song_name)

        if musician_name:
            wiki_entity = WikiEntityInterface.link_span(musician_name)
            if wiki_entity and WikiEntityInterface.is_in_entity_group(wiki_entity, WikiEntityInterface.EntityGroup.MUSICIAN):
                musician_entity = MusicEntity(pref_label=wiki_entity.common_name, wiki_entity=wiki_entity)
                return musician_entity

        # Try to find in Knowledge graph
        musician_entity = KnowledgeInterface().get_musician_entity_by_song(song_name)
        return musician_entity
Esempio n. 10
0
    def _handle_answer_liked_songs(self, state, triggered_templates):
        question_name = 'QuestionWhichOfTheirSongsDoYouLike'
        cur_entity = self.state_manager.current_state.entity_tracker.cur_entity
        current_state = self.state_manager.current_state
        user_initiated = current_state.entity_tracker.cur_entity_initiated_by_user_this_turn(current_state)

        if cur_entity and user_initiated and WikiEntityInterface.is_in_entity_group(cur_entity, WikiEntityInterface.EntityGroup.SONG):
            response = self.choose(ACKNOWLEDGE_LIKED_SONGS)
            rg_result = self.prepare_rg_result(response, state)
        else:
            response = self.choose(ACKNOWLEDGE_LIKED_SONGS_NEGATIVE)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.needs_prompt = True

        return rg_result
Esempio n. 11
0
    def _handle_answer_favorite_question(self, state, triggered_answers):
        question_name = 'QuestionFavoriteInstrumentTemplate'

        # Check if the user mentioned an instrument.
        cur_entity = self.state_manager.current_state.entity_tracker.cur_entity
        instrument_entity = None
        if cur_entity and WikiEntityInterface.is_in_entity_group(
                cur_entity, WikiEntityInterface.EntityGroup.INSTRUMENT):
            instrument_entity = cur_entity
        elif question_name in triggered_answers and 'answer' in triggered_answers[
                question_name]:
            instrument_name = triggered_answers[question_name]['answer']
            instrument_entity = WikiEntityInterface.link_span(
                instrument_name.capitalize())

        # If the user mentioned an instrument, ask a follow up question.
        if instrument_entity:
            response = self.choose(ACKNOWLEDGE_FAVORITE_INSTRUMENT)
            followup = self.choose(FAVORITE_INSTRUMENT_FOLLOWUP_QUESTIONS)
            response = "{} {}".format(response, followup)
            response = response.replace(WikiEntityInterface.ENTITY_PLACEHOLDER,
                                        instrument_entity.common_name)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.cur_entity = instrument_entity
            rg_result.conditional_state.asked_question = 'QuestionFavoriteInstrumentTemplate Followup 1'
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.conditional_state.next_treelet = self.name
        # If not, acknowledge the user response and exit the Music RG.
        elif self.is_no_answer(
        ) or 'NegativeTemplate' in triggered_answers or 'DontKnowTemplate' in triggered_answers:
            response = self.choose(ACKNOWLEDGE_FAVORITE_INSTRUMENT_NEGATIVE)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.needs_prompt = True
        else:
            response = self.choose(ACKNOWLEDGE_FAVORITE_INSTRUMENT_NEVER_HEARD)
            rg_result = self.prepare_rg_result(response, state)
            rg_result.conditional_state.needs_internal_prompt = False
            rg_result.needs_prompt = True

        return rg_result