Esempio n. 1
0
    def __init__(self):
        self.builder = StatementBuilder()
        self.adder = StatementSafeAdder()
        self.question_handler = QuestionHandler()
        self.sfactory = SentenceFactory()

        self.output_sentence = []
Esempio n. 2
0
    def _references_resolution_replace_current_object_with_ua_exception(
            self, sentence, uae_object, uae_object_with_more_info,
            uae_object_list):
        """This attempts to replace a nominal group that has failled from identifying the anaphoric word with one that holds more information.
        """

        current_object = None

        if uae_object_with_more_info[1]:
            current_object = uae_object_with_more_info[0]
        else:
            sf = SentenceFactory()
            raise UnidentifiedAnaphoraError({
                'object':
                uae_object,
                'object_to_confirm':
                uae_object_with_more_info[0],
                'object_with_more_info':
                None,
                'objects_list':
                uae_object_list,
                'sentence':
                sentence,
                'question':
                sf.create_do_you_mean_reference(uae_object_with_more_info[0])
            })

        return current_object
Esempio n. 3
0
    def _references_resolution_with_anaphora_matcher(self, nominal_group,
                                                     matcher, current_speaker,
                                                     current_object):
        """ This attempts to match the nominal group containing anaphoric words
        with an object identifed from the dialog history.

        If several candidates are found, a confirmation is asked to user.
        """
        if current_object:
            self._current_object = None
            return current_object

        # Trying to match anaphora
        if not self.sentences_store:
            raise DialogError("Empty Dialog history")

        sf = SentenceFactory()

        #object = [ng, [List]]
        #       Where ng is the first nominal group to match with the anaphoric word
        #       and List contains nominal group that are to be explored if ng is not confirmed from the user

        object = matcher.match_first_object(get_last(self.sentences_store, 10),
                                            nominal_group)

        if not object:
            raise DialogError("No anaphora matches in dialog history")

        # Case there exist only one nominal group identified from anaphora matching
        if len(object[1]) == 1:
            nominal_group = object[0]
            logger.debug("Found anaphoric match " + str(nominal_group))

        # Else, ask for confirmation to the user
        else:
            raise UnidentifiedAnaphoraError({
                'object':
                nominal_group,
                'object_to_confirm':
                object[0],
                'object_with_more_info':
                None,
                'objects_list':
                object[1],
                'sentence':
                self._current_sentence,
                'question':
                sf.create_do_you_mean_reference(object[0])
            })

        ResourcePool().mark_active(nominal_group.id)
        return nominal_group
Esempio n. 4
0
    def __init__(self):
        self.builder = StatementBuilder()
        self.adder = StatementSafeAdder()
        self.question_handler = QuestionHandler()
        self.sfactory = SentenceFactory()

        self.output_sentence = []
Esempio n. 5
0
    def _references_resolution_replace_current_object_with_ua_exception(self, sentence, uae_object,
                                                                        uae_object_with_more_info, uae_object_list):
        """This attempts to replace a nominal group that has failled from identifying the anaphoric word with one that holds more information.
        """

        current_object = None

        if uae_object_with_more_info[1]:
            current_object = uae_object_with_more_info[0]
        else:
            sf = SentenceFactory()
            raise UnidentifiedAnaphoraError({'object': uae_object,
                                             'object_to_confirm': uae_object_with_more_info[0],
                                             'object_with_more_info': None,
                                             'objects_list': uae_object_list,
                                             'sentence': sentence,
                                             'question': sf.create_do_you_mean_reference(uae_object_with_more_info[0])})

        return current_object
Esempio n. 6
0
    def _references_resolution_with_anaphora_matcher(self, nominal_group, matcher, current_speaker, current_object):
        """ This attempts to match the nominal group containing anaphoric words
        with an object identifed from the dialog history.

        If several candidates are found, a confirmation is asked to user.
        """
        if current_object:
            self._current_object = None
            return current_object

        # Trying to match anaphora
        if not self.sentences_store:
            raise DialogError("Empty Dialog history")

        sf = SentenceFactory()

        #object = [ng, [List]]
        #       Where ng is the first nominal group to match with the anaphoric word
        #       and List contains nominal group that are to be explored if ng is not confirmed from the user

        object = matcher.match_first_object(get_last(self.sentences_store, 10), nominal_group)

        if not object:
            raise DialogError("No anaphora matches in dialog history")

        # Case there exist only one nominal group identified from anaphora matching
        if len(object[1]) == 1:
            nominal_group = object[0]
            logger.debug("Found anaphoric match " + str(nominal_group))

        # Else, ask for confirmation to the user
        else:
            raise UnidentifiedAnaphoraError({'object': nominal_group,
                                             'object_to_confirm': object[0],
                                             'object_with_more_info': None,
                                             'objects_list': object[1],
                                             'sentence': self._current_sentence,
                                             'question': sf.create_do_you_mean_reference(object[0])})

        ResourcePool().mark_active(nominal_group.id)
        return nominal_group
Esempio n. 7
0
class ContentAnalyser(object):
    def __init__(self):
        self.builder = StatementBuilder()
        self.adder = StatementSafeAdder()
        self.question_handler = QuestionHandler()
        self.sfactory = SentenceFactory()

        self.output_sentence = []

    def analyse(self, sentence, current_speaker):
        """Analyse a sentence intent and perform the corresponding behaviour.

        :returns: a pair with
         - a list of symbolic statements produced
        during the analyse. Note that these statements have 
        already been sent to the knowledge base
         - a situation ID that identifies a situation the speaker is
         desiring (for an imperative sentence or an order) or 
         experiencing (like an 'InterrogativeState' for a question).

         These two values can be None.

        Note also that an answer to the speaker is stored in self.output_sentence
        after analyse() completes.

        It can be used to tell the human to acknowledge an order, answer a 
        gratulation, the answer a question (or the fact the answer is not known),
        etc.
        """

        self.builder.clear_all()
        self.output_sentence = []

        sentence = self.pre_analyse_content(sentence)

        if sentence.data_type == [INTERJECTION, EXCLAMATION]:
            pass

        if sentence.data_type in [START, END]:
            self.output_sentence.append(sentence)

        if sentence.data_type == GRATULATION:
            self.output_sentence.extend(
                self.sfactory.create_gratulation_reply())

        if sentence.data_type in [AGREEMENT, DISAGREEMENT]:
            self.output_sentence.extend(self.sfactory.create_agree_reply())

        if sentence.data_type in [IMPERATIVE, STATEMENT]:
            logger.debug(
                colored_print(
                    "Processing the content of " +
                    ("an imperative sentence" if sentence.data_type
                     == IMPERATIVE else "a statement "), "magenta"))
            return self.process_sentence(sentence, current_speaker)

        if sentence.data_type in [W_QUESTION, YES_NO_QUESTION]:
            logger.debug(
                colored_print(
                    "Processing the content of " +
                    ("a W question " if sentence.data_type == W_QUESTION else
                     "a YES/NO question"), "magenta"))
            return self.process_question(sentence, current_speaker)

        return None, None  # default: no statement generated, no situation ID

    def process_sentence(self, sentence, current_speaker):
        self.builder.set_current_speaker(current_speaker)

        stmts, situation_id = self.builder.process_sentence(sentence)

        if stmts:

            self.add_stmts(stmts)

            emotions.satisfied()

            if situation_id:
                # If a new situation has been created, mark it as
                # active.
                self.output_sentence.extend(self.sfactory.create_agree_reply())
                ResourcePool().mark_active(situation_id)
        else:
            logger.info("No statements produced")

        # Class grounding
        if self.builder.lear_more_concept:
            self.output_sentence.extend(
                self.sfactory.create_what_is_a_reference(
                    sentence, self.builder.lear_more_concept))

        return stmts, situation_id

    def process_question(self, sentence, current_speaker):
        self.question_handler.set_current_speaker(current_speaker)

        # 'stmts' contains a list of statement describing the current
        # 'interrogative state' of the interactor.
        answer, stmts, situation_id = self.question_handler.process_sentence(
            sentence)

        if stmts:
            self.add_stmts(stmts)
        else:
            logger.info("No statements produced")

        if answer:
            emotions.satisfied()
            logger.info(
                level_marker(level=2, color="yellow") + "Found: \n" +
                colored_print(str(answer), None, "magenta"))
        else:
            emotions.sorry()
            logger.info(
                level_marker(level=2, color="yellow") +
                "Couldn't find anything!")

        if sentence.data_type == W_QUESTION:
            self.output_sentence.extend(
                self.sfactory.create_w_question_answer(
                    sentence, answer, self.question_handler._current_speaker,
                    self.question_handler.get_query_on_field()))

        if sentence.data_type == YES_NO_QUESTION:
            self.output_sentence.extend(
                self.sfactory.create_yes_no_answer(sentence, answer))

        return stmts, situation_id

    def add_stmts(self, stmts):
        logger.info("Generated statements: ")
        for s in stmts:
            logger.info(">> " + colored_print(s, None, 'magenta'))

        self.adder._current_speaker = self.builder._current_speaker
        self.adder._unclarified_ids = self.builder._unclarified_ids
        self.adder._statements = stmts
        self.adder._statements_to_remove = self.builder._statements_to_remove
        stmts = self.adder.process()

        logger.debug("...added to the ontology")

    def analyse_output(self):
        return self.output_sentence

    def pre_analyse_content(self, sentence):
        """ this method analyse the content of a sentence and possibly changes its purpose.

        E.g: Can you give me the bottle?
        The sentence above is of YES_NO_QUESTION type but should actually
        be processed as an order in which the current speaker desires 'the
        bottle'. Therefore, we turn it into 'give me the bottle'.
        """
        # Case of :
        #   -INPUT:  Yes_no_question + can + action verb
        #   -OUTPUT: Imperative + action verb
        #

        if sentence.data_type == YES_NO_QUESTION:
            for sv in sentence.sv:
                for verb in sv.vrb_main:
                    if 'can+' in verb:

                        vrb_main = verb.lstrip('can+')

                        if not vrb_main in ResourcePool().state + ResourcePool(
                        ).action_verb_with_passive_behaviour.keys(
                        ) + ResourcePool().goal_verbs:
                            logger.debug(
                                colored_print(
                                    "Interpreting the <can + action verb> sequence as a desire.\nApplying transformation:",
                                    "magenta"))

                            sv.vrb_main[sv.vrb_main.index(verb)] = verb.lstrip(
                                'can+')
                            sentence.data_type = IMPERATIVE

                            logger.debug(str(sentence))

                            return sentence

        return sentence
Esempio n. 8
0
    def clarify(self, description, ignoreFeatureL=None):

        if not ignoreFeatureL: ignoreFeatureL = []
        objL = self.get_all_objects_with_desc(description)

        if len(objL) == 0:
            logger.debug(colored_print('Nothing found!', "magenta"))
        else:
            logger.debug(
                colored_print('Found these possible concepts ID: ', "magenta")
                + colored_print(str(objL), 'blue'))

        if not self.oro:  #No ontology server
            return 'UNKNOWN_CONCEPT_' + generate_id(with_question_mark=False)

        if not objL:
            questions = SentenceFactory().create_i_dont_understand()
            raise UnsufficientInputError({
                'status': 'FAILURE',
                'question': questions
            })
            #return "I don't understand"

        else:
            # Check if the speaker sees only some of the object.
            # If he sees none of them, discriminate on the whole set.
            # Else, discriminate only on visible objects.
            agent = description[0][0]
            logger.debug("Checking which of these objects are visible for " +
                         agent)
            visible_objects = self.visible_subset(agent, objL)

            if visible_objects:
                objL = visible_objects
                logger.debug(
                    colored_print('Only ', "magenta") +
                    colored_print(str(objL), 'blue') +
                    colored_print(" are visible by " + agent, "magenta"))
            else:
                logger.debug(
                    colored_print('None are visible by ' + agent, "magenta"))

            if len(objL) == 1:
                return objL[0]

            if len(objL) == 2 and self.oro.check(
                ['%s owl:sameAs %s' % (objL[0], objL[1])]):
                return objL[0]

            agent, descriptor = self.get_descriptor(description,
                                                    ignoreFeatureL)
            object = self.get_type_description(description)

            if descriptor:
                sentence_builder = SentenceFactory()

                question = None
                values = self.get_values_for_descriptor(
                    agent, descriptor, objL)
                if not object: object = 'object'

                if descriptor == 'hasColor' or descriptor == 'mainColorOfObject':
                    questions = sentence_builder.create_w_question_choice(
                        object, 'color', values)

                elif descriptor == 'hasShape':
                    questions = sentence_builder.create_w_question_choice(
                        object, 'shape', values)

                elif descriptor == 'hasSize':
                    questions = sentence_builder.create_w_question_choice(
                        object, 'size', values)

                elif descriptor == 'isOn':
                    questions = sentence_builder.create_w_question_location(
                        object, 'on', values)

                elif descriptor == 'isIn':
                    questions = sentence_builder.create_w_question_location(
                        object, 'in', values)

                elif descriptor == 'isNextTo':
                    questions = sentence_builder.create_w_question_location(
                        object, 'next to', values)

                elif descriptor == 'isAt':
                    questions = sentence_builder.create_w_question_location(
                        object, 'at', values)

                elif descriptor == 'isLocated':
                    questions = sentence_builder.create_w_question_location_PT(
                        values, agent)

                elif descriptor == 'rdf:type':
                    questions = sentence_builder.create_w_question_choice(
                        object, 'type', values)

                else:
                    questions = sentence_builder.create_w_question_generic_descriptor(
                        object, descriptor, values)

                raise UnsufficientInputError({
                    'status': 'SUCCESS',
                    'question': questions
                })
                #return questions

            else:
                questions = [
                    Sentence(IMPERATIVE, '', [], [
                        VerbalGroup(['give'], [], 'present simple', [
                            NominalGroup([], ['information'], [['more', []]],
                                         [], [])
                        ], [
                            IndirectComplement(
                                [], [NominalGroup([], ['me'], [], [], [])]),
                            IndirectComplement(
                                ['about'],
                                [NominalGroup(['the'], [object], [], [], [])])
                        ], [], [], VerbalGroup.affirmative, [])
                    ])
                ]
                raise UnsufficientInputError({
                    'status': 'SUCCESS',
                    'question': questions
                })
Esempio n. 9
0
    def _resolve_nouns(self, nominal_group, current_speaker, discriminator, builder):
        """This attempts to resolve a single nominal group by the use of discrimiation routines.
            The output is the ID of the nominal group
        """

        if nominal_group._resolved: #already resolved: possible after asking human for more details.
            return nominal_group

        logger.debug(str(nominal_group))

        #Creating a concept description
        builder.process_nominal_group(nominal_group, '?concept', None, False)
        stmts = builder.get_statements()
        builder.clear_statements()

        # Special case of "other" occuring in the nominal group
        if builder.process_on_other:
            nominal_group, stmts = self.resolve_different_from_dialog_history(nominal_group, current_speaker, stmts,
                                                                              builder)
            if nominal_group._resolved:
                ResourcePool().mark_active(nominal_group.id)
                return nominal_group

        if nominal_group._quantifier in ['SOME']:

            #enforce object visibility
            stmtsAndVisibility = stmts + [current_speaker + " sees ?concept"]

            # Pick a random id
            logger.debug(colored_print("Looking for at least one visible concept matching in " + \
                                       current_speaker + "'s model: \n", "magenta") + \
                         '[' + colored_print(', '.join(stmtsAndVisibility), None, 'magenta') + ']')
            concepts = []
            try:
                concepts = ResourcePool().ontology_server.findForAgent(current_speaker, '?concept', stmtsAndVisibility)
            except AttributeError: # No ontology server
                pass
            except KbError: #The agent does not exist in the ontology
                pass

            if not concepts:
                # no acceptable concepts that are visible. Look for concepts that are not visible."
                logger.debug(colored_print("No visible concepts found. Removing the visibility constraint"))
                try:
                    concepts = ResourcePool().ontology_server.findForAgent(current_speaker, '?concept', stmts)
                except AttributeError: # No ontology server
                    pass
                except KbError: #The agent does not exist in the ontology
                    pass

            if concepts:
                id = random.choice(concepts)
            else:
                sf = SentenceFactory()
                uie = UnsufficientInputError({'status': 'FAILURE'})
                uie.value['question'] = sf.create_what_do_you_mean_reference(nominal_group)
                uie.value['object'] = nominal_group
                uie.value['sentence'] = self._current_sentence
                uie.value['object_with_more_info'] = None
                raise uie

        else:
            #Try to discriminate 
            logger.debug(colored_print("Looking for the concept matching in " + \
                                       current_speaker + "'s model: \n", "magenta") + \
                         '[' + colored_print(', '.join(stmts), None, 'magenta') + ']')
            description = [[current_speaker, '?concept', stmts]]

            #   Features to ignore from discrimination
            features = []
            if self._current_sentence.data_type in [W_QUESTION, YES_NO_QUESTION]:
                if self._current_sentence.aim in ResourcePool().adjectives_ontology_classes:
                    # feature =["hasColor"]
                    features = ["has" + self._current_sentence.aim.capitalize()]
                else:
                    features = ["rdf:type"]

            #   Discriminate
            try:
                id = discriminator.clarify(description, features)
            except UnsufficientInputError as uie:
                #   Create a new concept instead of raising unsificient input error, as the current sentence start with "learn that ..."
                if self._current_sentence.islearning():
                    id = self._ontology_learns_new_concept(stmts, current_speaker)
                else:
                    sf = SentenceFactory()
                    if uie.value['status'] != 'SUCCESS':
                        uie.value['question'][:0] = sf.create_what_do_you_mean_reference(nominal_group)
                    uie.value['object'] = nominal_group
                    uie.value['sentence'] = self._current_sentence
                    uie.value['object_with_more_info'] = None
                    raise uie

        logger.debug(colored_print("Hurra! Found \"" + id + "\"", 'magenta'))

        nominal_group.id = id
        nominal_group._resolved = True

        ResourcePool().mark_active(nominal_group.id)
        return nominal_group
Esempio n. 10
0
    def _resolve_references(self, nominal_group, verb, matcher, current_speaker, current_object):

        # Case of a resolved nominal group
        if nominal_group._resolved:
            return nominal_group


        # Case of a nominal group built by only adjectives 
        #   E.g, 'big' in 'the yellow banana is big'.
        if nominal_group.adjectives_only():
            nominal_group.id = nominal_group.adj[0][0]
            nominal_group._resolved = True
            return nominal_group


        # Case of an anaphoric word in the determiner
        # E.g: This , that cube
        if nominal_group.det and \
                        nominal_group.det[0].lower() in ResourcePool().demonstrative_det:

            onto_focus = ''
            logger.debug(
                colored_print("Found a demonstrative (this/that...). Trying to resolve it based on current focus...",
                              "magenta"))

            if nominal_group.noun and nominal_group.noun[
                0].lower() != 'one': # case "this + category" -> eg "this phone"
                class_name = self._get_class_name_from_ontology(current_speaker, nominal_group)
                logger.debug(colored_print("Looking for : ", "magenta") + colored_print(
                    current_speaker + ' pointsAt ?concept, ?concept rdf:type ' + class_name, None, "magenta"))
                try:
                    onto_focus = ResourcePool().ontology_server.findForAgent(
                        current_speaker,
                        '?concept',
                        [current_speaker + ' pointsAt ?concept', '?concept rdf:type ' + class_name])
                except AttributeError:
                    pass
                except KbError: #Agent not found in the ontology
                    pass

            else: # case "this" alone or "this one"
                logger.debug(
                    colored_print("Looking for : ", "magenta") + colored_print(current_speaker + ' pointsAt ?concept',
                                                                               None, "magenta"))
                try:
                    onto_focus = ResourcePool().ontology_server.findForAgent(
                        current_speaker,
                        '?concept',
                        [current_speaker + ' pointsAt ?concept'])
                except AttributeError:
                    pass
                except KbError: #Agent not found in the ontology
                    pass

            if onto_focus:
                logger.debug(colored_print("OK, found ", "magenta") + colored_print(str(onto_focus), "blue"))
                nominal_group.id = onto_focus[0]
                nominal_group._resolved = True

                ResourcePool().mark_active(nominal_group.id)

                return nominal_group

            logger.debug(colored_print("No focus. Processing is as a classic anaphora.", "magenta"))

            # Case of 
            #   this + noun - E.g: Take this cube:
            if nominal_group.noun and nominal_group.noun[0].lower() != 'one':
                pass # Nothing to do appart from processing "this" as "the"

            # Case of 
            #   this + one -  E.g: Take this one
            #   this + None - E.g: Take this
            else:
                try:
                    nominal_group.noun = self._references_resolution_with_anaphora_matcher(
                        nominal_group, matcher,
                        current_speaker,
                        current_object)
                except DialogError: #...no dialog history yet! or nothing found in history. Can not do any matching over past sentences
                    uie = UnsufficientInputError({'status': 'FAILURE'})

                    sf = SentenceFactory()
                    uie.value['question'] = sf.create_what_do_you_mean_reference(nominal_group)
                    uie.value['object'] = nominal_group
                    uie.value['sentence'] = self._current_sentence
                    uie.value['object_with_more_info'] = None
                    raise uie


        # Case of a nominal group with no Noun
        if not nominal_group.noun:
            return nominal_group

        # Case of an existing ID in the Ontology
        onto = []
        try:
            onto = ResourcePool().ontology_server.lookupForAgent(current_speaker, nominal_group.noun[0])
        except AttributeError: #the ontology server is not started or doesn't know the method
            pass
        except KbError: #The agent does not exist in the ontology
            pass

        if onto:
            for c in onto:
                if "INSTANCE" in c:
                    nominal_group.id = c[0]
                    logger.debug("... \t" + nominal_group.noun[0] + " is an existing ID (" + nominal_group.id + \
                                 ") in " + current_speaker + "'s model.")
                    nominal_group._resolved = True
                    ResourcePool().mark_active(nominal_group.id)
                    break

        # Case of personal prounouns
        if current_speaker and nominal_group.noun[0].lower() in ['me', 'i']:
            logger.debug(colored_print("Replaced \"me\" or \"I\" by \"" + current_speaker + "\"", "magenta"))
            nominal_group.id = current_speaker
            nominal_group._resolved = True
            return nominal_group

        if nominal_group.noun[0].lower() in ['you']:
            logger.debug(colored_print("Replaced \"you\" by \"myself\"", "magenta"))
            nominal_group.id = 'myself'
            nominal_group._resolved = True
            return nominal_group

        #Anaphoric words in the noun
        if nominal_group.noun[0].lower() in ['it', 'one']:
            nominal_group = self._references_resolution_with_anaphora_matcher(nominal_group, matcher,
                                                                              current_speaker,
                                                                              current_object)

        # Case of a quantifier different from ONE
        #   means the nominal group holds an indefinite determiner. 
        #   E.g a robot, every plant, fruits, ...
        if nominal_group._quantifier in ['SOME', 'ALL']:

            class_name = self._get_class_name_from_ontology(current_speaker, nominal_group)

            if verb and verb in ResourcePool().state and nominal_group.noun[0] not in ["everything", "anything"]:
                # Case of a state verb
                # id = the class name
                # E.g: an apple is a fruit
                #       the id of apple is Apple
                # TODO: adjectives are discarded: we do not handle 'A green apple is a fruit' for instance
                logger.debug("Found indefinite quantifier " + nominal_group._quantifier + \
                             " for " + nominal_group.noun[0] + " and state verb " + verb + \
                             ". Replacing it by its class.")

                nominal_group.id = class_name

            else:
                if nominal_group._quantifier in ['SOME']:
                # Do not deal further here with existential quantifier. It will be processed
                    # later in noun_resolution.
                    return nominal_group

                if nominal_group.noun[0] in ["everything", "anything"]:
                    # case of everything/anything
                    # -> we get all *Artifact* ids existing in the ontology

                    logger.debug("Found " + nominal_group.noun[0] + ": retrieving all existing instances.")

                    onto_id = []
                    try:
                        # TODO: anything -> all Artifact: is that right?
                        onto_id = ResourcePool().ontology_server.findForAgent(current_speaker, '?concept',
                                                                              ['?concept rdf:type Artifact'])
                    except KbError: # The agent does not exist in the ontology
                        pass

                else:
                    # case of an action verbs
                    # id = generated 
                    # E.g: An apple grows on a tree
                    # e.g.: show me the books -> books replaced by all book instance
                    #   we get the ids of all existing books in the ontology otherwise we generate one

                    logger.debug("Found indefinite quantifier " + nominal_group._quantifier + \
                                 " for " + nominal_group.noun[0] + ((" and with verb " + verb) if verb else "") + \
                                 ". Replacing it by all its instances.")

                    onto_id = []
                    try:
                        onto_id = ResourcePool().ontology_server.findForAgent(current_speaker, '?concept',
                                                                              ['?concept rdf:type ' + class_name])
                    except KbError: # The agent does not exist in the ontology
                        pass

                if not onto_id:
                    sf = SentenceFactory()
                    raise InterruptedInteractionError(sf.create_no_instance_of(nominal_group))

                elif len(onto_id) == 1:
                    [nominal_group.id] = onto_id

                else:
                    # More than one value! Add all ids
                    nominal_group.id = onto_id

            nominal_group._resolved = True

            ResourcePool().mark_active(nominal_group.id)

            return nominal_group

        return nominal_group
Esempio n. 11
0
    def clarify(self, description, ignoreFeatureL=None):

        if not ignoreFeatureL: ignoreFeatureL = []
        objL = self.get_all_objects_with_desc(description)

        if len(objL) == 0:
            logger.debug(colored_print('Nothing found!', "magenta"))
        else:
            logger.debug(
                colored_print('Found these possible concepts ID: ', "magenta") + colored_print(str(objL), 'blue'))

        if not self.oro: #No ontology server
            return 'UNKNOWN_CONCEPT_' + generate_id(with_question_mark=False)

        if not objL:
            questions = SentenceFactory().create_i_dont_understand()
            raise UnsufficientInputError({'status': 'FAILURE', 'question': questions})
            #return "I don't understand"

        else:
            # Check if the speaker sees only some of the object.
            # If he sees none of them, discriminate on the whole set.
            # Else, discriminate only on visible objects.
            agent = description[0][0]
            logger.debug("Checking which of these objects are visible for " + agent)
            visible_objects = self.visible_subset(agent, objL)

            if visible_objects:
                objL = visible_objects
                logger.debug(colored_print('Only ', "magenta") +
                             colored_print(str(objL), 'blue') +
                             colored_print(" are visible by " + agent, "magenta"))
            else:
                logger.debug(colored_print('None are visible by ' + agent, "magenta"))

            if len(objL) == 1:
                return objL[0]

            if len(objL) == 2 and self.oro.check(['%s owl:sameAs %s' % (objL[0], objL[1])]):
                return objL[0]

            agent, descriptor = self.get_descriptor(description, ignoreFeatureL)
            object = self.get_type_description(description)

            if descriptor:
                sentence_builder = SentenceFactory()

                question = None
                values = self.get_values_for_descriptor(agent, descriptor, objL)
                if not object: object = 'object'

                if descriptor == 'hasColor' or descriptor == 'mainColorOfObject':
                    questions = sentence_builder.create_w_question_choice(object, 'color', values)

                elif descriptor == 'hasShape':
                    questions = sentence_builder.create_w_question_choice(object, 'shape', values)

                elif descriptor == 'hasSize':
                    questions = sentence_builder.create_w_question_choice(object, 'size', values)

                elif descriptor == 'isOn':
                    questions = sentence_builder.create_w_question_location(object, 'on', values)

                elif descriptor == 'isIn':
                    questions = sentence_builder.create_w_question_location(object, 'in', values)

                elif descriptor == 'isNextTo':
                    questions = sentence_builder.create_w_question_location(object, 'next to', values)

                elif descriptor == 'isAt':
                    questions = sentence_builder.create_w_question_location(object, 'at', values)

                elif descriptor == 'isLocated':
                    questions = sentence_builder.create_w_question_location_PT(values, agent)

                elif descriptor == 'rdf:type':
                    questions = sentence_builder.create_w_question_choice(object, 'type', values)

                else:
                    questions = sentence_builder.create_w_question_generic_descriptor(object, descriptor, values)

                raise UnsufficientInputError({'status': 'SUCCESS', 'question': questions})
                #return questions

            else:
                questions = [Sentence(IMPERATIVE, '', [],
                                      [Verbal_Group(['give'], [], 'present simple',
                                                    [Nominal_Group([], ['information'], [['more', []]], [], [])],
                                                    [Indirect_Complement([], [Nominal_Group([], ['me'], [], [], [])]),
                                                     Indirect_Complement(['about'], [
                                                         Nominal_Group(['the'], [object], [], [], [])])],
                                          [], [], Verbal_Group.affirmative, [])])]
                raise UnsufficientInputError({'status': 'SUCCESS', 'question': questions})
Esempio n. 12
0
class ContentAnalyser(object):
    def __init__(self):
        self.builder = StatementBuilder()
        self.adder = StatementSafeAdder()
        self.question_handler = QuestionHandler()
        self.sfactory = SentenceFactory()

        self.output_sentence = []

    def analyse(self, sentence, current_speaker):
        """Analyse a sentence intent and perform the corresponding behaviour.

        :returns: a pair with
         - a list of symbolic statements produced
        during the analyse. Note that these statements have 
        already been sent to the knowledge base
         - a situation ID that identifies a situation the speaker is
         desiring (for an imperative sentence or an order) or 
         experiencing (like an 'InterrogativeState' for a question).

         These two values can be None.

        Note also that an answer to the speaker is stored in self.output_sentence
        after analyse() completes.

        It can be used to tell the human to acknowledge an order, answer a 
        gratulation, the answer a question (or the fact the answer is not known),
        etc.
        """

        self.builder.clear_all()
        self.output_sentence = []

        sentence = self.pre_analyse_content(sentence)

        if sentence.data_type == [INTERJECTION, EXCLAMATION]:
            pass

        if sentence.data_type in [START, END]:
            self.output_sentence.append(sentence)

        if sentence.data_type == GRATULATION:
            self.output_sentence.extend(self.sfactory.create_gratulation_reply())

        if sentence.data_type in [AGREEMENT, DISAGREEMENT]:
            self.output_sentence.extend(self.sfactory.create_agree_reply())

        if sentence.data_type in [IMPERATIVE, STATEMENT]:
            logger.debug(colored_print("Processing the content of " + (
                "an imperative sentence" if sentence.data_type == IMPERATIVE else "a statement "), "magenta"))
            return self.process_sentence(sentence, current_speaker)

        if sentence.data_type in [W_QUESTION, YES_NO_QUESTION]:
            logger.debug(colored_print("Processing the content of " + (
                "a W question " if sentence.data_type == W_QUESTION else "a YES/NO question"), "magenta"))
            return self.process_question(sentence, current_speaker)

        return None, None # default: no statement generated, no situation ID

    def process_sentence(self, sentence, current_speaker):
        self.builder.set_current_speaker(current_speaker)

        stmts, situation_id = self.builder.process_sentence(sentence)

        if stmts:

            self.add_stmts(stmts)

            emotions.satisfied()

            if situation_id:
                # If a new situation has been created, mark it as
                # active.
                self.output_sentence.extend(self.sfactory.create_agree_reply())
                ResourcePool().mark_active(situation_id)
        else:
            logger.info("No statements produced")

        # Class grounding
        if self.builder.lear_more_concept:
            self.output_sentence.extend(
                self.sfactory.create_what_is_a_reference(sentence, self.builder.lear_more_concept))

        return stmts, situation_id


    def process_question(self, sentence, current_speaker):
        self.question_handler.set_current_speaker(current_speaker)

        # 'stmts' contains a list of statement describing the current 
        # 'interrogative state' of the interactor.
        answer, stmts, situation_id = self.question_handler.process_sentence(sentence)

        if stmts:
            self.add_stmts(stmts)
        else:
            logger.info("No statements produced")

        if answer:
            emotions.satisfied()
            logger.info(
                level_marker(level=2, color="yellow") + "Found: \n" + colored_print(str(answer), None, "magenta"))
        else:
            emotions.sorry()
            logger.info(level_marker(level=2, color="yellow") + "Couldn't find anything!")

        if sentence.data_type == W_QUESTION:
            self.output_sentence.extend(self.sfactory.create_w_question_answer(sentence,
                                                                               answer,
                                                                               self.question_handler._current_speaker,
                                                                               self.question_handler.get_query_on_field()))

        if sentence.data_type == YES_NO_QUESTION:
            self.output_sentence.extend(self.sfactory.create_yes_no_answer(sentence, answer))

        return stmts, situation_id


    def add_stmts(self, stmts):
        logger.info("Generated statements: ")
        for s in stmts:
            logger.info(">> " + colored_print(s, None, 'magenta'))

        self.adder._current_speaker = self.builder._current_speaker
        self.adder._unclarified_ids = self.builder._unclarified_ids
        self.adder._statements = stmts
        self.adder._statements_to_remove = self.builder._statements_to_remove
        stmts = self.adder.process()

        logger.debug("...added to the ontology")

    def analyse_output(self):
        return self.output_sentence

    def pre_analyse_content(self, sentence):
        """ this method analyse the content of a sentence and possibly changes its purpose.

        E.g: Can you give me the bottle?
        The sentence above is of YES_NO_QUESTION type but should actually
        be processed as an order in which the current speaker desires 'the
        bottle'. Therefore, we turn it into 'give me the bottle'.
        """
        # Case of : 
        #   -INPUT:  Yes_no_question + can + action verb
        #   -OUTPUT: Imperative + action verb
        #   

        if sentence.data_type == YES_NO_QUESTION:
            for sv in sentence.sv:
                for verb in sv.vrb_main:
                    if 'can+' in verb:

                        vrb_main = verb.lstrip('can+')

                        if not vrb_main in ResourcePool().state + ResourcePool().action_verb_with_passive_behaviour.keys() + ResourcePool().goal_verbs:
                            logger.debug(colored_print(
                                "Interpreting the <can + action verb> sequence as a desire.\nApplying transformation:",
                                "magenta"))

                            sv.vrb_main[sv.vrb_main.index(verb)] = verb.lstrip('can+')
                            sentence.data_type = IMPERATIVE

                            logger.debug(str(sentence))

                            return sentence

        return sentence
Esempio n. 13
0
    def _resolve_nouns(self, nominal_group, current_speaker, discriminator,
                       builder):
        """This attempts to resolve a single nominal group by the use of discrimiation routines.
            The output is the ID of the nominal group
        """

        if nominal_group._resolved:  #already resolved: possible after asking human for more details.
            return nominal_group

        logger.debug(str(nominal_group))

        #Creating a concept description
        builder.process_nominal_group(nominal_group, '?concept', None, False)
        stmts = builder.get_statements()
        builder.clear_statements()

        # Special case of "other" occuring in the nominal group
        if builder.process_on_other:
            nominal_group, stmts = self.resolve_different_from_dialog_history(
                nominal_group, current_speaker, stmts, builder)
            if nominal_group._resolved:
                ResourcePool().mark_active(nominal_group.id)
                return nominal_group

        if nominal_group._quantifier in ['SOME']:

            #enforce object visibility
            stmtsAndVisibility = stmts + [current_speaker + " sees ?concept"]

            # Pick a random id
            logger.debug(colored_print("Looking for at least one visible concept matching in " + \
                                       current_speaker + "'s model: \n", "magenta") + \
                         '[' + colored_print(', '.join(stmtsAndVisibility), None, 'magenta') + ']')
            concepts = []
            try:
                concepts = ResourcePool().ontology_server.findForAgent(
                    ResourcePool().get_model_mapping(current_speaker),
                    '?concept', stmtsAndVisibility)
            except KbError:  #The agent does not exist in the ontology
                pass

            if not concepts:
                # no acceptable concepts that are visible. Look for concepts that are not visible."
                logger.debug(
                    colored_print(
                        "No visible concepts found. Removing the visibility constraint"
                    ))
                try:
                    concepts = ResourcePool().ontology_server.findForAgent(
                        ResourcePool().get_model_mapping(current_speaker),
                        '?concept', stmts)
                except KbError:  #The agent does not exist in the ontology
                    pass

            if concepts:
                id = random.choice(concepts)
            else:
                sf = SentenceFactory()
                uie = UnsufficientInputError({'status': 'FAILURE'})
                uie.value['question'] = sf.create_what_do_you_mean_reference(
                    nominal_group)
                uie.value['object'] = nominal_group
                uie.value['sentence'] = self._current_sentence
                uie.value['object_with_more_info'] = None
                raise uie

        else:
            #Try to discriminate
            logger.debug(colored_print("Looking for the concept matching in " + \
                                       current_speaker + "'s model: \n", "magenta") + \
                         '[' + colored_print(', '.join(stmts), None, 'magenta') + ']')
            description = [[current_speaker, '?concept', stmts]]

            #   Features to ignore from discrimination
            features = []
            if self._current_sentence.data_type in [
                    W_QUESTION, YES_NO_QUESTION
            ]:
                if self._current_sentence.aim in ResourcePool(
                ).adjectives_ontology_classes:
                    # feature =["hasColor"]
                    features = [
                        "has" + self._current_sentence.aim.capitalize()
                    ]
                else:
                    features = ["rdf:type"]

            #   Discriminate
            try:
                id = discriminator.clarify(description, features)
            except UnsufficientInputError as uie:
                #   Create a new concept instead of raising unsificient input error, as the current sentence start with "learn that ..."
                if self._current_sentence.islearning():
                    id = self._ontology_learns_new_concept(
                        stmts, current_speaker)
                else:
                    sf = SentenceFactory()
                    if uie.value['status'] != 'SUCCESS':
                        uie.value[
                            'question'][:
                                        0] = sf.create_what_do_you_mean_reference(
                                            nominal_group)
                    uie.value['object'] = nominal_group
                    uie.value['sentence'] = self._current_sentence
                    uie.value['object_with_more_info'] = None
                    raise uie

        logger.debug(colored_print("Hurra! Found \"" + id + "\"", 'magenta'))

        nominal_group.id = id
        nominal_group._resolved = True

        ResourcePool().mark_active(nominal_group.id)
        return nominal_group
Esempio n. 14
0
    def _resolve_references(self, nominal_group, verb, matcher,
                            current_speaker, current_object):

        # Case of a resolved nominal group
        if nominal_group._resolved:
            return nominal_group

        # Case of a nominal group built by only adjectives
        #   E.g, 'big' in 'the yellow banana is big'.
        if nominal_group.adjectives_only():
            nominal_group.id = nominal_group.adj[0][0]
            nominal_group._resolved = True
            return nominal_group

        # Case of an anaphoric word in the determiner
        # E.g: This , that cube
        if nominal_group.det and \
                        nominal_group.det[0].lower() in ResourcePool().demonstrative_det:

            onto_focus = ''
            logger.debug(
                colored_print(
                    "Found a demonstrative (this/that...). Trying to resolve it based on current focus...",
                    "magenta"))

            if nominal_group.noun and nominal_group.noun[0].lower(
            ) != 'one':  # case "this + category" -> eg "this phone"
                class_name = self._get_class_name_from_ontology(
                    current_speaker, nominal_group)
                logger.debug(
                    colored_print("Looking for : ", "magenta") + colored_print(
                        current_speaker +
                        ' focusesOn ?concept, ?concept rdf:type ' +
                        class_name, None, "magenta"))
                try:
                    onto_focus = ResourcePool().ontology_server.findForAgent(
                        ResourcePool().get_model_mapping(current_speaker),
                        '?concept', [
                            current_speaker + ' focusesOn ?concept',
                            '?concept rdf:type ' + class_name
                        ])
                except KbError:  #Agent not found in the ontology
                    pass

            else:  # case "this" alone or "this one"
                logger.debug(
                    colored_print("Looking for : ", "magenta") +
                    colored_print(current_speaker +
                                  ' focusesOn ?concept', None, "magenta"))
                try:
                    onto_focus = ResourcePool().ontology_server.findForAgent(
                        ResourcePool().get_model_mapping(current_speaker),
                        '?concept', [current_speaker + ' focusesOn ?concept'])
                except KbError:  #Agent not found in the ontology
                    pass

            if onto_focus:
                logger.debug(
                    colored_print("OK, found ", "magenta") +
                    colored_print(str(onto_focus), "blue"))
                nominal_group.id = onto_focus[0]
                nominal_group._resolved = True

                ResourcePool().mark_active(nominal_group.id)

                return nominal_group

            logger.debug(
                colored_print("No focus. Processing is as a classic anaphora.",
                              "magenta"))

            # Case of
            #   this + noun - E.g: Take this cube:
            if nominal_group.noun and nominal_group.noun[0].lower() != 'one':
                pass  # Nothing to do appart from processing "this" as "the"

            # Case of
            #   this + one -  E.g: Take this one
            #   this + None - E.g: Take this
            else:
                try:
                    nominal_group.noun = self._references_resolution_with_anaphora_matcher(
                        nominal_group, matcher, current_speaker,
                        current_object)
                except DialogError:  #...no dialog history yet! or nothing found in history. Can not do any matching over past sentences
                    uie = UnsufficientInputError({'status': 'FAILURE'})

                    sf = SentenceFactory()
                    uie.value[
                        'question'] = sf.create_what_do_you_mean_reference(
                            nominal_group)
                    uie.value['object'] = nominal_group
                    uie.value['sentence'] = self._current_sentence
                    uie.value['object_with_more_info'] = None
                    raise uie

        # Case of a nominal group with no Noun
        if not nominal_group.noun:
            return nominal_group

        # Case of an existing ID in the Ontology
        onto = []
        try:
            onto = ResourcePool().ontology_server.lookupForAgent(
                ResourcePool().get_model_mapping(current_speaker),
                nominal_group.noun[0])
        except KbError:  #The agent does not exist in the ontology
            pass

        if onto:
            for c in onto:
                if "instance" in c:
                    nominal_group.id = c[0]
                    logger.debug("... \t" + nominal_group.noun[0] + " is an existing ID (" + nominal_group.id + \
                                 ") in " + current_speaker + "'s model.")
                    nominal_group._resolved = True
                    ResourcePool().mark_active(nominal_group.id)
                    break

        # Case of personal prounouns
        if current_speaker and nominal_group.noun[0].lower() in ['me', 'i']:
            logger.debug(
                colored_print(
                    "Replaced \"me\" or \"I\" by \"" + current_speaker + "\"",
                    "magenta"))
            nominal_group.id = current_speaker
            nominal_group._resolved = True
            return nominal_group

        if nominal_group.noun[0].lower() in ['you']:
            logger.debug(
                colored_print("Replaced \"you\" by \"myself\"", "magenta"))
            nominal_group.id = 'myself'
            nominal_group._resolved = True
            return nominal_group

        #Anaphoric words in the noun
        if nominal_group.noun[0].lower() in ['it', 'one']:
            nominal_group = self._references_resolution_with_anaphora_matcher(
                nominal_group, matcher, current_speaker, current_object)

        # Case of a quantifier different from ONE
        #   means the nominal group holds an indefinite determiner.
        #   E.g a robot, every plant, fruits, ...
        if nominal_group._quantifier in ['SOME', 'ALL']:

            class_name = self._get_class_name_from_ontology(
                current_speaker, nominal_group)

            if verb and verb in ResourcePool(
            ).state and nominal_group.noun[0] not in [
                    "everything", "anything"
            ]:
                # Case of a state verb
                # id = the class name
                # E.g: an apple is a fruit
                #       the id of apple is Apple
                # TODO: adjectives are discarded: we do not handle 'A green apple is a fruit' for instance
                logger.debug("Found indefinite quantifier " + nominal_group._quantifier + \
                             " for " + nominal_group.noun[0] + " and state verb " + verb + \
                             ". Replacing it by its class.")

                nominal_group.id = class_name

            else:
                if nominal_group._quantifier in ['SOME']:
                    # Do not deal further here with existential quantifier. It will be processed
                    # later in noun_resolution.
                    return nominal_group

                if nominal_group.noun[0] in ["everything", "anything"]:
                    # case of everything/anything
                    # -> we get all *Artifact* ids existing in the ontology

                    logger.debug("Found " + nominal_group.noun[0] +
                                 ": retrieving all existing instances.")

                    onto_id = []
                    try:
                        # TODO: anything -> all Artifact: is that right?
                        onto_id = ResourcePool().ontology_server.findForAgent(
                            ResourcePool().get_model_mapping(current_speaker),
                            '?concept', ['?concept rdf:type Artifact'])
                    except KbError:  # The agent does not exist in the ontology
                        pass

                else:
                    # case of an action verbs
                    # id = generated
                    # E.g: An apple grows on a tree
                    # e.g.: show me the books -> books replaced by all book instance
                    #   we get the ids of all existing books in the ontology otherwise we generate one

                    logger.debug("Found indefinite quantifier " + nominal_group._quantifier + \
                                 " for " + nominal_group.noun[0] + ((" and with verb " + verb) if verb else "") + \
                                 ". Replacing it by all its instances.")

                    onto_id = []
                    try:
                        onto_id = ResourcePool().ontology_server.findForAgent(
                            ResourcePool().get_model_mapping(current_speaker),
                            '?concept', ['?concept rdf:type ' + class_name])
                    except KbError:  # The agent does not exist in the ontology
                        pass

                if not onto_id:
                    sf = SentenceFactory()
                    raise InterruptedInteractionError(
                        sf.create_no_instance_of(nominal_group))

                elif len(onto_id) == 1:
                    [nominal_group.id] = onto_id

                else:
                    # More than one value! Add all ids
                    nominal_group.id = onto_id

            nominal_group._resolved = True

            ResourcePool().mark_active(nominal_group.id)

            return nominal_group

        return nominal_group