def _ontology_learns_new_concept(self, concept_description, current_speaker): """This method commit a new concept in the ontology regarding the description that has been provided. Also, it returns a randomly genrated ID of the new concept """ #Genrating ID id = generate_id(with_question_mark=False) #Replacing '?concept' by ID stmts = [s.replace('?concept', id) for s in concept_description] #Removing remaining statements holding unbound tokens other than '?concept' # in order not to add unbound references in the ontology. stmts = [s for s in stmts if not "?" in s] #Commiting the ontology now, in case of a research on this concept on the remaining unresolved concepts of the sentence logger.debug(colored_print("Learning this new concept in " + current_speaker + "'s model: \n", "magenta") + '[' + colored_print(', '.join(stmts), None, 'magenta') + ']') try: ResourcePool().ontology_server.revise(stmts, {"method": "add", "models": [current_speaker]}) except AttributeError: pass if current_speaker != ResourcePool().default_model: logger.debug( colored_print("Learning this new concept in robot's model: \n", "magenta") + '[' + colored_print( ', '.join(stmts), None, 'magenta') + ']') try: ResourcePool().ontology_server.revise(stmts, {"method": "add", "models": [ResourcePool().default_model]}) except AttributeError: pass return id
def test(self, speaker, input, answer=None): """This method eases the testing of dialog by returning only when a sentence is completely processed. The optional 'answer' argument is used to answer a request for more details from the resolution code. The method returns a tuple containing the last produced statements (if relevant) and the last sentence produced (as a tuple of (Sentence, verbalized sentence), is relevant). """ import time self.in_interaction = True self.input(input, speaker) while self.in_interaction: if self.waiting_for_more_info: if answer: self._logger.debug( colored_print("> Automatically answering: ", 'bold')) self._logger.info(colored_print(answer, 'red')) self.input(answer, speaker) answer = None else: return [], self.last_sentence time.sleep(0.1) return self.last_stmts_set, self.last_sentence
def test(self, speaker, input, answer=None): """This method eases the testing of dialog by returning only when a sentence is completely processed. The optional 'answer' argument is used to answer a request for more details from the resolution code. The method returns a tuple containing the last produced statements (if relevant) and the last sentence produced (as a tuple of (Sentence, verbalized sentence), is relevant). """ import time self.in_interaction = True self.input(input, speaker) while self.in_interaction: if self.waiting_for_more_info: if answer: self._logger.debug(colored_print("> Automatically answering: ", "bold")) self._logger.info(colored_print(answer, "red")) self.input(answer, speaker) answer = None else: return [], self.last_sentence time.sleep(0.1) return self.last_stmts_set, self.last_sentence
def resolve_different_from_dialog_history(self, nominal_group, current_speaker, current_stmts, builder): """This attempts to resolve nouns that involve both a discrimination processing and searching the dialog history It first retrieve all candidates that would match without 'other', then select amongst these candidates the ones that where previously mentioned in the dialogue, and eventually add 'owl:differentFrom' statements for each of the resulting concepts. E.g: the 'other' cup. - if there is only one cup existing in the ontology, then we identify it by a discrimination processing. - if there are several cups known in the ontology, then we possibly mean a cup different from the one that has been stated earlier in the dialog. """ logger.debug( colored_print( "\tFound '(an)other'. Looking for a different concept from dialog history.", "magenta")) obj_list = [] obj_list = ResourcePool().ontology_server.findForAgent( ResourcePool().get_model_mapping(current_speaker), '?concept', current_stmts) if obj_list: if len(obj_list) == 1: nominal_group.id = obj_list[0] nominal_group._resolved = True ResourcePool().mark_active(nominal_group.id) else: historic_objects_list = recover_nominal_group_list( get_last(self.sentences_store, 10)) if not historic_objects_list: raise DialogError( "Error: possibly due to an empty dialog history") candidates = [ obj for obj in historic_objects_list if obj.id in obj_list ] if not candidates: logger.debug( colored_print( "\tCould not find any suitable candidate from dialog history.", "magenta")) # Discriminate everything different from this ID for c in candidates: current_stmts.append("?concept owl:differentFrom " + c.id) return nominal_group, current_stmts
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 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_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 clarify(self, statements, ids): """This attempts to identify a matching reference of the action described from the statements - statements: the field of statements used to query the ontology - ids: the field of references that are to be identified e.g: Danny doesn't drive the blue car. statements = [?sit rdf:type Drive, ?sit performedBy DANNY, ?sit involves BLUE_CAR] ids = [?sit] Before removing the statements set from the ontology, we determine if there is a matching action to ?sit """ current_s = statements for id in ids: stmts = [] #Attempt to find the unidentified IDs onto = ResourcePool().ontology_server.find([id], current_s) #Replace Matching IDs if onto: logger.info( colored_print("... Found ID " + onto[0] + " matching description given statements.", "magenta")) for s in current_s: stmts.append(s.replace(id, onto[0])) current_s = stmts return current_s
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 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
def resolve_different_from_dialog_history(self, nominal_group, current_speaker, current_stmts, builder): """This attempts to resolve nouns that involve both a discrimination processing and searching the dialog history It first retrieve all candidates that would match without 'other', then select amongst these candidates the ones that where previously mentioned in the dialogue, and eventually add 'owl:differentFrom' statements for each of the resulting concepts. E.g: the 'other' cup. - if there is only one cup existing in the ontology, then we identify it by a discrimination processing. - if there are several cups known in the ontology, then we possibly mean a cup different from the one that has been stated earlier in the dialog. """ logger.debug( colored_print("\tFound '(an)other'. Looking for a different concept from dialog history.", "magenta")) obj_list = [] try: obj_list = ResourcePool().ontology_server.findForAgent(current_speaker, '?concept', current_stmts) except AttributeError: pass if obj_list: if len(obj_list) == 1: nominal_group.id = obj_list[0] nominal_group._resolved = True ResourcePool().mark_active(nominal_group.id) else: historic_objects_list = recover_nominal_group_list(get_last(self.sentences_store, 10)) if not historic_objects_list: raise DialogError("Error: possibly due to an empty dialog history") candidates = [obj for obj in historic_objects_list if obj.id in obj_list] if not candidates: logger.debug( colored_print("\tCould not find any suitable candidate from dialog history.", "magenta")) # Discriminate everything different from this ID for c in candidates: current_stmts.append("?concept owl:differentFrom " + c.id) return nominal_group, current_stmts
def _send_state(state): models = [ResourcePool().default_model] policy = {"method": "add", "models": models} state_id = generate_id(False) statements = [ state_id + " rdf:type " + state, "myself experiences " + state_id ] logger.info(colored_print("Setting my mood to " + state, "magenta")) #logger.warning(colored_print("Not setting my mood due to Pellet bugs!", "magenta")) ResourcePool().ontology_server.revise(statements, policy)
def verbal_phrases_resolution(self, sentence): logger.info(colored_print("-> Resolving verbal groups", 'green')) #Skipping processing of sentences that are neither questions nor statements nor imperative if not sentence.data_type in [W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE]: return sentence for sv in sentence.sv: sv = self._resolve_verbs(sv) return sentence
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 _ontology_learns_new_concept(self, concept_description, current_speaker): """This method commit a new concept in the ontology regarding the description that has been provided. Also, it returns a randomly genrated ID of the new concept """ #Genrating ID id = generate_id(with_question_mark=False) #Replacing '?concept' by ID stmts = [s.replace('?concept', id) for s in concept_description] #Removing remaining statements holding unbound tokens other than '?concept' # in order not to add unbound references in the ontology. stmts = [s for s in stmts if not "?" in s] #Commiting the ontology now, in case of a research on this concept on the remaining unresolved concepts of the sentence logger.debug( colored_print( "Learning this new concept in " + current_speaker + "'s model: \n", "magenta") + '[' + colored_print(', '.join(stmts), None, 'magenta') + ']') ResourcePool().ontology_server.revise( stmts, { "method": "add", "models": [ResourcePool().get_model_mapping(current_speaker)] }) if current_speaker != ResourcePool().default_model: logger.debug( colored_print("Learning this new concept in robot's model: \n", "magenta") + '[' + colored_print(', '.join(stmts), None, 'magenta') + ']') ResourcePool().ontology_server.revise( stmts, { "method": "add", "models": [ResourcePool().default_model] }) return id
def safe_add(self, statements): """ This process the commitment of new statements in the ontology and deals with adding inconsistency """ models = [ResourcePool().default_model] if self._current_speaker: models.append(ResourcePool().get_model_mapping(self._current_speaker)) policy = {"method": "safe_add", "models": models} if not ResourcePool().ontology_server.revise(statements, policy): logger.debug(colored_print("At least one statement hasn't been " + \ "pushed to the ontology server because it would lead to inconsistencies."))
def _send_state(state): models = [ResourcePool().default_model] policy = {"method": "add", "models": models} state_id = generate_id(False) statements = [state_id + " rdf:type " + state, "myself experiences " + state_id] try: logger.info(colored_print("Setting my mood to " + state, "magenta")) #logger.warning(colored_print("Not setting my mood due to Pellet bugs!", "magenta")) ResourcePool().ontology_server.revise(statements, policy) except AttributeError: #the ontology server is not started of doesn't know the method pass
def verbal_phrases_resolution(self, sentence): logger.info(colored_print("-> Resolving verbal groups", 'green')) #Skipping processing of sentences that are neither questions nor statements nor imperative if not sentence.data_type in [ W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE ]: return sentence for sv in sentence.sv: sv = self._resolve_verbs(sv) return sentence
def noun_phrases_resolution(self, sentence, current_speaker, uie_object, uie_object_with_more_info): logger.info(colored_print("-> Resolving noun phrases", 'green')) #Skipping processing of sentences that are neither questions nor statements nor imperatives if not sentence.data_type in [ W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE ]: return sentence #Nominal group replacement possibly after uie_object and uie_object_with_more_info are sent from Dialog to resolve missing content if uie_object and uie_object_with_more_info: sentence = self._noun_phrases_replace_with_ui_exception( sentence, uie_object, uie_object_with_more_info) #No uie_objects needed after replacement uie_object = None uie_object_with_more_info = None #Record of current sentence self._current_sentence = sentence #NominalGroupStatementBuilder builder = NominalGroupStatementBuilder(None, current_speaker) #Discrimination discriminator = Discrimination() #sentence.sn nominal groups nouns phrase resolution if sentence.sn: sentence.sn = self._resolve_groups_nouns(sentence.sn, current_speaker, discriminator, builder) #sentence.sv nominal groups nouns phrase resolution if sentence.sv: sentence.sv = self.verbal_phrases_noun_resolution( sentence.sv, current_speaker, discriminator, builder) return sentence
def references_resolution(self, sentence, current_speaker, uae_object, uae_object_with_more_info, uae_object_list): #Skipping processing of sentences that are neither questions nor statements if not sentence.data_type in [W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE]: return sentence # Current object replacement with uae object if uae_object and uae_object_with_more_info: self._current_object = self._references_resolution_replace_current_object_with_ua_exception(sentence, uae_object, uae_object_with_more_info, uae_object_list) logger.info(colored_print("-> Resolving references and anaphors...", 'green')) #Record of current sentence self._current_sentence = sentence #Anaphoric resolution matcher = AnaphoraMatcher() # First, resolve the verbal group, since we may need to know the verb to # resolve the subject. # for instance "The girls are human" -> Girl rdfs:subClassOf Human # "The girls are playing football" -> girl1, girl2 currentlyPerforms PlayFoot if sentence.sv: sentence.sv = self.verbal_phrases_reference_resolution(sentence.sv, matcher, current_speaker, self._current_object) #sentence sn nominal groups reference resolution if sentence.sn: sentence.sn = self._resolve_groups_references(sentence.sn, sentence.sv[0].vrb_main[0] if sentence.sv else None, matcher, current_speaker, self._current_object) return sentence
def references_resolution(self, sentence, current_speaker, uae_object, uae_object_with_more_info, uae_object_list): #Skipping processing of sentences that are neither questions nor statements if not sentence.data_type in [ W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE ]: return sentence # Current object replacement with uae object if uae_object and uae_object_with_more_info: self._current_object = self._references_resolution_replace_current_object_with_ua_exception( sentence, uae_object, uae_object_with_more_info, uae_object_list) logger.info( colored_print("-> Resolving references and anaphors...", 'green')) #Record of current sentence self._current_sentence = sentence #Anaphoric resolution matcher = AnaphoraMatcher() # First, resolve the verbal group, since we may need to know the verb to # resolve the subject. # for instance "The girls are human" -> Girl rdfs:subClassOf Human # "The girls are playing football" -> girl1, girl2 currentlyPerforms PlayFoot if sentence.sv: sentence.sv = self.verbal_phrases_reference_resolution( sentence.sv, matcher, current_speaker, self._current_object) #sentence sn nominal groups reference resolution if sentence.sn: sentence.sn = self._resolve_groups_references( sentence.sn, sentence.sv[0].vrb_main[0] if sentence.sv else None, matcher, current_speaker, self._current_object) return 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
def noun_phrases_resolution(self, sentence, current_speaker, uie_object, uie_object_with_more_info): logger.info(colored_print("-> Resolving noun phrases", 'green')) #Skipping processing of sentences that are neither questions nor statements nor imperatives if not sentence.data_type in [W_QUESTION, YES_NO_QUESTION, STATEMENT, IMPERATIVE]: return sentence #Nominal group replacement possibly after uie_object and uie_object_with_more_info are sent from Dialog to resolve missing content if uie_object and uie_object_with_more_info: sentence = self._noun_phrases_replace_with_ui_exception(sentence, uie_object, uie_object_with_more_info) #No uie_objects needed after replacement uie_object = None uie_object_with_more_info = None #Record of current sentence self._current_sentence = sentence #NominalGroupStatementBuilder builder = NominalGroupStatementBuilder(None, current_speaker) #Discrimination discriminator = Discrimination() #sentence.sn nominal groups nouns phrase resolution if sentence.sn: sentence.sn = self._resolve_groups_nouns(sentence.sn, current_speaker, discriminator, builder) #sentence.sv nominal groups nouns phrase resolution if sentence.sv: sentence.sv = self.verbal_phrases_noun_resolution(sentence.sv, current_speaker, discriminator, builder) return sentence
def process_sentence(self, sentence): """This processes a w_question or yes_no_question sentence""" self._sentence = sentence #StatementBuilder builder = StatementBuilder(self._current_speaker) self._statements, situation_id = builder.process_sentence(self._sentence) logger.info(level_marker(level=2, color="yellow") + "Generated statements based on the sentence components: " + colored_print( str(self._statements), None, "magenta")) #Case the question is a y_n_question : check the fact in the ontology if sentence.data_type == YES_NO_QUESTION: self._statements = self._set_situation_id(self._statements) logger.info( level_marker(level=2, color="yellow") + "Generated statements for this question: " + colored_print( str(self._statements), None, "magenta")) #Processing :Do you know something? if self.process_on_knowing_concept: #self._statements = [agent knows object] for s in self._statements: self._answer = True if "knows" in s: [agent, object] = s.split(" knows ") onto_lookup = [] try: logger.debug(level_marker(level=2, color="yellow") + "Looking up for " + object + " in " + agent + "'s model") onto_lookup = ResourcePool().ontology_server.lookupForAgent(agent, object) except AttributeError: pass self._answer = self._answer and (True if onto_lookup else False) self.process_on_knowing_concept = False else: try: logger.debug(level_marker(level=2, color="yellow") + "Checking in the ontology: " + colored_print( str(self._statements), None, "magenta")) self._answer = ResourcePool().ontology_server.check(self._statements) except AttributeError: #the ontology server is not started of doesn't know the method pass #Case the question is a w_question : find the concept the concept that answers the question if sentence.data_type == W_QUESTION: # self._query_on_field = self._set_query_on_field(sentence) statements_with_bound_tokens = self._remove_statements_with_no_unbound_tokens(self._statements) #Agent from which the ontology model is queried agent = self._default_agent self._answer = [] #For all the possible subjects of a same question if not self._sentence.sn: statements_to_query = [self._extend_statement_from_sentence_aim(statements_with_bound_tokens)] else: statements_to_query = [self._extend_statement_from_sentence_aim(statements_with_bound_tokens, sn) for sn in self._sentence.sn] for statements in statements_to_query: if self.process_on_knowing_concept: #Get agent in a statement such as [agent knows object] for s in statements: if "knows" in s: [agent, object] = s.split(" knows ") break #No need of statements such as [S knows O] [statements.remove(s) for s in statements if "knows" in s] self.process_on_knowing_concept = False if statements: logger.info(level_marker(level=2, color="yellow") + "Generated statements for this question: " + colored_print( str(self._statements), None, "magenta")) answers = [] if self._process_on_location: prepositions_list = ResourcePool().preposition_rdf_object_property.copy() roles = dict([(preposition, prepositions_list[preposition][0]) \ for preposition in prepositions_list.keys() \ if 'objectFoundInLocation' in prepositions_list[preposition]]) #Case of ojectFound in location stmts = [] prepositions_already_used = [] for role in roles: if roles[role] in prepositions_already_used: continue stmts = [s.replace('objectFoundInLocation', roles[role]) for s in statements] try: logger.debug(level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print( str(stmts), None, "magenta")) answers = ResourcePool().ontology_server.findForAgent(agent, '?concept', stmts) except AttributeError: #the ontology server is not started of doesn't know the method pass prepositions_already_used.append(roles[role]) if answers: ResourcePool().mark_active(answers) self._answer.append([[role], answers]) #Case of object found in location + direction stmts = [s.replace('objectFoundInLocation', 'isAt') for s in statements] for role in ResourcePool().direction_words: try: logger.debug(level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print( str(stmts + ['?concept is' + role.capitalize() + 'Of ?obj', '?concept rdf:type Location']), None, "magenta")) answers = ResourcePool().ontology_server.findForAgent(agent, '?obj', stmts + [ '?concept is' + role.capitalize() + 'Of ?obj', '?concept rdf:type Location']) except AttributeError: #the ontology server is not started of doesn't know the method pass if answers: ResourcePool().mark_active(answers) self._answer.append([[role], answers]) else: try: logger.debug(level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print( str(statements), None, "magenta")) answers = ResourcePool().ontology_server.findForAgent(agent, '?concept', statements) except AttributeError: #the ontology server is not started of doesn't know the method pass if answers: ResourcePool().mark_active(answers) self._answer.append([[], answers]) else: pass self._statements.extend(statements) stmts, sit_id = self._build_situation_statements() return self._answer, stmts, sit_id
def findForAgent(self, model, var, query): self.log.info(colored_print("QUERY (in model <%s>): %s" % (model, query), 'cyan'))
def run(self): while self.go_on: try: # block with a (short) timeout to prevent maxing the CPU input = self._nl_input_queue.get(True, 0.1).strip() ResourcePool().mark_active(self._speaker) self._logger.info( colored_print("\n-------[ NL INPUT ]-------\n", 'green')) self._logger.info(colored_print("- " + input + "\n", 'blue')) self.in_interaction = True try: self._process(input) except UnsufficientInputError as uie: self._logger.info( colored_print( "Not enough informations! Going back to human:", 'magenta')) self._last_output = uie.value #Output towards human sys.stdout.write( self._verbalizer.verbalize(uie.value['question']) + "\n") sys.stdout.flush() self._logger.info( colored_print( "- " + self._verbalizer.verbalize( uie.value['question']), 'blue') + "\n") #Waiting for more info to solve content self.waiting_for_more_info = True except InterruptedInteractionError as iie: self._logger.info( colored_print( "I can not continue. I interrupt the interaction.", 'magenta')) #Output towards human sys.stdout.write( self._verbalizer.verbalize(iie.value) + "\n") sys.stdout.flush() self._logger.info( colored_print( "- " + self._verbalizer.verbalize(iie.value), 'blue') + "\n") except UnidentifiedAnaphoraError as uae: self._logger.info( colored_print( "Not sure of the interpretation... Asking for confirmation to human:", 'magenta')) self._anaphora_input = uae.value #waiting for more info to solve anaphora self.waiting_for_more_info = True #Output towards human sys.stdout.write( self._verbalizer.verbalize(uae.value['question']) + "\n") sys.stdout.flush() self._logger.info("- " + colored_print( self._verbalizer.verbalize(uae.value['question']), 'blue') + "\n") except GrammaticalError as ge: self._logger.info(colored_print("Grammatical error! " + \ "I can not correctly parse the sentence. Asking " + \ "the speaker to reformulate", 'magenta')) #waiting for more info to solve anaphora self.waiting_for_more_info = True #Output towards human sys.stdout.write( "I didn't really understand your last sentence. Could you reformulate?\n" ) sys.stdout.flush() except DialogError as de: self._logger.info( colored_print("Error! " + de.value, 'magenta')) #Output towards human emotions.confused() sys.stdout.write( "Sorry, I'm confused... Could you repeat in a different way?\n" ) sys.stdout.flush() except KbError as ke: self._logger.info( colored_print("Error! " + ke.value, 'magenta')) #Output towards human emotions.confused() sys.stdout.write( "Sorry, I'm confused... My knowledge looks somehow broken...\n" ) sys.stdout.flush() # interrupt the interaction self.in_interaction = False except Empty: pass try: output = self._sentence_output_queue.get(block=False) self._logger.info(colored_print("> Returning output: ", 'bold')) nl_output = self._verbalizer.verbalize(output) sys.stdout.write(nl_output + "\n") sys.stdout.flush() self._logger.info("- " + colored_print(nl_output, 'blue') + "\n") except Empty: pass
def process_sentence(self, sentence): """This processes a w_question or yes_no_question sentence""" self._sentence = sentence #StatementBuilder builder = StatementBuilder(self._current_speaker) self._statements, situation_id = builder.process_sentence( self._sentence) logger.info( level_marker(level=2, color="yellow") + "Generated statements based on the sentence components: " + colored_print(str(self._statements), None, "magenta")) #Case the question is a y_n_question : check the fact in the ontology if sentence.data_type == YES_NO_QUESTION: self._statements = self._set_situation_id(self._statements) logger.info( level_marker(level=2, color="yellow") + "Generated statements for this question: " + colored_print(str(self._statements), None, "magenta")) #Processing :Do you know something? if self.process_on_knowing_concept: #self._statements = [agent knows object] for s in self._statements: self._answer = True if "knows" in s: [agent, object] = s.split(" knows ") onto_lookup = [] logger.debug( level_marker(level=2, color="yellow") + "Looking up for " + object + " in " + agent + "'s model") onto_lookup = ResourcePool( ).ontology_server.lookupForAgent( ResourcePool().get_model_mapping(agent), object) self._answer = self._answer and (True if onto_lookup else False) self.process_on_knowing_concept = False else: logger.debug( level_marker(level=2, color="yellow") + "Checking in the ontology: " + colored_print(str(self._statements), None, "magenta")) self._answer = ResourcePool().ontology_server.check( self._statements) #Case the question is a w_question : find the concept the concept that answers the question if sentence.data_type == W_QUESTION: # self._query_on_field = self._set_query_on_field(sentence) statements_with_bound_tokens = self._remove_statements_with_no_unbound_tokens( self._statements) #Agent from which the ontology model is queried agent = self._default_agent self._answer = [] #For all the possible subjects of a same question if not self._sentence.sn: statements_to_query = [ self._extend_statement_from_sentence_aim( statements_with_bound_tokens) ] else: statements_to_query = [ self._extend_statement_from_sentence_aim( statements_with_bound_tokens, sn) for sn in self._sentence.sn ] for statements in statements_to_query: if self.process_on_knowing_concept: #Get agent in a statement such as [agent knows object] for s in statements: if "knows" in s: [agent, object] = s.split(" knows ") break #No need of statements such as [S knows O] [statements.remove(s) for s in statements if "knows" in s] self.process_on_knowing_concept = False if statements: logger.info( level_marker(level=2, color="yellow") + "Generated statements for this question: " + colored_print(str(self._statements), None, "magenta")) answers = [] if self._process_on_location: prepositions_list = ResourcePool( ).preposition_rdf_object_property.copy() roles = dict([(preposition, prepositions_list[preposition][0]) \ for preposition in prepositions_list.keys() \ if 'objectFoundInLocation' in prepositions_list[preposition]]) #Case of ojectFound in location stmts = [] prepositions_already_used = [] for role in roles: if roles[role] in prepositions_already_used: continue stmts = [ s.replace('objectFoundInLocation', roles[role]) for s in statements ] logger.debug( level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print(str(stmts), None, "magenta")) answers = ResourcePool( ).ontology_server.findForAgent( ResourcePool().get_model_mapping(agent), '?concept', stmts) prepositions_already_used.append(roles[role]) if answers: ResourcePool().mark_active(answers) self._answer.append([[role], answers]) #Case of object found in location + direction stmts = [ s.replace('objectFoundInLocation', 'isAt') for s in statements ] for role in ResourcePool().direction_words: logger.debug( level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print( str(stmts + [ '?concept is' + role.capitalize() + 'Of ?obj', '?concept rdf:type Location' ]), None, "magenta")) answers = ResourcePool( ).ontology_server.findForAgent( ResourcePool().get_model_mapping(agent), '?obj', stmts + [ '?concept is' + role.capitalize() + 'Of ?obj', '?concept rdf:type Location' ]) if answers: ResourcePool().mark_active(answers) self._answer.append([[role], answers]) else: logger.debug( level_marker(level=2, color="yellow") + "Searching in " + agent + " model: " + colored_print(str(statements), None, "magenta")) answers = ResourcePool().ontology_server.findForAgent( ResourcePool().get_model_mapping(agent), '?concept', statements) if answers: ResourcePool().mark_active(answers) self._answer.append([[], answers]) else: pass self._statements.extend(statements) stmts, sit_id = self._build_situation_statements() return self._answer, stmts, sit_id
def findForAgent(self, model, var, query): self.log.info( colored_print("QUERY (in model <%s>): %s" % (model, query), 'cyan'))
def _process(self, nl_input): # Parsing self._logger.info(colored_print("\n-------[ PREPROCESSING ]-------\n", "green")) preprocessed_sentences = self._parser.preprocess(nl_input, None) for s in preprocessed_sentences: self._logger.debug(s) self._logger.info(colored_print("\n-------[ PARSING ]-------\n", "green")) parsed_sentences = self._parser.parse(preprocessed_sentences, None) for s in parsed_sentences: self._logger.debug(str(s)) if self._demo_mode: wait_for_keypress() # Unsufficient input or unidentified anaphora Error processing for s in parsed_sentences: # Check the sentence is grammatically valid, else go back to the human if not s.isvalid(): raise GrammaticalError(s) if s.isaborting(): parsed_sentences.remove(s) self._last_output = self._anaphora_input = None self.waiting_for_more_info = False sys.stdout.write("Alright. Forgotten!\n") sys.stdout.flush() self._logger.info("- " + colored_print("Alright. Forgotten!", "blue") + "\n") break if s.islearning() and self._last_output: s.append_sub_sentence(self._last_output["sentence"]) self._last_output = None self.waiting_for_more_info = False break if self.waiting_for_more_info: self._logger.info(colored_print("Waiting for more information activated\n", "magenta")) # Processing Unsifficient input Error with sentences remerge if self._last_output: self._logger.info( colored_print("New content provided by human! merging it with the previous sentence.", "magenta") ) self._last_output["object_with_more_info"] = nominal_group_remerge( parsed_sentences, self._last_output["status"], self._last_output["object"] ) # current_sentence that is to replace if it is to answer unsificient input parsed_sentences = [self._last_output["sentence"]] # Processing Unidentified Anaphora Error with sentences replacement if self._anaphora_input: self._logger.info(colored_print("Ok. Got a confirmation. Processing it.", "magenta")) self._anaphora_input["object_with_more_info"] = replacement( parsed_sentences, self._anaphora_input["object"], self._anaphora_input["objects_list"][1:], self._anaphora_input["object_to_confirm"], ) # current_sentence that is to replace if it is to answer unidentified anaphora parsed_sentences = [self._anaphora_input["sentence"]] # No more info needed self.waiting_for_more_info = False # end of Unsufficient input or unidentified anaphora Error processing # Sentences Queue() [self.sentences.append(stnts) for stnts in parsed_sentences] for s in range(len(self.sentences)): # sentences is a deque. Cannot do a simple [:] to iterate over a copy self.active_sentence = self.sentences.popleft() # Resolution self._resolver.sentences_store = Dialog.dialog_history uie_object = self._last_output["object"] if self._last_output else None uie_object_with_more_info = self._last_output["object_with_more_info"] if uie_object else None self._last_output = None uae_object = self._anaphora_input["object"] if self._anaphora_input else None uae_object_with_more_info = self._anaphora_input["object_with_more_info"] if uae_object else None uae_object_list = self._anaphora_input["objects_list"] if uae_object else None self._anaphora_input = None self._logger.info(colored_print("\n-------[ RESOLVING SENTENCE ]-------\n", "green")) self.active_sentence = self._resolver.references_resolution( self.active_sentence, self.current_speaker, uae_object, uae_object_with_more_info, uae_object_list ) self.active_sentence = self._resolver.noun_phrases_resolution( self.active_sentence, self.current_speaker, uie_object, uie_object_with_more_info ) self.active_sentence = self._resolver.verbal_phrases_resolution(self.active_sentence) self._logger.info(colored_print("\n[ Sentence after resolution ]", "green")) self._logger.info(str(self.active_sentence)) if self._demo_mode: wait_for_keypress() # Content analysis self._logger.info(colored_print("\n-------[ CONTENT ANALYSIS ]-------\n", "green")) self.last_stmts_set, self.current_situation_id = self._content_analyser.analyse( self.active_sentence, self.current_speaker ) if self._demo_mode: wait_for_keypress() # Verbalization if self._content_analyser.analyse_output(): self._logger.info(colored_print("\n-------[ VERBALIZATION ]-------\n", "green")) self.last_sentence = ( self._content_analyser.analyse_output(), self._verbalizer.verbalize(self._content_analyser.analyse_output()), ) if self.current_situation_id: self._logger.debug( colored_print("Answer: <%s>: Sent to knowledge base." % self.last_sentence[1], "magenta") ) self._logger.debug("Up to the robot controller now!") ResourcePool().ontology_server.revise( ['%s verbalisesTo "%s"' % (self.current_situation_id, self.last_sentence[1])], {"method": "add", "models": [ResourcePool().default_model]}, ) else: self._sentence_output_queue.put(self.last_sentence[0]) if self._demo_mode: wait_for_keypress() else: self._logger.info(colored_print("\nNothing to verbalize!", "magenta")) self.last_sentence = (None, "") # Dialog History self._logger.debug(colored_print("Sentence and answer saved in history.", "magenta")) Dialog.dialog_history.append(self.active_sentence) if self.last_sentence[0]: Dialog.dialog_history.extend(self.last_sentence[0]) # Finalizing the processing self.active_sentence = None self._logger.info(colored_print('\n[ NL sentence "' + nl_input + '" processed! ]', "green")) if self.last_sentence[0] and self.last_sentence[0][0].data_type == END: # Exit! self.stop() self.in_interaction = False
def run(self): while self.go_on: try: # block with a (short) timeout to prevent maxing the CPU input = self._nl_input_queue.get(True, 0.1).strip() ResourcePool().mark_active(self._speaker) self._logger.info(colored_print("\n-------[ NL INPUT ]-------\n", "green")) self._logger.info(colored_print("- " + input + "\n", "blue")) self.in_interaction = True try: self._process(input) except UnsufficientInputError as uie: self._logger.info(colored_print("Not enough informations! Going back to human:", "magenta")) self._last_output = uie.value # Output towards human sys.stdout.write(self._verbalizer.verbalize(uie.value["question"]) + "\n") sys.stdout.flush() self._logger.info( colored_print("- " + self._verbalizer.verbalize(uie.value["question"]), "blue") + "\n" ) # Waiting for more info to solve content self.waiting_for_more_info = True except InterruptedInteractionError as iie: self._logger.info(colored_print("I can not continue. I interrupt the interaction.", "magenta")) # Output towards human sys.stdout.write(self._verbalizer.verbalize(iie.value) + "\n") sys.stdout.flush() self._logger.info(colored_print("- " + self._verbalizer.verbalize(iie.value), "blue") + "\n") except UnidentifiedAnaphoraError as uae: self._logger.info( colored_print("Not sure of the interpretation... Asking for confirmation to human:", "magenta") ) self._anaphora_input = uae.value # waiting for more info to solve anaphora self.waiting_for_more_info = True # Output towards human sys.stdout.write(self._verbalizer.verbalize(uae.value["question"]) + "\n") sys.stdout.flush() self._logger.info( "- " + colored_print(self._verbalizer.verbalize(uae.value["question"]), "blue") + "\n" ) except GrammaticalError as ge: self._logger.info( colored_print( "Grammatical error! " + "I can not correctly parse the sentence. Asking " + "the speaker to reformulate", "magenta", ) ) # waiting for more info to solve anaphora self.waiting_for_more_info = True # Output towards human sys.stdout.write("I didn't really understand your last sentence. Could you reformulate?\n") sys.stdout.flush() except DialogError as de: self._logger.info(colored_print("Error! " + de.value, "magenta")) # Output towards human emotions.confused() sys.stdout.write("Sorry, I'm confused... Could you repeat in a different way?\n") sys.stdout.flush() except KbError as ke: self._logger.info(colored_print("Error! " + ke.value, "magenta")) # Output towards human emotions.confused() sys.stdout.write("Sorry, I'm confused... My knowledge looks somehow broken...\n") sys.stdout.flush() # interrupt the interaction self.in_interaction = False except Empty: pass try: output = self._sentence_output_queue.get(block=False) self._logger.info(colored_print("> Returning output: ", "bold")) nl_output = self._verbalizer.verbalize(output) sys.stdout.write(nl_output + "\n") sys.stdout.flush() self._logger.info("- " + colored_print(nl_output, "blue") + "\n") except Empty: pass
def lookupForAgent(self, model, query): self.log.info( colored_print("LOOKUP (in model <%s>): %s" % (model, query), 'cyan'))
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
def __getitem__(self, query): self.log.info(colored_print("QUERY: %s" % query, 'cyan' ))
def lookupForAgent(self, model, query): self.log.info(colored_print("LOOKUP (in model <%s>): %s" % (model, query), 'cyan'))
def _process(self, nl_input): #Parsing self._logger.info( colored_print("\n-------[ PREPROCESSING ]-------\n", 'green')) preprocessed_sentences = self._parser.preprocess(nl_input, None) for s in preprocessed_sentences: self._logger.debug(s) self._logger.info( colored_print("\n-------[ PARSING ]-------\n", 'green')) parsed_sentences = self._parser.parse(preprocessed_sentences, None) for s in parsed_sentences: self._logger.debug(str(s)) if self._demo_mode: wait_for_keypress() #Unsufficient input or unidentified anaphora Error processing for s in parsed_sentences: #Check the sentence is grammatically valid, else go back to the human if not s.isvalid(): raise GrammaticalError(s) if s.isaborting(): parsed_sentences.remove(s) self._last_output = self._anaphora_input = None self.waiting_for_more_info = False sys.stdout.write("Alright. Forgotten!\n") sys.stdout.flush() self._logger.info( "- " + colored_print("Alright. Forgotten!", 'blue') + "\n") break if s.islearning() and self._last_output: s.append_sub_sentence(self._last_output['sentence']) self._last_output = None self.waiting_for_more_info = False break if self.waiting_for_more_info: self._logger.info( colored_print("Waiting for more information activated\n", 'magenta')) #Processing Unsifficient input Error with sentences remerge if self._last_output: self._logger.info( colored_print( "New content provided by human! merging it with the previous sentence.", 'magenta')) self._last_output[ 'object_with_more_info'] = nominal_group_remerge( parsed_sentences, self._last_output['status'], self._last_output['object']) #current_sentence that is to replace if it is to answer unsificient input parsed_sentences = [self._last_output['sentence']] #Processing Unidentified Anaphora Error with sentences replacement if self._anaphora_input: self._logger.info( colored_print("Ok. Got a confirmation. Processing it.", 'magenta')) self._anaphora_input['object_with_more_info'] = replacement( parsed_sentences, self._anaphora_input['object'], self._anaphora_input['objects_list'][1:], self._anaphora_input['object_to_confirm']) #current_sentence that is to replace if it is to answer unidentified anaphora parsed_sentences = [self._anaphora_input['sentence']] #No more info needed self.waiting_for_more_info = False #end of Unsufficient input or unidentified anaphora Error processing #Sentences Queue() [self.sentences.append(stnts) for stnts in parsed_sentences] for s in range( len(self.sentences) ): #sentences is a deque. Cannot do a simple [:] to iterate over a copy self.active_sentence = self.sentences.popleft() #Resolution self._resolver.sentences_store = Dialog.dialog_history uie_object = self._last_output[ 'object'] if self._last_output else None uie_object_with_more_info = self._last_output[ 'object_with_more_info'] if uie_object else None self._last_output = None uae_object = self._anaphora_input[ 'object'] if self._anaphora_input else None uae_object_with_more_info = self._anaphora_input[ 'object_with_more_info'] if uae_object else None uae_object_list = self._anaphora_input[ 'objects_list'] if uae_object else None self._anaphora_input = None self._logger.info( colored_print("\n-------[ RESOLVING SENTENCE ]-------\n", 'green')) self.active_sentence = self._resolver.references_resolution( self.active_sentence, self.current_speaker, uae_object, uae_object_with_more_info, uae_object_list) self.active_sentence = self._resolver.noun_phrases_resolution( self.active_sentence, self.current_speaker, uie_object, uie_object_with_more_info) self.active_sentence = self._resolver.verbal_phrases_resolution( self.active_sentence) self._logger.info( colored_print("\n[ Sentence after resolution ]", 'green')) self._logger.info(str(self.active_sentence)) if self._demo_mode: wait_for_keypress() #Content analysis self._logger.info( colored_print("\n-------[ CONTENT ANALYSIS ]-------\n", 'green')) self.last_stmts_set, self.current_situation_id = self._content_analyser.analyse( self.active_sentence, self.current_speaker) if self._demo_mode: wait_for_keypress() #Verbalization if self._content_analyser.analyse_output(): self._logger.info( colored_print("\n-------[ VERBALIZATION ]-------\n", 'green')) self.last_sentence = ( self._content_analyser.analyse_output(), self._verbalizer.verbalize( self._content_analyser.analyse_output())) if self.current_situation_id: self._logger.debug( colored_print( "Answer: <%s>: Sent to knowledge base." % self.last_sentence[1], 'magenta')) self._logger.debug("Up to the robot controller now!") ResourcePool().ontology_server.revise( [ '%s verbalisesTo "%s"' % (self.current_situation_id, self.last_sentence[1]) ], { "method": "add", "models": [ResourcePool().default_model] }) else: self._sentence_output_queue.put(self.last_sentence[0]) if self._demo_mode: wait_for_keypress() else: self._logger.info( colored_print("\nNothing to verbalize!", 'magenta')) self.last_sentence = (None, "") #Dialog History self._logger.debug( colored_print("Sentence and answer saved in history.", 'magenta')) Dialog.dialog_history.append(self.active_sentence) if self.last_sentence[0]: Dialog.dialog_history.extend(self.last_sentence[0]) #Finalizing the processing self.active_sentence = None self._logger.info( colored_print("\n[ NL sentence \"" + nl_input + "\" processed! ]", 'green')) if self.last_sentence[0] and self.last_sentence[0][0].data_type == END: # Exit! self.stop() self.in_interaction = False
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
def revise(self, stmts, options): self.log.info(colored_print("REVISE (%s): %s" % (options,stmts), 'cyan'))
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
def __getitem__(self, query): self.log.info(colored_print("QUERY: %s" % query, 'cyan'))
def revise(self, stmts, options): self.log.info( colored_print("REVISE (%s): %s" % (options, stmts), 'cyan'))
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