コード例 #1
0
    def check_reject_intent(self, user_utterance):
        """

        Args:
            utterance: 

        """
        # checking for intent = 'reject'
        tokens = user_utterance.get_tokens()
        utterance = sum(tokens).lemma if tokens else ''
        user_dacts = []
        dact = DialogueAct(UserIntents.UNK, [])
        if any([
                re.search(r'\b{0}\b'.format(pattern), utterance)
                for pattern in self.dontlike_movie_pattern
        ]):
            dact.intent = UserIntents.REJECT
            dact.params = [ItemConstraint('reason', Operator.EQ, 'dont_like')]
        elif any([
                re.search(r'\b{0}\b'.format(pattern), utterance)
                for pattern in self.watched_pattern
        ]):
            dact.intent = UserIntents.REJECT
            dact.params = [ItemConstraint('reason', Operator.EQ, 'watched')]
        if dact.intent != UserIntents.UNK:
            user_dacts.append(dact)
        return user_dacts
コード例 #2
0
ファイル: nlg.py プロジェクト: iai-group/moviebot
    def _user_options_recommend(self):
        """Give use button options when making a recommendation
        
        Returns:
            a list of button options

        """
        options = {
            DialogueAct(UserIntents.REJECT, [
                ItemConstraint('reason', Operator.EQ, 'watched')
            ]): ['I have already watched it.'],
            # [random.choice(['I have already watched it.',
            #                 'I have seen this already.'])],
            DialogueAct(UserIntents.REJECT, [
                ItemConstraint('reason', Operator.EQ, 'dont_like')
            ]): ['Recommend me something else please.'],
            # [random.choice(['I don\'t like this recommendation.',
            #                 'Recommend me something else please.'])],
            DialogueAct(UserIntents.ACCEPT, []):
            ['I like this recommendation.'],
            DialogueAct(UserIntents.INQUIRE, [
                ItemConstraint(Slots.MORE_INFO.value, Operator.EQ, '')
            ]): [
                random.choice(
                    ['Tell me something about it.', 'Tell me more about it.'])
            ]
        }
        options.update({'/restart': ['/restart']})
        return options
コード例 #3
0
    def check_reveal_intent(self, user_utterance, last_agent_dact):
        """This function is only called if the intent of agent is ELicit to see
        if user has answered the query

        Args:
            utterance: 
            raw_utterance: 
            last_agent_dact: 

        """
        user_dacts = []
        for param in last_agent_dact.params:
            dact = DialogueAct(UserIntents.UNK, [])
            slot = param.slot
            params = self.slot_annotator.slot_annotation(slot, user_utterance)
            if params:
                dact.intent = UserIntents.REVEAL
                dact.params.extend(params)
            if dact.intent == UserIntents.UNK and self.is_dontcare(
                    user_utterance):
                dact.intent = UserIntents.REVEAL
                dact.params.append(
                    ItemConstraint(param.slot, Operator.EQ, Values.DONT_CARE))
            if dact.intent != UserIntents.UNK:
                # print(f'All Dacts\n{dact}')
                self._filter_dact(dact, user_utterance.get_text())
                # print(f'Filtered Dacts\n{dact}')
                if len(dact.params) > 0:
                    user_dacts.append(dact)
            else:
                dact.intent = UserIntents.REVEAL
                dact.params.append(
                    ItemConstraint(param.slot, Operator.EQ, Values.NOT_FOUND))
                user_dacts.append(dact)
        return user_dacts
コード例 #4
0
    def generate_params_continue_recommendation(self, item_in_focus):
        """

        Args:
            item_in_focus: 

        """
        movie_title = item_in_focus[Slots.TITLE.value]
        results = wikipedia.search(f'I need a film similar to {movie_title}',
                                   20)
        results = [r.split('(')[0].strip() for r in results]
        for result in deepcopy(results):
            if result not in self.slot_values[Slots.TITLE.value]:
                results.remove(result)
        if len(results) > 0:
            return [
                ItemConstraint(Slots.TITLE.value, Operator.EQ, str(results))
            ]
        else:
            results = wikipedia.search(
                f'I need a movie similar to {movie_title}', 20)
            results = [r.split('(')[0].strip() for r in results]
            for result in deepcopy(results):
                if result not in self.slot_values[Slots.TITLE.value]:
                    results.remove(result)
            if len(results) > 0:
                return [
                    ItemConstraint(Slots.TITLE.value, Operator.EQ,
                                   str(results))
                ]
コード例 #5
0
    def check_inquire_intent(self, user_utterance):
        """

        Args:
            utterance: 

        """
        # matching intents to 'list', 'Summarize', 'Subset', 'Compare' and
        # 'Similar'
        tokens = user_utterance.get_tokens()
        utterance = sum(tokens).lemma if tokens else ''
        user_dacts = []
        dact = DialogueAct(UserIntents.UNK, [])
        for slot, values in self.tag_words_user_inquire.items():
            if any([value for value in values if value in utterance]):
                dact.intent = UserIntents.INQUIRE
                dact.params.append(ItemConstraint(slot, Operator.EQ, ''))
        if dact.intent == UserIntents.UNK:  # and self._is_question(raw_utterance):
            for slot, values in self.tag_words_user_reveal_inquire.items():
                if any([value for value in values if value in utterance]):
                    dact.intent = UserIntents.INQUIRE
                    dact.params.append(ItemConstraint(slot, Operator.EQ, ''))
        if dact.intent != UserIntents.UNK:
            user_dacts.append(dact)
        return user_dacts
コード例 #6
0
    def _title_annotator(self, slot, user_utterance):
        """This annotator is used to check the movie title.
        Sometimes the user can just enter a part of the name.

        Args:
            slot: 
            utterance: 

        """
        tokens = user_utterance.get_tokens()
        values = self.slot_values[slot]
        processed_values = set(values.values())
        # split into n-grams
        for ngram_size in range(min(self.ngram_size[slot], len(tokens)), 0,
                                -1):
            options = {}
            for gram_list in ngrams(tokens, ngram_size):
                gram = sum(gram_list).lemma
                for processed_value in processed_values:
                    if processed_value == gram and len([
                            x.lemma
                            for x in gram_list if x.lemma in self.stop_words
                    ]) < ngram_size:
                        annotation = SemanticAnnotation.from_span(
                            sum(gram_list), AnnotationType.NAMED_ENTITY,
                            EntityType.TITLE)
                        param = ItemConstraint(slot, Operator.EQ, gram,
                                               annotation)
                        return [param]
                if len([x for x in gram_list if x.lemma in self.stop_words
                        ]) == 0 and len(
                            [int(val)
                             for val in re.findall(r'\b\d+', gram)]) == 0:
                    # check if
                    # all words are in the list of stop words and no numbers
                    if ngram_size == 1:
                        gram_occurrence = len([
                            value for value in processed_values
                            if gram == value
                        ])
                    else:
                        gram_occurrence = len([
                            value for value in processed_values
                            if f' {gram} ' in f' {value} '
                        ])
                    if gram_occurrence:
                        options[gram] = gram_occurrence
            if options:
                options = {
                    k: v
                    for k, v in sorted(options.items(),
                                       key=lambda item: item[1])
                }
                for gram in options:
                    param = ItemConstraint(slot, Operator.EQ, gram.strip())
                    return [param]
コード例 #7
0
    def _filter_genres(self, dact):
        """

        Args:
            dact: 

        """
        for param in dact.params:
            values = []
            if param.slot == Slots.GENRES.value:
                values = param.value.split()
                param.value = values[0] if values[0] in self.slot_values[Slots.GENRES.value] else \
                    self.slot_annotator.genres_alternatives[values[0]]
            if len(values) > 1:
                for value in values[1:]:
                    if value not in [
                            p.value for p in dact.params
                            if p.slot == param.slot
                    ]:
                        if value not in self.slot_values[Slots.GENRES.value]:
                            value = self.slot_annotator.genres_alternatives[
                                value]
                        dact.params.append(
                            ItemConstraint(Slots.GENRES.value, Operator.EQ,
                                           value))
コード例 #8
0
    def _get_annotation_relevance(self, dact, raw_utterance, dual_person):
        """Get the relevance if user really want a preference or wants to remove
        it from the list

        Args:
            dact: 
            raw_utterance: 
            dual_person: 

        """
        words_seq = word_tokenize(raw_utterance)
        # first sequence the params:
        values = sorted([p.value for p in dact.params], key=raw_utterance.find)
        words_pre_req = dict.fromkeys(values)
        next_ind = 0
        for val in words_pre_req:
            end_ind = raw_utterance.find(val)
            pre_req = raw_utterance[next_ind:end_ind]
            words_pre_req[val] = self._process_utterance(pre_req)
            next_ind = end_ind + len(val)
        param_dontwant = []
        for value, pre_req in words_pre_req.items():
            if any([
                    re.search(r'\b{0}\b'.format(pattern), pre_req)
                    for pattern in self.dontwant_pattern
            ]):
                param_dontwant.append(value)
        if dual_person and len(dual_person) > 0:
            for value in dual_person:
                if any([
                        re.search(r'\b{0}\b'.format(pattern),
                                  words_pre_req[value])
                        for pattern in self.tag_words_user_reveal_inquire[
                            Slots.DIRECTORS.value]
                ]):
                    self._remove_param(
                        ItemConstraint(Slots.ACTORS.value, Operator.EQ, value),
                        dact)
                elif any([
                        re.search(r'\b{0}\b'.format(pattern),
                                  words_pre_req[value]) for pattern in
                        self.tag_words_user_reveal_inquire[Slots.ACTORS.value]
                ]):
                    self._remove_param(
                        ItemConstraint(Slots.DIRECTORS.value, Operator.EQ,
                                       value), dact)
        return param_dontwant
コード例 #9
0
    def start_dialogue(self, new_user=False):
        """Starts the dialogue by generating a response from the agent
        
        :return: First agent response

        Args:
            new_user:  (Default value = False)

        """
        self.dialogue_state_tracker.dialogue_state.initialize()
        self.dialogue_state_tracker.dialogue_context.initialize()
        agent_dact = DialogueAct(AgentIntents.WELCOME, [
            ItemConstraint('new_user', Operator.EQ, new_user),
            ItemConstraint('is_bot', Operator.EQ, self.isBot)
        ])
        self.dialogue_state_tracker.update_state_agent([agent_dact])
        return [agent_dact]
コード例 #10
0
    def _keywords_annotator(self, slot, user_utterance):
        """This annotator is used to check the movie keywords.
        If the ngram has only keywords, it will be ignored.

        Args:
            slot: 
            utterance: 

        """
        tokens = user_utterance.get_tokens()
        values = self.slot_values[slot]
        for ngram_size in range(min(self.ngram_size[slot], len(tokens)), 0,
                                -1):
            for gram_list in ngrams(tokens, ngram_size):
                gram = sum(gram_list).lemma

                # TODO (Ivica Kostric): maybe 'no numbers' should be changed
                # since there are some numbers in keywords (.44, 007, age).
                # Same goes for stopwords. There are some stopwords as part of
                # keywords.
                # Alternatively, there is possibility to put a stopword flag
                # directly on tokens beforehand.

                if len([int(val)
                        for val in re.findall(r'\b\d+', gram)]) == 0 and len([
                            x.lemma
                            for x in gram_list if x.lemma in self.stop_words
                        ]) == 0:

                    for _, lem_value in values.items():
                        if lem_value == gram:
                            annotation = SemanticAnnotation.from_span(
                                sum(gram_list), AnnotationType.KEYWORD)
                            param = ItemConstraint(slot, Operator.EQ, gram,
                                                   annotation)

                            return [param]
                        elif (ngram_size == 1 and gram == lem_value) or (
                                ngram_size > 1
                                and f' {gram} ' in f' {lem_value} '):
                            annotation = SemanticAnnotation.from_span(
                                sum(gram_list), AnnotationType.KEYWORD)
                            param = ItemConstraint(slot, Operator.EQ, gram,
                                                   annotation)
                            return [param]
コード例 #11
0
ファイル: nlg.py プロジェクト: IKostric/moviebot
    def _user_options_inquire(self, dialogue_state):
        """

        Args:
            dialogue_state: 

        Returns:
            list of user requestables as buttons

        """
        options = {}
        requestables = {
            Slots.GENRES.value: 'genres',
            Slots.PLOT.value: 'movie plot',
            Slots.DIRECTORS.value: 'director name',
            Slots.DURATION.value: 'duration',
            Slots.ACTORS.value: 'list of actors',
            Slots.YEAR.value: 'release year',
            Slots.RATING.value: 'rating'
        }
        for slot in dialogue_state.user_requestable:
            dact = DialogueAct(UserIntents.INQUIRE,
                               [ItemConstraint(slot, Operator.EQ, '')])
            options[dact] = requestables.get(slot, 'Invalid slot')
        options.update({
            DialogueAct(UserIntents.REJECT, [
                ItemConstraint('reason', Operator.EQ, 'dont_like')
            ]): ['I don\'t like this recommendation.'],
            # [random.choice(['I don\'t like this recommendation.',
            #                 'Recommend me something else please.'])],
            DialogueAct(UserIntents.ACCEPT, []): [
                'I like this recommendation.'
            ],
            DialogueAct(UserIntents.CONTINUE_RECOMMENDATION, []): [
                "I would like a similar recommendation."
            ],
            DialogueAct(UserIntents.RESTART, []): [
                'I want to restart for a new movie.'
            ],
        })
        return options
コード例 #12
0
    def _person_name_annotator(self, user_utterance, slots=None):
        """This annotator is used to check the movie actor and/or director
        names. Sometimes the user can just enter a part of the name.

        Args:
            utterance: 
            slots:  (Default value = None)

        """
        tokens = user_utterance.get_tokens()
        if not slots:
            slots = [Slots.ACTORS.value, Slots.DIRECTORS.value]
            person_names = self.person_names
        else:
            slots = [slots]
            person_names = self.slot_values[slots]
        params = []
        for ngram_size in range(self.ngram_size['person'], 0, -1):
            for gram_list in ngrams(tokens, ngram_size):
                gram = sum(gram_list).lemma
                for _, lem_value in person_names.items():
                    if f' {gram} ' in f' {lem_value} ' and \
                        gram not in self.stop_words:
                        # gramR = self.find_in_raw_utterance(raw_utterance,
                        #                                   ngram_size,
                        #                                   gram)
                        for slot in slots:
                            if gram in self.slot_values[slot].values():
                                annotation = SemanticAnnotation.from_span(
                                    sum(gram_list),
                                    AnnotationType.NAMED_ENTITY,
                                    EntityType.PERSON)
                                params.append(
                                    ItemConstraint(slot, Operator.EQ, gram,
                                                   annotation))
                        break
            if len(params) > 0:
                return params
コード例 #13
0
    def _genres_annotator(self, slot, user_utterance):
        """

        Args:
            slot: 
            utterance: 

        """
        param = None
        values = self.slot_values[slot]
        tokens = user_utterance.get_tokens()
        for i in range(len(tokens)):
            for value, lem_value in values.items():
                len_lem_value = len(lem_value.split())
                token = tokens[i] if len_lem_value == 1 else sum(
                    tokens[i:i + len_lem_value])

                if token.lemma.startswith(lem_value):
                    annotation = SemanticAnnotation.from_span(
                        token, AnnotationType.NAMED_ENTITY, EntityType.GENRES)
                    if param:
                        param.add_value(value.lower(), annotation)
                    else:
                        param = ItemConstraint(slot, Operator.EQ,
                                               value.lower(), annotation)

            # TODO(Ivica Kostric): This could be merged with the main genre
            # dictionary at initialization time.
            for key, value in self.genres_alternatives.items():
                len_key = len(key.split())
                token = tokens[i] if len_key == 1 else sum(tokens[i:i +
                                                                  len_key])

                if token.lemma.startswith(self._process_value(key)):
                    annotation = SemanticAnnotation.from_span(
                        token, AnnotationType.NAMED_ENTITY, EntityType.GENRES)
                    if param:
                        param.add_value(key.lower(), annotation)
                    else:
                        param = ItemConstraint(slot, Operator.EQ, key.lower(),
                                               annotation)

        if param:
            return [param]
コード例 #14
0
ファイル: dialogue_policy.py プロジェクト: iai-group/moviebot
    def next_action(self,
                    dialogue_state,
                    dialogue_context=None,
                    restart=False):
        """Decides the next action to be taken by the agent based on the current state and context.

        Args:
            dialogue_state: current dialogue state
            dialogue_context: context of the dialogue (Default value = None)
            restart:  (Default value = False)

        Returns:
            a list of Dialogue Acts

        """
        agent_dacts = []
        slots = deepcopy(dialogue_state.agent_requestable)
        if not dialogue_state.last_user_dacts and not restart:
            agent_dacts.append(
                DialogueAct(AgentIntents.WELCOME, [
                    ItemConstraint('new_user', Operator.EQ, self.new_user),
                    ItemConstraint('is_bot', Operator.EQ, self.isBot)
                ]))
            return agent_dacts

        if not dialogue_state.last_agent_dacts and not restart:
            if not dialogue_state.last_agent_dacts:
                agent_dacts.append(
                    DialogueAct(AgentIntents.WELCOME, [
                        ItemConstraint('new_user', Operator.EQ, self.new_user),
                        ItemConstraint('is_bot', Operator.EQ, self.isBot)
                    ]))

        if (not dialogue_state.last_user_dacts and restart) or \
                (dialogue_state.last_user_dacts and UserIntents.RESTART in
                 [dact.intent for dact in dialogue_state.last_user_dacts]):
            agent_dacts.append(DialogueAct(AgentIntents.RESTART, []))
            agent_dacts.append(
                DialogueAct(AgentIntents.ELICIT,
                            [ItemConstraint(slots[0], Operator.EQ, '')]))
            return agent_dacts

        for user_dact in dialogue_state.last_user_dacts:
            agent_dact = DialogueAct(AgentIntents.UNK, [])
            # generating intent = "bye"
            if user_dact.intent == UserIntents.BYE:
                agent_dact.intent = AgentIntents.BYE
                agent_dacts.append(deepcopy(agent_dact))
                return agent_dacts

            # generating intent = "elicit"
            if user_dact.intent == UserIntents.ACKNOWLEDGE or user_dact.intent == \
                    UserIntents.UNK:
                if AgentIntents.WELCOME in [
                        dact.intent for dact in dialogue_state.last_agent_dacts
                ]:
                    agent_dact.intent = AgentIntents.ELICIT
                    agent_dact.params.append(
                        ItemConstraint(slots[0], Operator.EQ, ''))
                    agent_dacts.append(deepcopy(agent_dact))
                    return agent_dacts

            # deciding between intent "elicit" or "recommend"
            if dialogue_state.agent_made_partial_offer:  # agent will inform about number of
                CIN_slots = [
                    key for key in dialogue_state.frame_CIN.keys()
                    if not dialogue_state.frame_CIN[key]
                    and key != Slots.TITLE.value
                ]
                if len(
                        CIN_slots
                ) >= dialogue_state.slot_left_unasked:  # if there is a scope of
                    # further questioning
                    # results and will ask next question
                    agent_dact.intent = AgentIntents.COUNT_RESULTS
                    agent_dact.params.append(
                        ItemConstraint('count', Operator.EQ,
                                       len(dialogue_state.database_result)))
                    agent_dacts.append(deepcopy(agent_dact))
                    # adding another dialogue act of ELICIT
                    if dialogue_state.agent_req_filled:
                        random.shuffle(CIN_slots)
                        agent_dact = DialogueAct(AgentIntents.ELICIT, [])
                        agent_dact.params.append(
                            ItemConstraint(CIN_slots[0], Operator.EQ, ""))
                        agent_dacts.append(deepcopy(agent_dact))
                    else:
                        agent_dact = DialogueAct(AgentIntents.ELICIT, [])
                        random.shuffle(slots)
                        for slot in slots:
                            if not dialogue_state.frame_CIN[slot]:
                                agent_dact.params.append(
                                    ItemConstraint(slot, Operator.EQ, ''))
                                break
                        agent_dacts.append(deepcopy(agent_dact))

                else:
                    agent_dact = DialogueAct(AgentIntents.RECOMMEND, [])
                    item_in_focus = dialogue_state.database_result[0]
                    agent_dact.params.append(
                        ItemConstraint(Slots.TITLE.value, Operator.EQ,
                                       item_in_focus[Slots.TITLE.value]))
            elif dialogue_state.agent_should_make_offer:
                agent_dact.intent = AgentIntents.RECOMMEND
                agent_dact.params.append(
                    ItemConstraint(
                        Slots.TITLE.value, Operator.EQ,
                        dialogue_state.item_in_focus[Slots.TITLE.value]))
                agent_dacts.append(deepcopy(agent_dact))
            elif dialogue_state.agent_offer_no_results:
                agent_dact.intent = AgentIntents.NO_RESULTS
                agent_dacts.append(deepcopy(agent_dact))
            elif dialogue_state.agent_made_offer:
                if user_dact.intent == UserIntents.INQUIRE:
                    agent_dact.intent = AgentIntents.INFORM
                    for param in user_dact.params:
                        if param.slot != Slots.MORE_INFO.value:
                            agent_dact.params.append(
                                ItemConstraint(
                                    param.slot, Operator.EQ,
                                    dialogue_state.item_in_focus[param.slot]))
                        else:
                            agent_dact.params.append(
                                ItemConstraint(
                                    param.slot, Operator.EQ,
                                    dialogue_state.item_in_focus[
                                        Slots.TITLE.value]))
                    if len(agent_dact.params) == 0:
                        agent_dact.params.append(
                            ItemConstraint(
                                'deny', Operator.EQ,
                                dialogue_state.item_in_focus[
                                    Slots.TITLE.value]))
                    agent_dacts.append(deepcopy(agent_dact))
                # elif user_dact.intent == UserIntents.REVEAL and Slots.TITLE.value in [param.slot for
                #                                                                      param in
                #                                                                      user_dact.params]:
                #     agent_dact.intent = AgentIntents.INFORM
                #     agent_dact.params.append(ItemConstraint(Slots.MORE_INFO.value, Operator.EQ,
                #                                             dialogue_state.item_in_focus[
                #                                                 Slots.TITLE.value]))
                #     agent_dacts.append(deepcopy(agent_dact))
                elif user_dact.intent == UserIntents.ACCEPT:
                    agent_dact.intent = AgentIntents.CONTINUE_RECOMMENDATION
                    agent_dact.params.append(
                        ItemConstraint(
                            Slots.TITLE.value, Operator.EQ,
                            dialogue_state.item_in_focus[Slots.TITLE.value]))
                    agent_dacts.append(deepcopy(agent_dact))

            if agent_dact.intent == AgentIntents.UNK:
                if not dialogue_state.agent_req_filled and user_dact.intent != UserIntents.HI:
                    agent_dact.intent = AgentIntents.ELICIT
                    # random.shuffle(slots)
                    for slot in slots:
                        if not dialogue_state.frame_CIN[slot]:
                            agent_dact.params.append(
                                ItemConstraint(slot, Operator.EQ, ''))
                            break
                elif user_dact.intent == UserIntents.UNK:
                    agent_dact.intent = AgentIntents.CANT_HELP
                if agent_dact.intent != AgentIntents.UNK:
                    agent_dacts.append(deepcopy(agent_dact))

        if len(agent_dacts) == 0:
            agent_dacts.append(DialogueAct(AgentIntents.CANT_HELP, []))
        # Adding example:
        for agent_dact in agent_dacts:
            if agent_dact.intent == AgentIntents.ELICIT and \
                    agent_dact.params[0].slot not in [Slots.YEAR.value]:
                if dialogue_state.database_result:
                    agent_dact.params[0].value = self._generate_examples(
                        dialogue_state.database_result,
                        agent_dact.params[0].slot)
        return agent_dacts
コード例 #15
0
ファイル: nlg.py プロジェクト: iai-group/moviebot
    def _user_options_remove_preference_CIN(self, CIN):
        """Generate options for user to select a parameter to remove

        Args:
            CIN: The current information needs

        Returns:
            a list of button options

        """
        options = {}
        params = []
        for slot, values in CIN.items():
            if not values:
                continue
            if isinstance(values, list):
                params.extend([
                    ItemConstraint(slot, Operator.EQ, value)
                    for value in set(values)
                    if value not in Values.__dict__.values()
                    and not value.startswith('.NOT.')
                ])
            else:
                if values not in Values.__dict__.values(
                ) and not values.startswith('.NOT.'):
                    params.append(ItemConstraint(slot, Operator.EQ, values))

        for param in params:
            value = deepcopy(param.value)
            negative = False
            if value.startswith('.NOT.'):
                negative = True  # TODO. Add changes here
                value = value.replace('.NOT.', '')
            _a_an = 'an' if value[0] in ['a', 'e', 'i', 'o', 'u'] else 'a'
            param_key = DialogueAct(UserIntents.REMOVE_PREFERENCE, [param])
            if param.slot == Slots.GENRES.value:
                if negative:
                    options[param_key] = [
                        random.choice([
                            f'I want {_a_an} "{value}" movie.',
                            f'I would prefer {_a_an} "{value}" '
                            f'film.'
                        ])
                    ]
                else:
                    options[param_key] = [
                        random.choice([
                            f'Don\'t want {_a_an} "{value}" '
                            f'movie.', f'Won\'t prefer {_a_an} "{value}" film.'
                        ])
                    ]
            elif param.slot == Slots.TITLE.value:
                if negative:
                    options[param_key] = [
                        f'I want movies named like "{value}".'
                    ]
                else:
                    options[param_key] = [f'No movies named like "{value}".']
            elif param.slot == Slots.KEYWORDS.value:
                if negative:
                    options[param_key] = [f'I need movies based on "{value}".']
                else:
                    options[param_key] = [
                        random.choice([
                            f'Don\'t need movies based on '
                            f'"{value}".',
                            f'No need of {_a_an} "{value}" film.'
                        ])
                    ]
            elif param.slot == Slots.DIRECTORS.value:
                if negative:
                    options[param_key] = [
                        random.choice([
                            f'I want the director "{value.title()}".',
                            f'Should be directed by "{value.title()}".'
                        ])
                    ]
                else:
                    options[param_key] = [
                        random.choice([
                            f'Don\'t want the director "{value.title()}".',
                            f'Shouldn\'t be directed by "{value.title()}".'
                        ])
                    ]
            elif param.slot == Slots.ACTORS.value:
                if negative:
                    options[param_key] = [
                        f'I want the actor "{value.title()}".'
                    ]
                else:
                    options[param_key] = [
                        random.choice([
                            f'Don\'t consider actor "{value.title()}".',
                            f'Remove "{value.title()}" from the list of actors.'
                        ])
                    ]
            elif param.slot == Slots.YEAR.value:
                if negative:
                    options[param_key] = [
                        random.choice([
                            f'Release year should be the "'
                            f'{self._summarize_title_year(value)}".',
                            f'Need a movie from the "'
                            f'{self._summarize_title_year(value)}".'
                        ])
                    ]
                else:
                    options[param_key] = [
                        random.choice([
                            f'Release year shouldn\'t be the "'
                            f'{self._summarize_title_year(value)}".',
                            f'Don\'t need a movie from the "'
                            f'{self._summarize_title_year(value)}".'
                        ])
                    ]
            options.update({'/restart': ['/restart']})
        return options
コード例 #16
0
    def _year_annotator(self, slot, user_utterance):
        """

        Args:
            slot:
            user_utterance:
            utterance:

        """
        tokens = user_utterance.get_tokens()
        potential_item_constraint = []
        for token in tokens:
            annotation = SemanticAnnotation.from_span(token,
                                                      AnnotationType.TEMPORAL)
            if token.lemma.startswith(('new', 'latest')):
                potential_item_constraint.append(
                    ItemConstraint(slot, Operator.GT, '2010', annotation))
            if token.lemma.startswith('old'):
                potential_item_constraint.append(
                    ItemConstraint(slot, Operator.LT, '2010', annotation))

            if not token.lemma[:2].isdigit():
                continue

            if token.text[-1] == 's':
                year = token.text[:-1]
                if not year.isdigit():
                    continue

                # check if its for example 90s or 1990s
                if len(year) == 2:
                    year = '20' + year if int(year) <= 20 else '19' + year
                elif len(year) != 4:
                    continue

                if year[-1] == '0':
                    return [
                        ItemConstraint(slot, Operator.BETWEEN,
                                       f'{year} AND {str(int(year) + 10)}',
                                       annotation)
                    ]
                else:
                    return [
                        ItemConstraint(slot, Operator.EQ, year, annotation)
                    ]

            if token.text[-2:] == 'th':
                year = token.text[:-2]
                if year.isdigit() and len(year) == 2:
                    return [
                        ItemConstraint(
                            slot, Operator.BETWEEN,
                            f'{str(int(year) - 1)}00 AND'
                            f' {year}00', annotation)
                    ]

            if token.text.isdigit() and len(token.text) == 4:
                return [
                    ItemConstraint(slot, Operator.EQ, token.text, annotation)
                ]

        return potential_item_constraint[:1]