def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.reload() self.oro.add(['shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'table2 rdf:type Table', 'table2 hasColor blue', 'Banana rdfs:subClassOf Plant', 'y_banana rdf:type Banana', 'y_banana hasColor yellow', 'y_banana isOn shelf1', 'green_banana rdf:type Banana', 'green_banana hasColor green', 'green_banana isOn table2', 'ACCESSKIT rdf:type Gamebox', 'ACCESSKIT hasColor white', 'ACCESSKIT hasSize big', 'ACCESSKIT isOn table1', 'ORANGEBOX rdf:type Gamebox', 'ORANGEBOX hasColor orange', 'ORANGEBOX hasSize big', 'ORANGEBOX isOn ACCESSKIT', 'MYBOX rdf:type Gamebox', 'MYBOX hasColor orange', 'MYBOX hasSize small', 'MYBOX isOn ACCESSKIT', 'SPACENAVBOX rdf:type Gamebox', 'SPACENAVBOX hasColor white', 'SPACENAVBOX hasSize big', 'SPACENAVBOX isOn ACCESSKIT', 'y_bottle rdf:type Bottle', 'y_bottle isLocated RIGHT', 'r_bottle rdf:type Bottle', 'r_bottle isLocated FRONT', 'b_bottle rdf:type Bottle', 'b_bottle isLocated BACK' ]) except AttributeError: #the ontology server is not started of doesn't know the method pass
def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add(['ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'table1 rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn table1', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn table1', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn table1', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: pass try: self.oro.addForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'table1 rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn table1', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn table1', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn table1', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: pass
def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.reload() self.oro.add( [ "shelf1 rdf:type Shelf", "table1 rdf:type Table", "table2 rdf:type Table", "table2 hasColor blue", "Banana rdfs:subClassOf Plant", "y_banana rdf:type Banana", "y_banana hasColor yellow", "y_banana isOn shelf1", "green_banana rdf:type Banana", "green_banana hasColor green", "green_banana isOn table2", "ACCESSKIT rdf:type Gamebox", "ACCESSKIT hasColor white", "ACCESSKIT hasSize big", "ACCESSKIT isOn table1", "ORANGEBOX rdf:type Gamebox", "ORANGEBOX hasColor orange", "ORANGEBOX hasSize big", "ORANGEBOX isOn ACCESSKIT", "MYBOX rdf:type Gamebox", "MYBOX hasColor orange", "MYBOX hasSize small", "MYBOX isOn ACCESSKIT", "SPACENAVBOX rdf:type Gamebox", "SPACENAVBOX hasColor white", "SPACENAVBOX hasSize big", "SPACENAVBOX isOn ACCESSKIT", "y_bottle rdf:type Bottle", "y_bottle isLocated RIGHT", "r_bottle rdf:type Bottle", "r_bottle isLocated FRONT", "b_bottle rdf:type Bottle", "b_bottle isLocated BACK", ] ) except AttributeError: # the ontology server is not started of doesn't know the method pass
def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add(['shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'table2 rdf:type Table', 'table2 hasColor blue', 'Banana rdfs:subClassOf Plant', 'y_banana rdf:type Banana', 'y_banana hasColor yellow', 'y_banana isAt LEFT', 'y_banana isAt shelf1_front', 'shel1_front rdf:type Location', 'LEFT isLeftOf myself', 'LEFT rdf:type Location', 'shelf1_front isFrontOf shelf1', 'green_banana rdf:type Banana', 'green_banana hasColor green', 'green_banana isOn table2', 'green_banana isAt FRONT', 'FRONT rdf:type Location', 'FRONT isFrontOf myself', 'myself focusesOn y_banana', 'myself rdfs:label "Jido"', 'myself sees id_tom', 'myself sees y_banana', 'myself sees shelf1', 'myself_name rdf:type Name', 'myself_name belongsTo myself', 'myself_name rdfs:label "Jido"', 'id_tom rdf:type Human', 'id_tom rdfs:label "Tom"', 'id_tom isNextTo myself', 'Banana rdfs:subClassOf Object', ]) except AttributeError: #the ontology server is not started of doesn't know the method pass
def w_quest_quant(type, request, sentence): """ process many different type of quantity question Input=type and requesting of sentence, the sentence and beginning sentence list Output=class Sentence """ for j in ResourcePool().sentence_starts: if sentence[2] == j[0]: if j[1] == '3': #This case is the same with y_n_question return y_n_ques(type, request, sentence[2:]) analysis = y_n_ques(type, request, sentence[3:]) #There is not sn in the sentence if not analysis.sn: analysis.sn = [NominalGroup(['a'], [sentence[2]], [], [], [])] else: #There is not direct object in the sentence analysis.sv[0].d_obj = [NominalGroup(['a'], [sentence[2]], [], [], [])] return analysis
def get_values_for_descriptor(self, agent, descriptor, objL): valL = [] # get values for each object for obj in objL: # if the discriminant is type, then look for the directClass of the obj (first found) # how should this work for different agents? There is no directClassForAgent # probably won't be necessary since all the knowledge of the human is part # of the robot's knowledge as well. Then we can obtain this information # directly from the robot itself. if descriptor == 'rdf:type': val = self.oro.getDirectClassesOf(obj).keys() else: val = self.oro.findForAgent( ResourcePool().get_model_mapping(agent), '?val', [obj + ' ' + descriptor + ' ?val']) if val: #TODO: we only consider the first result item! valL.append(self.oro.getLabel(val[0])) # otherwise, the object doesn't have this descriptor, and we don't include it # we make a set to remove repeated elements return list(set(valL))
def convert_to_digit(det): """ Function convert the determinant to digit Input=word Output=digit (string form) """ #init num = k = 0 for n in ResourcePool().numbers: if det.startswith(n[1]): return det while k < len(det): if det[k] != '+': k += 1 else: num = word_to_digit(det[:k], num) det = det[k + 1:] k = 0 num = word_to_digit(det, num) return str(num)
def process_noun_phrases(self, nominal_group, ng_id, ng_quantifier, negative_object): def get_object_property(subject_quantifier, object_quantifier): """ The following returns the appropriate object property relationship between two nominal groups; the subject and the object. These are the rule: - ONE + ONE => rdf:type ; E.g: [The blue cube] is [small]. Here, both nominal groups of 'the blue cube' and 'small' hold the quantifier 'ONE' - ONE + SOME => rdf:type; E.g: [The blue object] is [a robot]. Here, the nominal group of robot holds the indefinite quantifier 'SOME' - SOME + SOME => rdfs:subClassOf; E.g: [an apple] is [a fruit]. Both the quantifier of the nominal groups of "apple" and "fruit" are 'SOME'. This is a convention for all nomina group with an indefinite determiner - ALL + ALL => rdfs:subClassOf ; E.g: [Apples] are [fruits]. E.g: [the apples] are [the fruits]. Here, both Apples and Fruits hold the quantifier 'ALL'. This is a convention for all nominal group with plural nouns for more details about quantifiers, see sentence.py """ if [subject_quantifier, object_quantifier] in [['SOME', 'SOME'], ['ALL', 'ALL']]: return ' rdfs:subClassOf ' else: # default case return ' rdf:type ' # End of def get_object_property() for noun in nominal_group.noun: # Case : existing ID onto_id = '' try: onto_id = ResourcePool().ontology_server.lookupForAgent( ResourcePool().get_model_mapping(self._current_speaker), noun) except KbError: # The agent does not exist in the ontology pass instance_id = None if onto_id: # If one of the returned concepts is an instance, take the first one. for c in onto_id: if "instance" in c: instance_id = c[0] break if instance_id: # Case of Negation if negative_object: self._statements.append(ng_id + " owl:differentFrom " + instance_id) elif nominal_group._resolved: self._statements.append(ng_id + " owl:sameAs " + instance_id) # Case : Personal pronoun elif not nominal_group.det and noun in ResourcePool().pronouns: # Case of negation if negative_object: # assign noun_id == current_speaker ID or Current receipient, or so on noun_id = None if noun in ["I", "me"]: noun_id = self._current_speaker elif noun in ["you"]: noun_id = "myself" if noun_id: self._statements.append(ng_id + " owl:differentFrom " + noun_id) else: logger.debug("Aie Aie!! Personal pronoun " + noun + " Not implemented yet!") # Case of affirmative form else: pass # Case : proper noun (Always Capitalized in sentence, and never follows a determiner) elif not nominal_group.det and noun.istitle(): logger.info( "... \t" + noun + " is being processed as a proper noun in " + self._current_speaker + "'s model.") self._statements.append(ng_id + " rdfs:label \"" + noun + "\"") # Case : common noun else: logger.info( "... \t" + noun + " is being processed as a common noun in " + self._current_speaker + "'s model.") # Case of Directions if noun in ResourcePool().direction_words: class_name = 'Location' if not nominal_group.noun_cmpl: self._statements.append(ng_id + " is" + noun.capitalize() + "Of " + self._current_speaker) # get the exact class name (capitalized letters where needed) else: class_name = get_class_name(noun, onto_id) # get the exact object property (subClassOf or type) object_property = get_object_property(ng_quantifier, nominal_group._quantifier) # Case of negation if negative_object: # Case of a definite concept if nominal_group._quantifier == 'ONE': self._statements.append(ng_id + " owl:differentFrom " + nominal_group.id) # Case of an indefinite concept else: #Committing ComplementOf class ResourcePool().ontology_server.safeAdd( ["ComplementOf" + class_name + " owl:complementOf " + class_name, "ComplementOf" + class_name + " rdfs:subClassOf ComplementClasses"]) self._statements.append(ng_id + object_property + "ComplementOf" + class_name) # Case of affirmative sentence else: if isinstance(ng_id, basestring): ng_id = [ng_id] self._statements += [id + object_property + class_name for id in ng_id]
def nom_struc_rebuilding(nom_struc): """ This function recovers nominal structure Input=class nominal structure Output=phrase concatenate all information of this class """ #init nominal_structure = ns = nn = [] i = 0 while i < len(nom_struc): if nom_struc[i]._quantifier == 'SOME' and (nom_struc[i].det == ['a'] or nom_struc[i].det == ['an']): nom_struc[i]._quantifier = 'ONE' #The first nominal group not preceded but 'and' if there is if nom_struc[i]._conjunction == 'AND' and i > 0: nominal_structure = nominal_structure + ['and'] elif nom_struc[i]._conjunction == 'OR': nominal_structure = nominal_structure + ['or'] elif nom_struc[i]._conjunction == 'BUT': nominal_structure = nominal_structure + ['but'] #We recover the nominal group and his complement if nom_struc[i]._quantifier == 'SOME' or nom_struc[ i]._quantifier == 'ALL' or nom_struc[ i]._quantifier == 'ANY' or (nom_struc[i]._quantifier == 'DIGIT' and nom_struc[i].det != 'one'): #If there is a specific quantifier (plural) for n in ResourcePool().plural_nouns: if nom_struc[i].noun != [] and n[1] == nom_struc[i].noun[0]: nn = [n[0]] #If it is not a specific plural, we add 's' if nom_struc[i].noun != [] and nn == []: nn = [nom_struc[i].noun[0] + 's'] #We reconver the other information nominal_structure = nominal_structure + nom_struc[i].det for z in nom_struc[i].adj: nominal_structure = nominal_structure + z[1] + [z[0]] nominal_structure = nominal_structure + nn #Re-init nn = [] else: #if not plural nominal_structure = nominal_structure + nom_struc[i].det for z in nom_struc[i].adj: nominal_structure = nominal_structure + z[1] + [z[0]] nominal_structure = nominal_structure + nom_struc[i].noun #We recover noun complement if nom_struc[i].noun_cmpl: nominal_structure = nominal_structure + ['of'] nominal_structure = nominal_structure + nom_struc_rebuilding( nom_struc[i].noun_cmpl) #We recover the relative for j in nom_struc[i].relative: if not j.sn: ns = [nom_struc[i]] nominal_structure = nominal_structure + [ j.aim ] + sentence_rebuilding.relative(j, ns) ns = [] i += 1 return nominal_structure
def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add([ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) """ self.oro.addForAgent('ACHILLE', ['BLUE_TRASHBIN rdf:type Trashbin', 'PINK_TRASHBIN rdf:type Trashbin', 'BLACK_TAPE rdf:type VideoTape', 'BLACK_TAPE isIn PINK_TRASHBIN', 'GREY_TAPE rdf:type VideoTape', 'GREY_TAPE isOn HRP2TABLE']) """ except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('ACHILLE',[ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('JULIE',[ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise
class TestQuestionHandlerDialog(unittest.TestCase): """Tests the processing of question by the Dialog module. This must be tested with oro-server using the testsuite.oro.owl ontology. """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add(['shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'table2 rdf:type Table', 'table2 hasColor blue', 'Banana rdfs:subClassOf Plant', 'y_banana rdf:type Banana', 'y_banana hasColor yellow', 'y_banana isAt LEFT', 'y_banana isAt shelf1_front', 'shel1_front rdf:type Location', 'LEFT isLeftOf myself', 'LEFT rdf:type Location', 'shelf1_front isFrontOf shelf1', 'green_banana rdf:type Banana', 'green_banana hasColor green', 'green_banana isOn table2', 'green_banana isAt FRONT', 'FRONT rdf:type Location', 'FRONT isFrontOf myself', 'myself focusesOn y_banana', 'myself rdfs:label "Jido"', 'myself sees id_tom', 'myself sees y_banana', 'myself sees shelf1', 'myself_name rdf:type Name', 'myself_name belongsTo myself', 'myself_name rdfs:label "Jido"', 'id_tom rdf:type Human', 'id_tom rdfs:label "Tom"', 'id_tom isNextTo myself', 'Banana rdfs:subClassOf Object', ]) except AttributeError: #the ontology server is not started of doesn't know the method pass def test_question1_where(self): logger.info("\n##################### test_question1_where ########################\n") #### stmt = "Where is the green banana?" #### ### res = self.dialog.test('myself', stmt) logger.info(">> input: " + stmt) self.assertTrue(val in res[1][1] for val in ["The green banana", "is", "on the blue table", "in front of me"]) logger.info("\n##################### test_question1_where ########################\n") #### stmt = "Where is the yellow banana?" #### ### res = self.dialog.test('myself', stmt) logger.info(">> input: " + stmt) self.assertTrue(val in res[1][1] for val in ["The yellow banana is", "in front of the shelf", "at my left"]) def test_question2_what(self): logger.info("\n##################### test_question2_what ########################\n") #### stmt = "What is yellow?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "The yellow banana.") def test_question3_what(self): logger.info("\n##################### test_question3_what ########################\n") stmt = "What object is yellow?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "The yellow banana.") def test_question4_what(self): logger.info("\n##################### test_question4_what ########################\n") stmt = "What color is the banana that is on the blue table?" #### ### res = self.dialog.test('myself', stmt) self.assertTrue(val in res[1][1] for val in ["The banana", "that's", "on the blue table", "is green"]) def test_question5_what(self): logger.info("\n##################### test_question5_what ########################\n") stmt = "What is this?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "This is the yellow banana.") def test_question6_who(self): logger.info("\n##################### test_question6_who ########################\n") #### stmt = "Who are you?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "I am Jido.") def test_question6_who(self): logger.info("\n##################### test_question6_who_bis ########################\n") #### stmt = "What is your name?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "My name is Jido.") def test_question7_who(self): logger.info("\n##################### test_question7_who ########################\n") stmt = "Who is the myself?" #### ### res = self.dialog.test('myself', stmt) self.assertTrue(val in res[1][1] for val in ["The myself", "Jido"]) def test_question8_who(self): logger.info("\n##################### test_question8_who ########################\n") stmt = "Who do you see?" res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "I see Tom.") def test_question8_what(self): logger.info("\n##################### test_question8_what ########################\n") stmt = "What do you see?" res = self.dialog.test('myself', stmt) self.assertTrue(val in res[1][1] for val in ["I see", "Tom", "the yellow banana", "and", "the shelf"]) def test_question9_who(self): logger.info("\n##################### test_question9_who ########################\n") stmt = "Who is Tom?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "Tom is Tom.") def test_question10(self): logger.info("\n##################### test_question10 ########################\n") stmt = "Do you see the yellow banana?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "Yes. I see the yellow banana.") def test_question11(self): logger.info("\n##################### test_question11 ########################\n") stmt = "is the yellow banana on the shelf?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "Yes. The yellow banana is on the shelf.") def test_question12(self): logger.info("\n##################### Check label ########################\n") stmt = "What human do you see?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "I see Tom.") def test_question13(self): logger.info("\n##################### Check label ########################\n") stmt = "What human do you know?" #### ### res = self.dialog.test('myself', stmt) self.assertTrue(val in res[1][1] for val in ["I know Tom"]) def test_question14(self): logger.info("\n##################### KNOW ########################\n") stmt = "What object do you know?" #### ### res = self.dialog.test('myself', stmt) self.assertTrue(val in res[1][1] for val in ["I know", "Tom", "the yellow banana", "the green banana", "the table", "and", "the shelf"]) def test_question15(self): logger.info("\n##################### KNOW ########################\n") stmt = "do you know the yellow banana?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "Yes. I know the yellow banana.") def test_question16(self): logger.info("\n##################### WHICH ########################\n") stmt = "which banana is at the left?" #### ### res = self.dialog.test('myself', stmt) self.assertEquals(res[1][1], "The yellow banana.")
class TestDiscriminateCompleteDialog(unittest.TestCase): """Tests the differents features of the Dialog module. This must be tested with oro-server using the testsuite.oro.owl ontology. """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.reload() self.oro.add([ 'shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'table2 rdf:type Table', 'table2 hasColor blue', 'Banana rdfs:subClassOf Plant', 'y_banana rdf:type Banana', 'y_banana hasColor yellow', 'y_banana isOn shelf1', 'green_banana rdf:type Banana', 'green_banana hasColor green', 'green_banana isOn table2', 'ACCESSKIT rdf:type Gamebox', 'ACCESSKIT hasColor white', 'ACCESSKIT hasSize big', 'ACCESSKIT isOn table1', 'ORANGEBOX rdf:type Gamebox', 'ORANGEBOX hasColor orange', 'ORANGEBOX hasSize big', 'ORANGEBOX isOn ACCESSKIT', 'MYBOX rdf:type Gamebox', 'MYBOX hasColor orange', 'MYBOX hasSize small', 'MYBOX isOn ACCESSKIT', 'SPACENAVBOX rdf:type Gamebox', 'SPACENAVBOX hasColor white', 'SPACENAVBOX hasSize big', 'SPACENAVBOX isOn ACCESSKIT', 'y_bottle rdf:type Bottle', 'y_bottle isLocated RIGHT', 'r_bottle rdf:type Bottle', 'r_bottle isLocated FRONT', 'b_bottle rdf:type Bottle', 'b_bottle isLocated BACK' ]) except AttributeError: #the ontology server is not started of doesn't know the method pass def test_discriminate1(self): """ Color discriminant should be found""" logger.info( "\n##################### test_discriminate1 ########################\n" ) #### stmt = "the banana is good" answer = "the green one" #### res = self.dialog.test('myself', stmt, answer) logger.info(res) expected_result = ['green_banana hasFeature good'] self.assertTrue(check_results(res[0], expected_result)) """ Color discriminant should be found""" logger.info( "\n##################### test_discriminate2 ########################\n" ) #### stmt = "the banana is good" answer = "the yellow one" #### res = self.dialog.test('myself', stmt, answer) logger.info(res) expected_result = ['y_banana hasFeature good'] self.assertTrue(check_results(res[0], expected_result)) def test_discriminate3(self): """ Color discriminant should be found""" logger.info( "\n##################### test_discriminate3 ########################\n" ) #### stmt = "give me the banana" answer = "the green one" #### expected_result = [ 'myself desires *', '* rdf:type Give', '* performedBy myself', '* actsOnObject green_banana', '* receivedBy myself' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate4(self): """No ambiguity.""" logger.info( "\n##################### test_discriminate4 ########################\n" ) #### stmt = "get the gamebox which is on the table" answer = None #### expected_result = [ 'myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ACCESSKIT' ] ### res = self.dialog.test('myself', stmt) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate5(self): """ Size discriminant should be found """ logger.info( "\n##################### test_discriminate5 ########################\n" ) #### stmt = "get the orange gamebox" answer = "the big one" #### expected_result = [ 'myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ORANGEBOX' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate6(self): """No complete discriminant found. More info required""" logger.info( "\n##################### test_discriminate6 ########################\n" ) #### stmt = "get the big gamebox" answer = "the orange one" #### expected_result = [ 'myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ORANGEBOX' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate7(self): """ Location discriminant should be found """ logger.info( "\n##################### test_discriminate7 ########################\n" ) #### stmt = "get the white gamebox" answer = "the one which is on the table1" #### expected_result = [ 'myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ACCESSKIT' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate8(self): """ Location wrt robot discriminant should be found """ logger.info( "\n##################### test_discriminate8 ########################\n" ) #### stmt = "get the bottle" answer = "the one which is in front of you" #### expected_result = [ 'myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject r_bottle' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate9(self): logger.info( "\n##################### Class grounding ########################\n" ) #### stmt = "a fruit is a plant" answer = "a kind of thing" #### expected_result = [ 'Plant rdfs:subClassOf Thing', 'Fruit rdfs:subClassOf Plant' ] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def tearDown(self): self.dialog.stop() self.dialog.join()
def upper_to_lower(sentence): """ converts the upper case to lower case Input=sentence, beginning sentence list Output=sentence """ # If the sentence begins with upper case if other_functions.find_cap_lettre(sentence[0]): # We convert upper case to lower case if it is not 'I' if sentence[0] == 'I': sentence = expand_contractions(sentence) return sentence else: sentence[0] = sentence[0][0].lower() + sentence[0][1:] #We make changes here because we need lower case and not upper case sentence = expand_contractions(sentence) sentence = adverbial_or_subsentence(sentence) stc = process_and_beginning_sentence(sentence) #If sentence is modified we can return it if stc != sentence: return stc #We find an action verb => it is an imperative sentence if sentence[0] in ThematicRolesDict().get_all_verbs(): return sentence #If we find the word in the Beginning_sentence list for v in ResourcePool().sentence_starts: if sentence[0] == v[0]: return sentence #We find a number if other_functions.number(sentence[0]) == 1: return sentence #If there is plural sentence = analyse_nominal_group.find_plural(sentence) #If it still start with adjective if analyse_nominal_group.is_an_adj(sentence[0]) == 1: sentence = ['the'] + sentence #If there is a nominal group if analyse_nominal_group.find_sn_pos(sentence, 0): return sentence #Default case: we assume a proper name, we convert lowercase to uppercase sentence[0] = sentence[0][0].upper() + sentence[0][1:] # If the sentence begins with lower case else: #We make changes here because we need lower case and not upper case sentence = expand_contractions(sentence) sentence = adverbial_or_subsentence(sentence) sentence = process_and_beginning_sentence(sentence) #If we find the word in the Beginning_sentence list so we can return it for v in ResourcePool().sentence_starts: if sentence[0] == v[0]: return sentence #If there is plural sentence = analyse_nominal_group.find_plural(sentence) #If it still start with adjective if analyse_nominal_group.is_an_adj(sentence[0]) == 1: sentence = ['the'] + sentence return sentence
class TestMovingToLondonScenario(unittest.TestCase): """ Scenario -------- ACHILLE and JULIE are moving from Toulouse to London, and they must pack everything before leaving. ACHILLE is sorting its video tapes, and he throws away the oldest ones. Jido is watching him. Setup: One trashbin, one cardboard box, 2 tapes on the table [TAPE1 = Lord of the Robots (lotr) and TAPE2 = JIDO-E]. Complete scenario here: http://homepages.laas.fr/slemaign/wiki/doku.php?id=scenario_demo_roman """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add([ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) """ self.oro.addForAgent('ACHILLE', ['BLUE_TRASHBIN rdf:type Trashbin', 'PINK_TRASHBIN rdf:type Trashbin', 'BLACK_TAPE rdf:type VideoTape', 'BLACK_TAPE isIn PINK_TRASHBIN', 'GREY_TAPE rdf:type VideoTape', 'GREY_TAPE isOn HRP2TABLE']) """ except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('ACHILLE', [ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('JULIE', [ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise def runTest(self): """ MOVING TO LONDON SCENARIO ACHILLE puts TAPE1 in CARDBOARDBOX""" print() self.oro.add(['TAPE1 isIn CARDBOARD_BOX']) self.oro.addForAgent('ACHILLE', ['ACHILLE pointsAt CARDBOARD_BOX']) stmt = "Jido, what is in the box?" answer = "This box" #### res = self.dialog.test('ACHILLE', stmt, answer) self.assertEquals(res[1][1], "The Lords of the robots.") self.oro.removeForAgent('ACHILLE', ['ACHILLE pointsAt CARDBOARD_BOX']) stmt = "Ok. And where is the other tape?" #### self.assertEquals( self.dialog.test('ACHILLE', stmt)[1][1], "The other tape is on the table.") stmt = "Ok. Thanks." self.assertEquals( self.dialog.test('ACHILLE', stmt)[1][1], "You're welcome.") """Julie arrives, and gives two big boxes to ACHILLE. He can not take anything!""" self.oro.update(['TAPE2 isReachable false']) stmt = "Jido, can you take Jido-E?" #### res = self.dialog.test('ACHILLE', stmt) expected_result = [ 'ACHILLE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2' ] self.assertTrue(check_results(res[0], expected_result)) """Julie pushes a bit the TAPE2, which is now close enough, but still unreachable because of an obstacle. """ self.oro.addForAgent('ACHILLE', ['ACHILLE pointsAt TAPE2']) stmt = "And now, can you reach this tape?" #### ### Check ['myself reaches TAPE2'] self.assertEquals( self.dialog.test('ACHILLE', stmt)[1][1], "I don't know, if I can reach this tape now.") self.oro.removeForAgent('ACHILLE', ['ACHILLE pointsAt TAPE2']) """Julie pushes again the tape. It is now reachable. """ self.oro.update(['TAPE2 isReachable true']) stmt = "Jido, can you take it?" #### ### Do you mean Jido-E answer = "I mean Jido-E" ### res = self.dialog.test('JULIE', stmt, answer) expected_result = [ 'JULIE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2' ] self.assertTrue(check_results(res[0], expected_result)) """Achille puts JIDO-E in the trashbin. Jido still observes. Achille leaves. Julie finds JIDO-E in the trashbin, and takes it away. ACHILLE comes back to the table. """ print() self.oro.remove(['TAPE2 isOn TABLE']) self.oro.add(['TAPE2 isAt JULIE']) self.oro.addForAgent('ACHILLE', ['TAPE2 isIn TRASHBIN']) stmt = "Can you give me the tape in the trashbin?" #Expected intermediate question: "You mean, the JIDO-E tape?" #NOT FOR ROMAN demo! #answer = "Yes" #### res = self.dialog.test('ACHILLE', stmt) expected_result = [ 'ACHILLE desires *', '* rdf:type Give', '* performedBy myself', '* actsOnObject TAPE2', '* receivedBy ACHILLE' ] self.assertTrue(check_results(res[0], expected_result)) def tearDown(self): self.dialog.stop() self.dialog.join()
def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add([ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) """ self.oro.addForAgent('ACHILLE', ['BLUE_TRASHBIN rdf:type Trashbin', 'PINK_TRASHBIN rdf:type Trashbin', 'BLACK_TAPE rdf:type VideoTape', 'BLACK_TAPE isIn PINK_TRASHBIN', 'GREY_TAPE rdf:type VideoTape', 'GREY_TAPE isOn HRP2TABLE']) """ except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('ACHILLE', [ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('JULIE', [ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print( "Couldn't connect to the ontology server. Aborting the test.") raise
log_handler = logging.StreamHandler() formatter = logging.Formatter("%(message)s") log_handler.setFormatter(formatter) logger.addHandler(log_handler) import unittest from dialogs.dialog_core import Dialog from dialogs.resources_manager import ResourcePool #By default, use a remote knowledge base embeddedkb = False kb_HOST = 'localhost' kb_PORT = 6969 ResourcePool().init(kb_host=kb_HOST, kb_port=kb_PORT, embeddedkb=embeddedkb, defaultontology=None) class TestMovingToLondonScenario(unittest.TestCase): """ Scenario -------- ACHILLE and JULIE are moving from Toulouse to London, and they must pack everything before leaving. ACHILLE is sorting its video tapes, and he throws away the oldest ones. Jido is watching him. Setup: One trashbin, one cardboard box, 2 tapes on the table [TAPE1 = Lord of the Robots (lotr) and TAPE2 = JIDO-E].
def __init__(self): self.oro = ResourcePool().ontology_server
class Discrimination(object): def __init__(self): self.oro = ResourcePool().ontology_server # -- GET_ALL_OBJECTS_WITH_DESC ------------------------------------------------# # Returns all objects' ids with a given set of features (eg. green, big, etc). # Since we have several descriptions, we obtain a list of objects for each agent # and then we intersect them. # # INPUT: # - description: # [[agent1 '?obj' oro_query]..[[agentN '?obj' oro_query]] # (oro_query= ['?obj hasColor blue',.. ?obj hasShape box']) # # OUTPUT: # - empty list: no objects found fulfilling the description # - list: objects fulfilling the description # - None: no description (or description format incorrect) # -----------------------------------------------------------------------------# def get_all_objects_with_desc(self, description): obj_list = None for agent_desc in description: obj_tmp = [] try: obj_tmp = self.oro.findForAgent(agent_desc[0], agent_desc[1], agent_desc[2]) except AttributeError: # No ontology server pass except KbError: #The agent does not exist in the ontology pass # if no object found, no need to continue if not obj_tmp: obj_list = [] break else: if obj_list is None: obj_list = obj_tmp else: obj_list = filter(lambda x: x in obj_list, obj_tmp) # intersection return obj_list # -- GET_DISCRIMINANT ---------------------------------------------------------# # Queries the ontology for a list of discriminants. Returns the first one. # TODO: prioritize which discriminant to return. # # INPUT: # - agent # - object list # - ignore_descriptors: list of descriptors not to be used # - include_partial: if true, then partial discriminants are also returned # OUTPUT: # - discriminant: [C, discriminat] if complete, or [P, discriminant] if partial # The new discriminant should be different from the ones already known or ignored # -----------------------------------------------------------------------------# def get_discriminant(self, agent, obj_list, ignore_descriptors, include_partial): discriminants = self.oro.discriminateForAgent(agent, obj_list) logger.debug(colored_print('Possible discriminants: ', 'magenta') + \ str(colored_print(discriminants[1], 'blue')) + \ colored_print(" (complete discriminants: ", 'magenta') + \ str(colored_print(discriminants[0], 'blue')) + ")") complete_disc = discriminants[0] partial_disc = discriminants[1] if complete_disc: res = filter(lambda x: x not in ignore_descriptors, complete_disc) elif partial_disc and include_partial: res = filter(lambda x: x not in ignore_descriptors, partial_disc) else: res = None if res: # include randomization so the same discriminant is not always returned return choice(res) else: # No discriminant after applying the blacklist. return None # -- GET_DESCRIPTOR -----------------------------------------------------------# # Searches for a new descriptor candidate from all agents. # # INPUT: # - description: # [[agent1 '?obj' oro_query]..[[agentN '?obj' oro_query]] # (oro_query= ['?obj hasColor blue',.. ?obj hasShape box']) # - ignore_features: list of features not to use as discriminants # [feat1 ..featN] # - allowPartialDesc: consider also partial discriminants (1) or not (0) (0 default) # # OUTPUT: # - descriptor or None (if no discriminant for any agent found) # -----------------------------------------------------------------------------# def get_descriptor(self, description, ignore_features=None, partial_disc=True): if not ignore_features: ignore_features = [] objL = self.get_all_objects_with_desc(description) descriptor = None agent = None #TODO bug in oro doesn't allow to search discriminants base on other agents models!! # we cannot search in all agents, but only in robot's model # for agent_desc in description: # # list current descriptors to not to use them anymore # #currentDescriptors = map(lambda x: x.split()[1], agent_desc[2]) # descriptor = self.get_discriminant(agent_desc[0], objL, ignore_features, partial_disc) # # if descriptor: # agent = agent_desc[0] # break agent = ResourcePool().default_model # list current descriptors to not to use them anymore #currentDescriptors = map(lambda x: x.split()[1], description[0][2]) descriptor = self.get_discriminant(agent, objL, ignore_features, partial_disc) return agent, descriptor # -- get_values_for_descriptor ------------------------------------------------# # Creates the information to be sent to user based on the discriminant found. # # INPUT: # - agent, discriminant, objectsList # # OUTPUT # - list of values to ask for # -----------------------------------------------------------------------------# def get_values_for_descriptor(self, agent, descriptor, objL): valL = [] # get values for each object for obj in objL: # if the discriminant is type, then look for the directClass of the obj (first found) # how should this work for different agents? There is no directClassForAgent # probably won't be necessary since all the knowledge of the human is part # of the robot's knowledge as well. Then we can obtain this information # directly from the robot itself. if descriptor == 'rdf:type': val = self.oro.getDirectClassesOf(obj).keys() else: val = self.oro.findForAgent(agent, '?val', [obj + ' ' + descriptor + ' ?val']) if val: #TODO: we only consider the first result item! valL.append(self.oro.getLabel(val[0])) # otherwise, the object doesn't have this descriptor, and we don't include it # we make a set to remove repeated elements return list(set(valL)) # -- get_type_description ------------------------------------------------------# # Returns the first type of concept in the description. # # INPUT: # - description # # OUTPUT: # - type # - none # -------------------------------------------------------------------------------# def get_type_description(self, description): def find(value, seq): for item in seq: items = item.split() if value in items: return items[2] return None type = None for desc in description: type = find('rdf:type', desc[2]) if type: break return ResourcePool().ontology_server.getLabel(type) # -- CLARIFY ------------------------------------------------------------------# # Searches for a new descriptor candidate. The descriptor should be as # discriminating as possible. # # INPUT: # - description [['myself', '?obj', ['?obj rdf:type Bottle', '?obj hasColor blue']], # ['agent1', '?obj', ['?obj isVisible True']] # - ignoreFeatureL [feat1..featN] List of features not to use as discriminators. # # OUTPUT: # - objectID: ok # - UnsufficientInputError: # - [FAILURE, "new info required"]: no match, new info required (forget previous description) # - [SUCCESS, "Which value? ..."]: user should indicate value for descriptor (mantain previous description) # - [SUCCESS, "additional info required"]: user should give additional info (mantain previous description) # -----------------------------------------------------------------------------# 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}) #return "Give me more information about the object" def visible_subset(self, agent, id_list): """ Returns the list of visible objects for an agent from a list of objects. """ visible_objects = self.oro.findForAgent(agent, "?o", [agent + " sees ?o"]) return list(set(id_list) & set(visible_objects)) # -- ADD_DESCRIPTOR -----------------------------------------------------------# # Includes descriptor in description list. # # INPUT: # - agent: to which agent the descriptor belongs to # - description: current description # - descriptor: feature # - value: feature value # # OUTPUT: # - new description # -----------------------------------------------------------------------------# def add_descriptor(self, agent, description, descriptor, value): # return sublist index in seq containing value def find(value, seq): for index, item in enumerate(seq): if value in item: return index, item idx, desc = find(agent, description) desc[2].append('?obj ' + descriptor + ' ' + value) description[idx] = desc return description # -- FIND_UNAMBIGUOUS_DESC ---------------------------------------# # Searches an unambiguous description for a given object. # If it fails, it returns the most complete description found. # # INPUT: # - objectID: object to be described # # OUTPUT: # - a tuple (is_unambigous, description) # - is_unambigous is a boolean # - description is a set of partial statements like # "?obj rdf:type Superman" describing as well as possible # the object. # ----------------------------------------------------------------# def find_unambiguous_desc(self, objectID): description = None # get the first class name types = [t for t in self.oro.getDirectClassesOf(objectID).keys() if t not in ["ActiveConcept"]] # Not type asserted/inferred? then assume this object is unique. if not types: return True, [] type = types[0] myself = ResourcePool().default_model description = [[myself, '?obj', ['?obj rdf:type ' + type]]] objL = self.get_all_objects_with_desc(description) while len(objL) > 1: nbCandidates = len(objL) logger.debug('Description ' + objectID + ': ' + str(description)) logger.debug('ObjL: ' + str(objL)) agent, descriptor = self.get_descriptor(description, [], True) if not descriptor: break val = self.oro.findForAgent(agent, '?val', [objectID + ' ' + descriptor + ' ?val']) if not val: break description = self.add_descriptor(agent, description, descriptor, val[0]) objL = self.get_all_objects_with_desc(description) if nbCandidates == len(objL): logger.error("While trying to find an unambiguous description" + \ " of " + objectID + ", oro answered a non-discriminant" + \ " property. Bug in oro? Halting here for now.") break if len(objL) == 1: unambiguous = True else: unambiguous = False return unambiguous, description[0][2]
def process_indirect_complement(self, indirect_cmpls, verb, sit_id): for ic in indirect_cmpls: # Case 1: if there is no preposition, the indirect complement is obviously an indirect object. # Therefore, it receives the action # e.g. I gave you a ball also means I gave a ball 'to' you # see http://www.englishlanguageguide.com/english/grammar/indirect-object.asp #Case 2: if there is a preposition, the indirect complement is either an indirect object or an adverbial # if the main verb is specified as a thematic role, we extract the matching object_property to the preposition. # e.g I moved the bottle 'to' the table. The object_property takes the value "hasGoal" # # if the preposition is 'to' , by default we assume the indirect complement is an indirect object # e.g. I gave a ball to Jido. The object_property takes the value "receivedBy" # otherwise, the default processing is to create an object_property by concatenating is and the preposition # e.g. I bought a ball for Jido. The object_property takes the value "isFor" i_stmt_builder = NominalGroupStatementBuilder(ic.gn, self._current_speaker) for ic_noun in ic.gn: #Indirect object ID if ic_noun.id: ic_noun_id = ic_noun.id else: ic_noun_id = i_stmt_builder.set_nominal_group_id(ic_noun) #Proposition role icmpl_role = None icmpl_qualification = None # Case of no preposition if not ic.prep: icmpl_role = " receivedBy " # Case of a preposition. Attempt to get from thematic roles else: icmpl_role = ResourcePool().thematic_roles.get_cmplt_role_for_preposition(verb, ic.prep[0], True) # If no thematic role exist AND the verb is not a state # verb, use the generic role 'involves' and try to qualify it properly. # E.g: 'move the ball next to the table' -> # action type Move, ..., action involves id1, id1 isNextTo table if not icmpl_role: try: if verb not in ResourcePool().state: icmpl_qualification = ResourcePool().preposition_rdf_object_property[ic.prep[0]][0] else: icmpl_role = " %s " % ResourcePool().preposition_rdf_object_property[ic.prep[0]][0] except IndexError: if ic.prep: icmpl_qualification = "is" + ic.prep[0].capitalize() #Creating statements # Case of negation if self._process_on_negative: negative_ic_noun_id = generate_id(with_question_mark=False) self._statements.append(sit_id + icmpl_role + negative_ic_noun_id) self._statements.append(negative_ic_noun_id + ' owl:differentFrom ' + ic_noun_id) # Case of affirmation else: if icmpl_qualification: qualification_id = generate_id(with_question_mark=False) self._statements += \ ["%s involves %s" % (sit_id, qualification_id), "%s %s %s" % (qualification_id, icmpl_qualification, ic_noun_id)] else: self._statements.append(sit_id + icmpl_role + ic_noun_id) i_stmt_builder.process_nominal_group(ic_noun, ic_noun_id, None, False) self._statements.extend(i_stmt_builder._statements) self._unclarified_ids.extend(i_stmt_builder._unclarified_ids) self.lear_more_concept.extend(i_stmt_builder.lear_more_concept)
class Discrimination(object): def __init__(self): self.oro = ResourcePool().ontology_server # -- GET_ALL_OBJECTS_WITH_DESC ------------------------------------------------# # Returns all objects' ids with a given set of features (eg. green, big, etc). # Since we have several descriptions, we obtain a list of objects for each agent # and then we intersect them. # # INPUT: # - description: # [[agent1 '?obj' oro_query]..[[agentN '?obj' oro_query]] # (oro_query= ['?obj hasColor blue',.. ?obj hasShape box']) # # OUTPUT: # - empty list: no objects found fulfilling the description # - list: objects fulfilling the description # - None: no description (or description format incorrect) # -----------------------------------------------------------------------------# def get_all_objects_with_desc(self, description): obj_list = None for agent_desc in description: obj_tmp = [] try: obj_tmp = self.oro.findForAgent( ResourcePool().get_model_mapping(agent_desc[0]), agent_desc[1], agent_desc[2]) except KbError: #The agent does not exist in the ontology pass # if no object found, no need to continue if not obj_tmp: obj_list = [] break else: if obj_list is None: obj_list = obj_tmp else: obj_list = filter(lambda x: x in obj_list, obj_tmp) # intersection return obj_list # -- GET_DISCRIMINANT ---------------------------------------------------------# # Queries the ontology for a list of discriminants. Returns the first one. # TODO: prioritize which discriminant to return. # # INPUT: # - agent # - object list # - ignore_descriptors: list of descriptors not to be used # - include_partial: if true, then partial discriminants are also returned # OUTPUT: # - discriminant: [C, discriminat] if complete, or [P, discriminant] if partial # The new discriminant should be different from the ones already known or ignored # -----------------------------------------------------------------------------# def get_discriminant(self, agent, obj_list, ignore_descriptors, include_partial): discriminants = self.oro.discriminateForAgent( ResourcePool().get_model_mapping(agent), obj_list) logger.debug(colored_print('Possible discriminants: ', 'magenta') + \ str(colored_print(discriminants[1], 'blue')) + \ colored_print(" (complete discriminants: ", 'magenta') + \ str(colored_print(discriminants[0], 'blue')) + ")") complete_disc = discriminants[0] partial_disc = discriminants[1] if complete_disc: res = filter(lambda x: x not in ignore_descriptors, complete_disc) elif partial_disc and include_partial: res = filter(lambda x: x not in ignore_descriptors, partial_disc) else: res = None if res: # include randomization so the same discriminant is not always returned return choice(res) else: # No discriminant after applying the blacklist. return None # -- GET_DESCRIPTOR -----------------------------------------------------------# # Searches for a new descriptor candidate from all agents. # # INPUT: # - description: # [[agent1 '?obj' oro_query]..[[agentN '?obj' oro_query]] # (oro_query= ['?obj hasColor blue',.. ?obj hasShape box']) # - ignore_features: list of features not to use as discriminants # [feat1 ..featN] # - allowPartialDesc: consider also partial discriminants (1) or not (0) (0 default) # # OUTPUT: # - descriptor or None (if no discriminant for any agent found) # -----------------------------------------------------------------------------# def get_descriptor(self, description, ignore_features=None, partial_disc=True): if not ignore_features: ignore_features = [] objL = self.get_all_objects_with_desc(description) descriptor = None agent = None #TODO bug in oro doesn't allow to search discriminants base on other agents models!! # we cannot search in all agents, but only in robot's model # for agent_desc in description: # # list current descriptors to not to use them anymore # #currentDescriptors = map(lambda x: x.split()[1], agent_desc[2]) # descriptor = self.get_discriminant(agent_desc[0], objL, ignore_features, partial_disc) # # if descriptor: # agent = agent_desc[0] # break agent = ResourcePool().default_model # list current descriptors to not to use them anymore #currentDescriptors = map(lambda x: x.split()[1], description[0][2]) descriptor = self.get_discriminant(agent, objL, ignore_features, partial_disc) return agent, descriptor # -- get_values_for_descriptor ------------------------------------------------# # Creates the information to be sent to user based on the discriminant found. # # INPUT: # - agent, discriminant, objectsList # # OUTPUT # - list of values to ask for # -----------------------------------------------------------------------------# def get_values_for_descriptor(self, agent, descriptor, objL): valL = [] # get values for each object for obj in objL: # if the discriminant is type, then look for the directClass of the obj (first found) # how should this work for different agents? There is no directClassForAgent # probably won't be necessary since all the knowledge of the human is part # of the robot's knowledge as well. Then we can obtain this information # directly from the robot itself. if descriptor == 'rdf:type': val = self.oro.getDirectClassesOf(obj).keys() else: val = self.oro.findForAgent( ResourcePool().get_model_mapping(agent), '?val', [obj + ' ' + descriptor + ' ?val']) if val: #TODO: we only consider the first result item! valL.append(self.oro.getLabel(val[0])) # otherwise, the object doesn't have this descriptor, and we don't include it # we make a set to remove repeated elements return list(set(valL)) # -- get_type_description ------------------------------------------------------# # Returns the first type of concept in the description. # # INPUT: # - description # # OUTPUT: # - type # - none # -------------------------------------------------------------------------------# def get_type_description(self, description): def find(value, seq): for item in seq: items = item.split() if value in items: return items[2] return None type = None for desc in description: type = find('rdf:type', desc[2]) if type: break return ResourcePool().ontology_server.getLabel(type) # -- CLARIFY ------------------------------------------------------------------# # Searches for a new descriptor candidate. The descriptor should be as # discriminating as possible. # # INPUT: # - description [['myself', '?obj', ['?obj rdf:type Bottle', '?obj hasColor blue']], # ['agent1', '?obj', ['?obj isVisible True']] # - ignoreFeatureL [feat1..featN] List of features not to use as discriminators. # # OUTPUT: # - objectID: ok # - UnsufficientInputError: # - [FAILURE, "new info required"]: no match, new info required (forget previous description) # - [SUCCESS, "Which value? ..."]: user should indicate value for descriptor (mantain previous description) # - [SUCCESS, "additional info required"]: user should give additional info (mantain previous description) # -----------------------------------------------------------------------------# 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 }) #return "Give me more information about the object" def visible_subset(self, agent, id_list): """ Returns the list of visible objects for an agent from a list of objects. """ visible_objects = self.oro.findForAgent( ResourcePool().get_model_mapping(agent), "?o", [agent + " sees ?o"]) return list(set(id_list) & set(visible_objects)) # -- ADD_DESCRIPTOR -----------------------------------------------------------# # Includes descriptor in description list. # # INPUT: # - agent: to which agent the descriptor belongs to # - description: current description # - descriptor: feature # - value: feature value # # OUTPUT: # - new description # -----------------------------------------------------------------------------# def add_descriptor(self, agent, description, descriptor, value): # return sublist index in seq containing value def find(value, seq): for index, item in enumerate(seq): if value in item: return index, item idx, desc = find(agent, description) desc[2].append('?obj ' + descriptor + ' ' + value) description[idx] = desc return description # -- FIND_UNAMBIGUOUS_DESC ---------------------------------------# # Searches an unambiguous description for a given object. # If it fails, it returns the most complete description found. # # INPUT: # - objectID: object to be described # # OUTPUT: # - a tuple (is_unambigous, description) # - is_unambigous is a boolean # - description is a set of partial statements like # "?obj rdf:type Superman" describing as well as possible # the object. # ----------------------------------------------------------------# def find_unambiguous_desc(self, objectID): description = None # get the first class name types = [ t for t in self.oro.getDirectClassesOf(objectID).keys() if t not in ["ActiveConcept"] ] # Not type asserted/inferred? then assume this object is unique. if not types: return True, [] type = types[0] myself = ResourcePool().default_model description = [[myself, '?obj', ['?obj rdf:type ' + type]]] objL = self.get_all_objects_with_desc(description) while len(objL) > 1: nbCandidates = len(objL) logger.debug('Description ' + objectID + ': ' + str(description)) logger.debug('ObjL: ' + str(objL)) agent, descriptor = self.get_descriptor(description, [], True) if not descriptor: break val = self.oro.findForAgent( ResourcePool().get_model_mapping(agent), '?val', [objectID + ' ' + descriptor + ' ?val']) if not val: break description = self.add_descriptor(agent, description, descriptor, val[0]) objL = self.get_all_objects_with_desc(description) if nbCandidates == len(objL): logger.error("While trying to find an unambiguous description" + \ " of " + objectID + ", oro answered a non-discriminant" + \ " property. Bug in oro? Halting here for now.") break if len(objL) == 1: unambiguous = True else: unambiguous = False return unambiguous, description[0][2]
class QuestionHandler(object): def __init__(self, current_speaker=None): self._sentence = None self._statements = [] self._current_speaker = current_speaker # This field takes the value True or False when processing a # Yes-No-question and takes a list of returned values from # the ontology when processing a w_question self._answer = False # This field is set to 'None' when the answer of the question # (wh-question) that is being processed aims to give information # about the subject. #It also holds the flags 'QUERY_ON_DIRECT_OBJ' and 'QUERY_ON_INDIRECT_OBJ'. self._query_on_field = None self._process_on_location = False # This field is set to True, when the verb 'to know' occurs in a # sentence. self.process_on_knowing_concept = False # This defines the default model used to resolve queries. self._default_agent = ResourcePool().default_model def clear_statements(self): self._statements = [] def set_current_speaker(self, current_speaker): """ Updates the speaker ID. """ self._current_speaker = current_speaker def get_query_on_field(self): return self._query_on_field 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 _build_situation_statements(self): sit_id = generate_id(with_question_mark=False) stmts = ["%s experiences %s" % (self._current_speaker, sit_id)] stmts += ["%s rdf:type InterrogativeState" % sit_id] for sn in self._sentence.sn: stmts += ["%s hasObject %s" % (sit_id, sn.id)] stmts += ["%s hasAim %s_question_aim" % (sit_id, self._sentence.aim)] stmts += ["%s hasAnswer %s" % (sit_id, "true" if self._answer else "false")] return stmts, sit_id def _set_situation_id(self, statements): """This attempts to clarify the ID of an action verbs E.g: statement = [?event rdf:type Go, ?event performedBy myself, ?event actsOnObject xxx] We attemtps to find an existing ontology ID matching '?event' """ stmts = [] find_id = False for s in statements: if '?' in s: find_id = True break if find_id: try: sit_id = ResourcePool().ontology_server.find(['?event'], statements) except AttributeError: #the ontology server is not started of doesn't know the method pass if sit_id: logger.debug( "\t/Found a staticSituation matching the yes_no_question query to be checked: " + str(sit_id)) for s in statements: #TODO:the ontology might find severals sit ID matching the query. Should we take this consideration? #The longer the query, the better the result of sit_id stmts.append(s.replace('?event', sit_id[0])) else: stmts = statements # Find process on knowing concept for s in statements: if "knows" in s: self.process_on_knowing_concept = True break return stmts def _extend_statement_from_sentence_aim(self, current_statements, sn=None): """This extends the statements states so that the query answer matches the w_question aim """ #Concept descriptor # E.g: Human, Object, Color ,Size... concept_descriptor = self.get_concept_descriptor(sn) #Case: the statement is complete from statement builder e.g: what is in the box? =>[?concept isIn ?id_box, ?id_box rdf:type Box] for s in current_statements: if '?concept' in s.split(): return current_statements + concept_descriptor #case: the statement is partially build from statement builder stmts = [] if sn: for sv in self._sentence.sv: for verb in sv.vrb_main: role = self.get_role_from_sentence_aim(self._query_on_field, verb) #Case of looking for the object in a location if role == 'objectFoundInLocation': self._process_on_location = True # Case of state verbs if verb.lower() in ResourcePool().state: stmts.append(sn.id + ' ' + role + ' ?concept') # Case of action verb with a passive behaviour elif verb.lower() in ResourcePool().action_verb_with_passive_behaviour.keys(): stmts.append( sn.id + ' ' + ResourcePool().action_verb_with_passive_behaviour[verb.lower()] + ' ?concept') # Case of know elif verb.lower() == 'know': self.process_on_knowing_concept = True stmts.append(sn.id + ' knows ?concept') # case of action verbs else: stmts.append('?event ' + role + ' ?concept') return current_statements + stmts + concept_descriptor def _set_query_on_field(self, sentence): """ This defines which part of a sentence is supposed to be completed once the answer of a w_question has been retrieved E:g - [W_question] : where is the cube - Answer: table - query_on_field = 'QUERY_ON_INDIRECT_OBJ' - Sentence built from answer, query_on_field, and w_question: the cube is on the table """ if sentence.aim == 'place': return 'QUERY_ON_INDIRECT_OBJ' if not sentence.sn: return None if sentence.sv: if not sentence.sv[0].d_obj: query_on_field = 'QUERY_ON_DIRECT_OBJ' else: query_on_field = 'QUERY_ON_INDIRECT_OBJ' return query_on_field def get_role_from_sentence_aim(self, query_on_field, verb): """ Given specific w_question aim and verb, this function attempts to define the matching object property to built an RDF tuple <S P O>. Cf. QuestionAimDict() for more detail. """ dic_aim = QuestionAimDict().dic_aim try: if verb.lower() in dic_aim[self._sentence.aim][query_on_field]: role = dic_aim[self._sentence.aim][query_on_field][verb.lower()] else: role = dic_aim[self._sentence.aim][query_on_field][None] except KeyError: if verb.lower() in dic_aim[self._sentence.aim][None]: role = dic_aim[self._sentence.aim][None][verb.lower()] else: role = dic_aim[self._sentence.aim][None][None] return role def get_concept_descriptor(self, ng): """ Get the type or feature of the concept to query if it is not mapped in the QuestionAimDict E.g: What color is the bottle? Here, the aim 'color' is about a feature and it is not in the QuestionAimDict. We return it in concept_descriptor = 'id hasColor ?concept' E.g: What Human do you see? Here, the aim 'human' is not a feature, and is not in the QuestionAimDict We return it in concept_descriptor = '?concept rdf:type Human' """ concept_descriptor = [] agent = self._default_agent aim = self._sentence.aim #Concept's Features if self._sentence.aim in ResourcePool().adjectives_ontology_classes: if ng: concept_descriptor = [ng.id + " has" + aim.capitalize() + " ?concept"] self._sentence.aim = "thing" #Concept's Type elif not self._sentence.aim in QuestionAimDict().dic_aim.keys(): logger.debug("\tFound the aim: " + aim + ".Extending statements with [?concept rdf:type aim]") try: onto = ResourcePool().ontology_server.lookupForAgent(agent, aim) except AttributeError: onto = None concept_descriptor = ["?concept rdf:type " + get_class_name(aim, onto)] self._sentence.aim = "thing" elif self._sentence.aim == "people": concept_descriptor = ["?concept rdf:type Agent"] return concept_descriptor """ what aim => 'thing' what kind => aim = 'thing', sn = [the kind of] what type => aim = 'thing' , sn = [the type of] what time => aim = 'time' which aim => 'choice' when aim => 'date' where aim => 'Place' where (from) => 'origin' why aim => 'reason' who aim => 'person' whose aim => 'owner' whom aim => 'person' how aim => 'place' how long => aim = 'duration' how far => aim = 'distance' how often => aim = 'Frequency' How much => aim = 'Quantity' How many => aim = 'Quantity' """ def _remove_statements_with_no_unbound_tokens(self, statements): """ This remove statement part with no unbound token, for querying the ontology.""" stmts = [] for s in statements: if '?' in s: stmts.append(s) return stmts
def process_and_beginning_sentence(sentence): """ process the beginning of the sentence For example if there is adverb, we put it at the end (i_cmpl also) Input=sentence Output=sentence """ # If sentence is empty if not sentence: return [] # Using flag is for the ending of this function if other_functions.find_cap_lettre(sentence[0]) == 1: flg = 1 sentence[0] = sentence[0][0].lower() + sentence[0][1:] else: flg = 0 #We have to take off this words if sentence[0] == ';' or sentence[0] == 'and' or sentence[ 0] == 'ah' or sentence[0] == ',' or sentence[0] == 'very': sentence = sentence[1:] #If it starts with proposal if sentence[0] in ResourcePool().proposals: gr = determination_nominal_group(sentence, 1, 'of') #We put the nominal group at the end of the sentence if gr: sentence = sentence[len(gr) + 1:] + [','] + [sentence[0]] + gr sentence = process_and_beginning_sentence(sentence) else: #In this case we don't find a nominal group but there is a i_cmpl for z in sentence: if z == ';' or z == '.' or z == ',': #The final point of i_cmpl is the punctuation phrase = sentence[:sentence.index(z)] if sentence[len(sentence) - 1] == '.' or sentence[ len(sentence) - 1] == '?' or sentence[len(sentence) - 1] == '!': sentence = sentence[sentence.index(z) + 1:len(sentence) - 1] + [','] + phrase + [ sentence[len(sentence) - 1] ] else: sentence = sentence[sentence.index(z) + 1:] + [','] + phrase #If it starts with adverb if sentence[0] in ResourcePool().adverbs: if sentence[len(sentence) - 1] == '.' or sentence[len(sentence) - 1] == '?' or sentence[len(sentence) - 1] == '!': sentence = sentence[1:len(sentence) - 1] + [sentence[0]] + [ sentence[len(sentence) - 1] ] sentence = process_and_beginning_sentence(sentence) else: sentence = sentence[1:] + [','] + [sentence[0]] sentence = process_and_beginning_sentence(sentence) #If flag is 1 => we have a capitol letter at the beginning if flg == 1: sentence[0] = sentence[0][0].upper() + sentence[0][1:] return sentence
class TestQuestionHandlerScenarioMovingToLondon(unittest.TestCase): """Tests the processing of question by the Dialog module. This must be tested with oro-server using the testsuite.oro.owl ontology. """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add(['ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'table1 rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn table1', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn table1', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn table1', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: pass try: self.oro.addForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'table1 rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn table1', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn table1', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn table1', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: pass def test1(self): self.oro.add(['TAPE1 isIn CARDBOARD_BOX']) self.oro.removeForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE focusesOn TAPE2']) self.oro.addForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE focusesOn CARDBOARD_BOX']) stmt = "Jido, what is in the box?" answer = "this box" #### self.assertEquals(self.dialog.test('ACHILLE', stmt, answer)[1][1], "The Lords of the robots.") def test2(self): #Fill in the history stmt = " the TAPE1 is in the CARDBOARD_BOX" self.dialog.test('ACHILLE', stmt) stmt = "Ok. And where is the other tape?" #### self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1], "Alright. The other tape is on the table.") def test3(self): stmt = "Ok thank you." self.assertIn(self.dialog.test('ACHILLE', stmt)[1][1], AGREEMENTS) def test3_2(self): stmt = "thank you." self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1], "You're welcome.") def test4(self): self.oro.update(['TAPE2 isReachable false']) stmt = "can you take Jido-E?" #### res = self.dialog.test('ACHILLE', stmt) expected_result = ['ACHILLE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2'] self.assertTrue(check_results(res[0], expected_result)) self.assertIn(res[1][1], AGREEMENTS) def test_5(self): self.oro.update(['TAPE2 isReachable false']) stmt = "can you take Jido-E?" #### res = self.dialog.test('ACHILLE', stmt) expected_result = ['ACHILLE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2'] self.assertTrue(check_results(res[0], expected_result)) self.assertIn(res[1][1], AGREEMENTS) def test_6(self): ### self.oro.removeForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE focusesOn CARDBOARD_BOX']) self.oro.addForAgent(ResourcePool().get_model_mapping('ACHILLE'), ['ACHILLE focusesOn TAPE2']) stmt = "Jido, can you reach this tape?" #### ## expected to check['myself reaches TAPE2'] self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1], "I don't know, if I can reach it.") def test_7(self): self.oro.update(['TAPE2 isReachable true']) #Feel history self.dialog.dialog_history = [] stmt = "can you reach Jido-E?" res = self.dialog.test('ACHILLE', stmt) ### stmt = "can you take it?" #### answer = "yes" ### res = self.dialog.test('ACHILLE', stmt, answer) expected_result = ['ACHILLE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2'] self.assertTrue(check_results(res[0], expected_result)) def test_8(self): ### stmt = "can you take the tape?" #### answer = "forget it" ### res = self.dialog.test('ACHILLE', stmt, answer) expected_result = [] self.assertTrue(check_results(res[0], expected_result))
def setUp(self): ResourcePool().ontology_server.reset() ResourcePool().ontology_server.add(['SPEAKER rdf:type Human', 'SPEAKER rdfs:label "Patrick"', 'blue_cube rdf:type Cube', 'blue_cube hasColor blue', 'blue_cube isOn table1', 'another_cube rdf:type Cube', 'another_cube isAt shelf1', 'another_cube belongsTo SPEAKER', 'another_cube hasSize small', 'shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'myself sees shelf1', 'take_blue_cube performedBy myself', 'take_blue_cube rdf:type Get', 'take_blue_cube actsOnObject blue_cube', 'take_my_cube canBePerformedBy SPEAKER', 'take_my_cube involves another_cube', 'take_my_cube rdf:type Take', 'SPEAKER focusesOn another_cube', 'id_danny rdfs:label "Danny"', 'give_another_cube rdf:type Give', 'give_another_cube performedBy id_danny', 'give_another_cube receivedBy SPEAKER', 'give_another_cube actsOnObject another_cube', 'id_danny sees SPEAKER', ]) ResourcePool().ontology_server.addForAgent(ResourcePool().get_model_mapping('SPEAKER'), [ 'SPEAKER rdf:type Human', 'SPEAKER rdfs:label "Patrick"', 'blue_cube rdf:type Cube', 'blue_cube hasColor blue', 'blue_cube isOn table1', 'another_cube rdf:type Cube', 'another_cube isAt shelf1', 'another_cube belongsTo SPEAKER', 'another_cube hasSize small', 'shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'myself sees shelf1', 'take_blue_cube performedBy myself', 'take_blue_cube rdf:type Get', 'take_blue_cube actsOnObject blue_cube', 'take_my_cube canBePerformedBy SPEAKER', 'take_my_cube involves another_cube', 'take_my_cube rdf:type Take', 'SPEAKER focusesOn another_cube', 'id_danny rdfs:label "Danny"', 'give_another_cube rdf:type Give', 'give_another_cube performedBy id_danny', 'give_another_cube receivedBy SPEAKER', 'give_another_cube actsOnObject another_cube', 'id_danny sees SPEAKER', ]) self.qhandler = QuestionHandler("SPEAKER") self.resolver = Resolver()
class TestDiscriminateCompleteDialog(unittest.TestCase): """Tests the differents features of the Dialog module. This must be tested with oro-server using the testsuite.oro.owl ontology. """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.reload() self.oro.add(['shelf1 rdf:type Shelf', 'table1 rdf:type Table', 'table2 rdf:type Table', 'table2 hasColor blue', 'Banana rdfs:subClassOf Plant', 'y_banana rdf:type Banana', 'y_banana hasColor yellow', 'y_banana isOn shelf1', 'green_banana rdf:type Banana', 'green_banana hasColor green', 'green_banana isOn table2', 'ACCESSKIT rdf:type Gamebox', 'ACCESSKIT hasColor white', 'ACCESSKIT hasSize big', 'ACCESSKIT isOn table1', 'ORANGEBOX rdf:type Gamebox', 'ORANGEBOX hasColor orange', 'ORANGEBOX hasSize big', 'ORANGEBOX isOn ACCESSKIT', 'MYBOX rdf:type Gamebox', 'MYBOX hasColor orange', 'MYBOX hasSize small', 'MYBOX isOn ACCESSKIT', 'SPACENAVBOX rdf:type Gamebox', 'SPACENAVBOX hasColor white', 'SPACENAVBOX hasSize big', 'SPACENAVBOX isOn ACCESSKIT', 'y_bottle rdf:type Bottle', 'y_bottle isLocated RIGHT', 'r_bottle rdf:type Bottle', 'r_bottle isLocated FRONT', 'b_bottle rdf:type Bottle', 'b_bottle isLocated BACK' ]) except AttributeError: #the ontology server is not started of doesn't know the method pass def test_discriminate1(self): """ Color discriminant should be found""" logger.info("\n##################### test_discriminate1 ########################\n") #### stmt = "the banana is good" answer = "the green one" #### res = self.dialog.test('myself', stmt, answer) logger.info(res) expected_result = ['green_banana hasFeature good'] self.assertTrue(check_results(res[0], expected_result)) """ Color discriminant should be found""" logger.info("\n##################### test_discriminate2 ########################\n") #### stmt = "the banana is good" answer = "the yellow one" #### res = self.dialog.test('myself', stmt, answer) logger.info(res) expected_result = ['y_banana hasFeature good'] self.assertTrue(check_results(res[0], expected_result)) def test_discriminate3(self): """ Color discriminant should be found""" logger.info("\n##################### test_discriminate3 ########################\n") #### stmt = "give me the banana" answer = "the green one" #### expected_result = ['myself desires *', '* rdf:type Give', '* performedBy myself', '* actsOnObject green_banana', '* receivedBy myself'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate4(self): """No ambiguity.""" logger.info("\n##################### test_discriminate4 ########################\n") #### stmt = "get the gamebox which is on the table" answer = None #### expected_result = ['myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ACCESSKIT'] ### res = self.dialog.test('myself', stmt) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate5(self): """ Size discriminant should be found """ logger.info("\n##################### test_discriminate5 ########################\n") #### stmt = "get the orange gamebox" answer = "the big one" #### expected_result = ['myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ORANGEBOX'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate6(self): """No complete discriminant found. More info required""" logger.info("\n##################### test_discriminate6 ########################\n") #### stmt = "get the big gamebox" answer = "the orange one" #### expected_result = ['myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ORANGEBOX'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate7(self): """ Location discriminant should be found """ logger.info("\n##################### test_discriminate7 ########################\n") #### stmt = "get the white gamebox" answer = "the one which is on the table1" #### expected_result = ['myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject ACCESSKIT'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate8(self): """ Location wrt robot discriminant should be found """ logger.info("\n##################### test_discriminate8 ########################\n") #### stmt = "get the bottle" answer = "the one which is in front of you" #### expected_result = ['myself desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject r_bottle'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def test_discriminate9(self): logger.info("\n##################### Class grounding ########################\n") #### stmt = "a fruit is a plant" answer = "a kind of thing" #### expected_result = ['Plant rdfs:subClassOf Thing', 'Fruit rdfs:subClassOf Plant'] ### res = self.dialog.test('myself', stmt, answer) logger.info(res) self.assertTrue(check_results(res[0], expected_result)) def tearDown(self): self.dialog.stop() self.dialog.join()
def recover_obj_iobj(phrase, vg): """ finds the direct, indirect object and the adverbial We, also, put these information in the class Input=sentence and verbal class Output=sentence and verbal class """ #init conjunction = 'AND' object = analyse_nominal_group.find_sn(phrase) if phrase and \ not object and \ phrase[0] in ResourcePool().adverbs_at_end: vg.advrb = [phrase[0]] while object: #If it is not a direct object => there is a proposal proposal = check_proposal(phrase, object) if proposal: gr_nom_list = [] #This 'while' is for duplicate with 'and' while object: pos_object = phrase.index(object[0]) #We refine the nominal group if there is an error like ending with question mark object = analyse_nominal_group.refine_nom_gr(object) #Recovering nominal group gr_nom_list = gr_nom_list + [ analyse_nominal_structure.fill_nom_gr( phrase, object, pos_object, conjunction) ] #We take off the nominal group phrase = analyse_nominal_group.take_off_nom_gr( phrase, object, pos_object) #We will take off the proposal phrase = phrase[:phrase.index(proposal[0])] + phrase[ phrase.index(proposal[0]) + 1:] conjunction = 'AND' #If there is a relative begin_pos_rel = analyse_nominal_group.find_relative( object, phrase, pos_object, ResourcePool().relatives) if begin_pos_rel != -1: end_pos_rel = other_functions.recover_end_pos_sub( phrase, ResourcePool().relatives) #We remove the relative part of the phrase phrase = phrase[:begin_pos_rel] + phrase[end_pos_rel:] #If there is 'and', we need to duplicate the information with the proposal if there is if len(phrase) != 0 and (phrase[0] == 'and' or phrase[0] == 'or' or phrase[0] == ':but'): phrase = [phrase[0]] + analyse_nominal_group.find_plural( phrase[1:]) #We have not duplicate the proposal, it depends on the presence of the nominal group after if analyse_nominal_group.find_sn_pos(phrase, 1): phrase = [phrase[0]] + proposal + phrase[1:] else: phrase = [phrase[0]] + phrase[1:] object = analyse_nominal_group.find_sn_pos(phrase[1:], 0) #We process the 'or' like the 'and' and remove it if phrase[0] == 'or': conjunction = 'OR' elif phrase[0] == ':but': conjunction = 'BUT' else: conjunction = 'AND' phrase = phrase[1:] else: object = [] vg.i_cmpl = vg.i_cmpl + [IndirectComplement(proposal, gr_nom_list)] else: #It is a direct complement gr_nom_list = [] #It reproduces the same code as above while object: pos_object = phrase.index(object[0]) #We refine the nominal group if there is an error like ending with question mark object = analyse_nominal_group.refine_nom_gr(object) #Recovering nominal group gr_nom_list = gr_nom_list + [ analyse_nominal_structure.fill_nom_gr( phrase, object, pos_object, conjunction) ] #We take off the nominal group phrase = analyse_nominal_group.take_off_nom_gr( phrase, object, pos_object) conjunction = 'AND' #If there is a relative begin_pos_rel = analyse_nominal_group.find_relative( object, phrase, pos_object, ResourcePool().relatives) if begin_pos_rel != -1: end_pos_rel = other_functions.recover_end_pos_sub( phrase, ResourcePool().relatives) #We remove the relative part of the phrase phrase = phrase[:begin_pos_rel] + phrase[end_pos_rel:] if len(phrase) != 0 and (phrase[0] == 'and' or phrase[0] == 'or' or phrase[0] == ':but'): phrase = [phrase[0]] + analyse_nominal_group.find_plural( phrase[1:]) object = analyse_nominal_group.find_sn_pos(phrase[1:], 0) #We process the 'or' like the 'and' and remove it if phrase[0] == 'or': conjunction = 'OR' elif phrase[0] == ':but': conjunction = 'BUT' else: conjunction = 'AND' phrase = phrase[1:] else: object = [] #In a sentence there is just one direct complement if there is no second verb if not vg.d_obj: vg.d_obj = gr_nom_list else: #Else the first nominal group found is indirect and this one is direct complement vg.i_cmpl = vg.i_cmpl + [IndirectComplement([], vg.d_obj)] vg.d_obj = gr_nom_list #If the last nominal group is followed by another one in plural form phrase = analyse_nominal_group.find_plural(phrase) object = analyse_nominal_group.find_sn(phrase) return phrase
class TestMovingToLondonScenario(unittest.TestCase): """ Scenario -------- ACHILLE and JULIE are moving from Toulouse to London, and they must pack everything before leaving. ACHILLE is sorting its video tapes, and he throws away the oldest ones. Jido is watching him. Setup: One trashbin, one cardboard box, 2 tapes on the table [TAPE1 = Lord of the Robots (lotr) and TAPE2 = JIDO-E]. Complete scenario here: http://homepages.laas.fr/slemaign/wiki/doku.php?id=scenario_demo_roman """ def setUp(self): self.dialog = Dialog() self.dialog.start() self.oro = ResourcePool().ontology_server try: self.oro.add([ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) """ self.oro.addForAgent('ACHILLE', ['BLUE_TRASHBIN rdf:type Trashbin', 'PINK_TRASHBIN rdf:type Trashbin', 'BLACK_TAPE rdf:type VideoTape', 'BLACK_TAPE isIn PINK_TRASHBIN', 'GREY_TAPE rdf:type VideoTape', 'GREY_TAPE isOn HRP2TABLE']) """ except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('ACHILLE',[ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise try: self.oro.addForAgent('JULIE',[ 'ACHILLE rdf:type Human', 'ACHILLE rdfs:label Achille', 'JULIE rdf:type Human', 'JULIE rdfs:label Julie', 'TABLE rdf:type Table', 'Trashbin rdfs:subClassOf Box', 'CardBoardBox rdfs:subClassOf Box', 'CardBoardBox rdfs:label "cardboard box"', 'TRASHBIN rdf:type Trashbin', 'CARDBOARD_BOX rdf:type CardBoardBox', 'CARDBOARD_BOX isOn TABLE', 'TAPE1 rdf:type VideoTape', 'TAPE1 rdfs:label "The Lords of the robots"', 'TAPE1 isOn TABLE', 'TAPE2 rdf:type VideoTape', 'TAPE2 rdfs:label "Jido-E"', 'TAPE2 isOn TABLE', 'VideoTape owl:equivalentClass Tape', 'TAPE1 owl:differentFrom TAPE2', ]) except AttributeError: #the ontology server is not started of doesn't know the method print("Couldn't connect to the ontology server. Aborting the test.") raise def runTest(self): """ MOVING TO LONDON SCENARIO ACHILLE puts TAPE1 in CARDBOARDBOX""" print() self.oro.add(['TAPE1 isIn CARDBOARD_BOX']) self.oro.addForAgent('ACHILLE',['ACHILLE pointsAt CARDBOARD_BOX']) stmt = "Jido, what is in the box?" answer = "This box" #### res = self.dialog.test('ACHILLE', stmt, answer) self.assertEquals(res[1][1],"The Lords of the robots.") self.oro.removeForAgent('ACHILLE',['ACHILLE pointsAt CARDBOARD_BOX']) stmt = "Ok. And where is the other tape?" #### self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1],"The other tape is on the table.") stmt = "Ok. Thanks." self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1],"You're welcome.") """Julie arrives, and gives two big boxes to ACHILLE. He can not take anything!""" self.oro.update(['TAPE2 isReachable false']) stmt = "Jido, can you take Jido-E?" #### res = self.dialog.test('ACHILLE', stmt) expected_result = ['ACHILLE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2'] self.assertTrue(check_results(res[0], expected_result)) """Julie pushes a bit the TAPE2, which is now close enough, but still unreachable because of an obstacle. """ self.oro.addForAgent('ACHILLE',['ACHILLE pointsAt TAPE2']) stmt = "And now, can you reach this tape?" #### ### Check ['myself reaches TAPE2'] self.assertEquals(self.dialog.test('ACHILLE', stmt)[1][1],"I don't know, if I can reach this tape now.") self.oro.removeForAgent('ACHILLE',['ACHILLE pointsAt TAPE2']) """Julie pushes again the tape. It is now reachable. """ self.oro.update(['TAPE2 isReachable true']) stmt = "Jido, can you take it?" #### ### Do you mean Jido-E answer = "I mean Jido-E" ### res = self.dialog.test('JULIE', stmt, answer) expected_result = ['JULIE desires *', '* rdf:type Get', '* performedBy myself', '* actsOnObject TAPE2'] self.assertTrue(check_results(res[0], expected_result)) """Achille puts JIDO-E in the trashbin. Jido still observes. Achille leaves. Julie finds JIDO-E in the trashbin, and takes it away. ACHILLE comes back to the table. """ print() self.oro.remove(['TAPE2 isOn TABLE']) self.oro.add(['TAPE2 isAt JULIE']) self.oro.addForAgent('ACHILLE', ['TAPE2 isIn TRASHBIN']) stmt = "Can you give me the tape in the trashbin?" #Expected intermediate question: "You mean, the JIDO-E tape?" #NOT FOR ROMAN demo! #answer = "Yes" #### res = self.dialog.test('ACHILLE', stmt) expected_result = ['ACHILLE desires *', '* rdf:type Give', '* performedBy myself', '* actsOnObject TAPE2', '* receivedBy ACHILLE'] self.assertTrue(check_results(res[0], expected_result)) def tearDown(self): self.dialog.stop() self.dialog.join()
def __init__(self): """ This class consits in building a map of object property regarding the Question's aim attribute and the query_on_field parameter. Below is a description of what should be generated depending of the question that is processed. 'What and which-question': Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' extend statements with [?event OBJ ?concept] where OBJ depends on the verb. e.g: if verb == "get": OBJ = "actsOnObject" if verb == "drive": OBJ = "involves" ... Case # query_on_field = None Nothing to extend Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' Nothing to extend 'Who-question': Case # query_on_field = None extend statements with [* performedBy ?concept] Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' and state verbs extend statements with [* rdfs:label ?concept] E.g: Who is the car's driver? Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' and action verbs same as "what" and "which" question for 'QUERY_ON_DIRECT_OBJ' Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' extend statements with [* receivedBy ?concept] 'Where-question': Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' extend statements with [* objectFoundInLocation ?concept] """ self.dic_aim = {} #Dictionaries related to thematice roles verbs verbs_dic = ResourcePool().thematic_roles.verbs self.dic_on_direct_obj = dict( [(verb, role.id) for verb in verbs_dic.keys() for role in verbs_dic[verb].roles[0:1]]) self.dic_on_direct_obj[None] = 'involves' self.dic_on_direct_obj['be'] = 'owl:sameAs' self.dic_on_indirect_obj = dict( [(verb, role.id) for verb in verbs_dic.keys() for role in verbs_dic[verb].roles[1:2]]) self.dic_on_indirect_obj['be'] = None self.dic_on_indirect_obj[None] = 'owl:sameAs' #Dictionary for sentence.aim = 'place' self.dic_place = {None: self.dic_on_indirect_obj.copy()} self.dic_place[None]['be'] = 'objectFoundInLocation' #Dictionary for sentence.aim = 'thing' self.dic_thing = {None: self.dic_on_direct_obj.copy()} #Dictionary for sentence.aim = 'manner' self.dic_manner = {None: {'be': 'owl:topObjectProperty'}} #Dictionary for sentence.aim = 'people' self.dic_people = {'QUERY_ON_DIRECT_OBJ': self.dic_on_direct_obj.copy(), 'QUERY_ON_INDIRECT_OBJ': self.dic_on_indirect_obj.copy()} #Dictionary for all question aims #What-question self.dic_aim['thing'] = self.dic_thing #Who-question self.dic_aim['people'] = self.dic_people #Where-question self.dic_aim['place'] = self.dic_place #How-Question self.dic_aim['manner'] = self.dic_manner #which-question self.dic_aim['choice'] = self.dic_thing
def process_compare(sentence, vg): """ process the compare Input=sentence and verbal structure Output=sentence verbal structure """ #init i = 0 conjunction = 'AND' gr_nom_list = [] while i < len(sentence): #We will find 'than' if sentence[i] == 'than': compare = {'nom_gr': [], 'object': ''} object = analyse_nominal_group.find_sn_pos(sentence, i + 1) #It reproduces the same code as above while object: #We refine the nominal group if there is an error like ending with question mark object = analyse_nominal_group.refine_nom_gr(object) #Recovering nominal group gr_nom_list = gr_nom_list + [ analyse_nominal_structure.fill_nom_gr( sentence, object, i + 1, conjunction) ] #We take off the nominal group sentence = analyse_nominal_group.take_off_nom_gr( sentence, object, i + 1) conjunction = 'AND' #If there is a relative begin_pos_rel = analyse_nominal_group.find_relative( object, sentence, i + 1, ResourcePool().relatives) if begin_pos_rel != -1: end_pos_rel = other_functions.recover_end_pos_sub( sentence, ResourcePool().relatives) #We remove the relative part of the sentence sentence = sentence[:begin_pos_rel] + sentence[end_pos_rel:] if len(sentence) != i + 1 and (sentence[i + 1] == 'and' or sentence[i + 1] == 'or' or sentence[i + 1] == ':but'): sentence = [ sentence[i + 1] ] + analyse_nominal_group.find_plural(sentence[1:]) object = analyse_nominal_group.find_sn_pos( sentence[i + 2:], i + 1) #We process the 'or' like the 'and' and remove it if sentence[i + 1] == 'or': conjunction = 'OR' elif sentence[i + 1] == ':but': conjunction = 'BUT' else: conjunction = 'AND' sentence = sentence[i + 1:] else: object = [] #Add the nominal group compare['nom_gr'] = gr_nom_list #Comparator : ends with 'er' if sentence[i - 1].endswith('er'): compare['object'] = sentence[i - 1] sentence = sentence[:i - 1] + sentence[i + 1:] #Comparator : with 2 words elif sentence[i - 2] == 'more' or sentence[i - 2] == 'less': compare['object'] = sentence[i - 2] + '+' + sentence[i - 1] sentence = sentence[:i - 1] + sentence[i + 1:] #Comparator : exceptions elif sentence[i - 1] == 'more' or sentence[i - 1] == 'less': compare['object'] = sentence[i - 1] sentence = sentence[:i - 1] + sentence[i + 1:] vg.comparator = vg.comparator + [compare] i += 1 return sentence
def dispatching(sentence): """ distributes the sentence according to: Their functionality and their type Input=sentence, beginning sentence list Output=class Sentence """ if len(sentence) > 0: #For ending dialogue if sentence[0].endswith('bye'): return [Sentence(END, '', [], [])] #When others for x in ResourcePool().sentence_starts: #If we find a knowing case if sentence[0] == x[0]: #For if x[1] == '1': return [Sentence(START, '', [], [])] #It's a w_question or subsentence if x[1] == '2': #If there is which or no nominal group it is a question if sentence[ 0] != 'which' and analyse_nominal_group.find_sn_pos( sentence, 1) != []: #Here we have the condition of the subsentences return [stc_start_subsentence(sentence)] #For 'when' if x[2] == '1': #If we remove the first word => it becomes like y_n_question return [y_n_ques(W_QUESTION, 'date', sentence[1:])] #For 'where' elif x[2] == '2': return [w_quest_where(W_QUESTION, 'place', sentence)] #For 'what' elif x[2] == '3': #Here we have to use a specific processing for 'type' and 'kind' if sentence[1] == 'type' or sentence[1] == 'kind': #We start by processing the end of the sentence like a y_n_question return [w_quest_class(sentence)] #For other type of 'what' question else: return [w_quest_what(W_QUESTION, sentence)] #For 'how' elif x[2] == '4': if sentence[1] == 'many' or sentence[1] == 'much': return [ w_quest_quant(W_QUESTION, 'quantity', sentence) ] elif sentence[1] == 'about': #We replace 'about' by 'is' to have a y_n_question sentence[1] = 'is' return [ y_n_ques(W_QUESTION, 'invitation', sentence[1:]) ] #For other type of 'how' question else: return [w_quest_how(W_QUESTION, sentence)] #For 'why' elif x[2] == '5': return [y_n_ques(W_QUESTION, 'reason', sentence[1:])] #For 'whose' elif x[2] == '6': return [w_quest_whose(W_QUESTION, 'owner', sentence)] #For 'who' elif x[2] == '7': return [y_n_ques(W_QUESTION, 'people', sentence[1:])] #For 'which' elif x[2] == '8': return [ w_quest_which(W_QUESTION, 'choice', sentence[1:]) ] #For 'to whom' elif x[2] == '9': return [ w_quest_whom(W_QUESTION, 'people', sentence[1:]) ] #It's a y_n_question elif x[1] == '3': return [y_n_ques(YES_NO_QUESTION, '', sentence)] #It's a conditional sentence elif x[1] == '4': return [stc_start_subsentence(sentence)] #Agree elif x[1] == '5': return separ_sentence(sentence, AGREEMENT) #Disagree elif x[1] == '6': return separ_sentence(sentence, DISAGREEMENT) #Gratulation elif x[1] == '7': return separ_sentence(sentence, GRATULATION) #Interjunction elif x[1] == '8': return [exclama_sentence(sentence)] #For exclamatively if sentence[len(sentence) - 1] == '!': return [exclama_sentence(sentence)] #It's a statement or an imperative sentence return [other_sentence('', '', sentence)] #Default case return []
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 process_subsentence(phrase, vg): """ process the subsentence Input=sentence and verbal class Output=sentence and verbal class """ #init begin_pos = -1 #If phrase is empty if len(phrase) < 0: return phrase #We look down the list to see if there is a subsentence for w in ResourcePool().subsentences: if w in phrase: begin_pos = phrase.index(w) #We include the relative's proposal if there are relatives in the subsentence end_pos = other_functions.recover_end_pos_sub( phrase[begin_pos:], ResourcePool().subsentences + ResourcePool().relatives) #If it is 'where', it can be relative if before we have nominal group if w == 'where' or w == 'which': position = phrase.index(w) - 1 gr = analyse_nominal_group.find_sn_pos(phrase, position) #We have to find the nominal group just before while position > 0 and gr == []: position -= 1 gr = analyse_nominal_group.find_sn_pos(phrase, position) #For exceptions, if the nominal group end with the proposal if gr != [] and gr[len(gr) - 1] == w: gr = gr[:len(gr) - 1] #Else we return the sentence and we assume it as relative if (w != 'where' and w != 'which') or ( len(gr) + position != phrase.index(w) or (len(gr) == 1 and is_cmpl_pr(gr[0]) == 1)): #We have to remove the proposal subsentence = phrase[begin_pos + 1:begin_pos + end_pos] if len(subsentence) > 1: subsentence = other_functions.recover_scd_verb_sub( subsentence) if w != 'which': #We perform processing vg.vrb_sub_sentence = vg.vrb_sub_sentence + analyse_sentence.dispatching( subsentence) vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].data_type = SUBSENTENCE + '+' + \ vg.vrb_sub_sentence[len( vg.vrb_sub_sentence) - 1].data_type if w[0] == ':': vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].aim = w[1:] else: vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].aim = w else: #Exception for which vg.vrb_sub_sentence = vg.vrb_sub_sentence + [ analyse_sentence.w_quest_which( W_QUESTION, 'choice', ['the'] + subsentence) ] vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].data_type = SUBSENTENCE + '+' + \ vg.vrb_sub_sentence[len( vg.vrb_sub_sentence) - 1].data_type vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].aim = w #If 'but' is between 2 nominal group and not before subsentence if w == 'but': #If the main verb is not a verb but a part of verbal structure => we have nominal groups for k in ['.', '?', '!', '' ] + ResourcePool().proposals: if not vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].sv \ or \ vg.vrb_sub_sentence[len(vg.vrb_sub_sentence) - 1].sv[0].vrb_main[0] == k: #We make changes and return the sentence with but of nominal groups phrase[phrase.index(w)] = ':but' vg.vrb_sub_sentence = vg.vrb_sub_sentence[:len( vg.vrb_sub_sentence) - 1] return phrase #We delete the subsentence phrase = phrase[:begin_pos] + phrase[begin_pos + end_pos:] + ['.'] return phrase return phrase
def y_n_ques(type, request, sentence): """ process the yes or no question from of a sentence Input=type and requesting of sentence and the sentence Output=class Sentence """ #init vg = VerbalGroup([], [], '', [], [], [], [], VerbalGroup.affirmative, []) analysis = Sentence(type, request, [], []) modal = [] stc = sentence #We start with determination of probably second verb in subsentence sentence = other_functions.find_scd_verb_sub(sentence) #We have to add punctuation if there is not if sentence == [] or sentence[0] == '.' or sentence[0] == '?' or sentence[ 0] == '!': #We have probably the aim as an adverb analyse_verbal_structure.find_adv([request], vg) analysis.aim = 'thing' analysis.sv = [vg] return analysis #We recover the auxiliary aux = sentence[0] #We have to know if there is a modal if aux in ResourcePool().modal: modal = aux #If we have a negative form if sentence[1] == 'not': vg.state = VerbalGroup.negative #We remove 'not' sentence = sentence[:1] + sentence[2:] #Wrong is a noun but not followed by the determinant if sentence[1] == 'wrong' and request == 'thing': analysis.sn = [NominalGroup([], [], ['wrong'], [], [])] sentence = [sentence[0]] + sentence[2:] #In this case we have an imperative sentence elif analyse_nominal_group.find_sn_pos(sentence, 1) == [] and type != W_QUESTION: #We have to reput the 'not' if vg.state == VerbalGroup.negative: sentence = sentence[:1] + ['not'] + sentence[1:] return other_sentence(type, request, sentence) #We delete the auxiliary sentence = sentence[1:] #We have to separate the case using these, this or there if sentence[0] in ResourcePool( ).demonstrative_det and analyse_verb.infinitive( [aux], 'present simple') == ['be']: #If we have a verb or an adverb just after (if not, we have a noun) if sentence[0].endswith('ed') or sentence[0].endswith( 'ing') or sentence[0].endswith( 'ly') or sentence[0] in ResourcePool().adverbs: #We recover this information and remove it analysis.sn = [NominalGroup([sentence[0]], [], [], [], [])] if sentence[0] == 'there' and aux == 'are': analysis.sn[0]._quantifier = 'SOME' sentence = sentence[1:] if not analysis.sn: #We recover the subject sentence = analyse_nominal_structure.recover_ns(sentence, analysis, 0) if aux == 'do' and not analyse_verbal_structure.can_be_imperative( sentence): return other_sentence('', '', stc) #If there is one element => it is an auxiliary => verb 'be' if len(sentence) == 0: vg.vrb_tense = analyse_verb.find_tense_statement(aux) vg.vrb_main = ['be'] else: sentence = analyse_verbal_structure.delete_unusable_word(sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg.vrb_tense = analyse_verb.find_tense_question(sentence, aux) #We process the verb verb = analyse_verb.find_verb_question(sentence, aux, vg.vrb_tense) verb_main = analyse_verb.return_verb(sentence, verb, vg.vrb_tense) vg.vrb_main = [other_functions.convert_to_string(verb_main)] #We delete the verb if the aux is not the verb 'be' if vg.vrb_main != ['be']: sentence = sentence[sentence.index(verb[0]) + len(verb_main):] elif sentence[0] == 'be': sentence = sentence[1:] #Here we have special processing for different cases if sentence: #For 'what' descrition case if sentence[0] == 'like' and aux != 'would': vg.vrb_main = ['like'] sentence = sentence[1:] #For 'how' questions with often elif sentence[0].endswith('ing') and not ( sentence[0].endswith('thing')): vg.vrb_main[0] = vg.vrb_main[0] + '+' + sentence[0] sentence = sentence[1:] #We recover the conjunctive subsentence sentence = analyse_verbal_structure.process_conjunctive_sub( sentence, vg) #It verifies if there is a secondary verb sec_vrb = analyse_verbal_structure.find_scd_vrb(sentence) if sec_vrb: sentence = analyse_verbal_structure.process_scd_sentence( sentence, vg, sec_vrb) #We recover the subsentence sentence = analyse_verbal_structure.process_subsentence(sentence, vg) #Process relative changes sentence = analyse_verbal_structure.correct_i_compl( sentence, vg.vrb_main[0]) sentence = analyse_verbal_structure.process_compare(sentence, vg) sentence = analyse_nominal_group.find_plural(sentence) #We recover the direct, indirect complement and the adverbial sentence = analyse_verbal_structure.recover_obj_iobj(sentence, vg) #We have to take off adverbs form the sentence sentence = analyse_verbal_structure.find_adv(sentence, vg) #We perform the processing with the modal if modal: vg.vrb_main = [modal + '+' + vg.vrb_main[0]] #If there is a forgotten sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) #In case there is a state verb followed by an adjective sentence = analyse_verbal_structure.state_adjective(sentence, vg) #We have to correct the mistake of the subject for p in ResourcePool().demonstrative_det: if analysis.sn and analysis.sn[0].det == [ p ] and analysis.sn[0].noun == []: if sentence != [0] and sentence[0] == '.' and sentence[ 0] == '?' and sentence[0] == '!': if sentence[0] in ResourcePool().proposals: pass else: analysis.sn[0].noun = [sentence[0]] sentence = sentence[1:] sentence = analyse_verbal_structure.state_adjective( sentence, vg) vg = analyse_verbal_structure.DOC_to_IOC(vg) while len(sentence) > 1: stc = analyse_verbal_structure.create_nom_gr(sentence, request) #We recover the direct, indirect complement and the adverbial stc = analyse_verbal_structure.recover_obj_iobj(stc, vg) if stc == sentence: #We leave the loop break else: sentence = stc vg = analyse_verbal_structure.refine_indirect_complement(vg) vg = analyse_verbal_structure.refine_subsentence(vg) vg = analyse_verbal_structure.DOC_to_IOC(vg) analysis.sv = [vg] return analysis
def conjugate_vrb(tense, verb, sn, type, aim): """ conjugates the verb Input=tense, verb in infinitive form, the adverb and subject Output=the verb conjugated """ #If there is no tense => we use the present simple if tense == '': tense = 'present simple' if aim.startswith('classification'): if not sn: sn = [NominalGroup([], [aim[15:]], [], [], [])] elif not sn[0].noun: sn[0].noun = [aim[15:]] if not sn: if type == IMPERATIVE: #If no subject, we use the third person of plural sn = [NominalGroup([], ['they'], [], [], [])] else: #If no subject, we use the third person of singular sn = [NominalGroup([], ['it'], [], [], [])] #For future simple if tense == 'future simple': return ['will'] + verb #For present simple elif tense == 'present simple': if verb[0] == 'be': #Plural nouns if sn[0].noun == ['I']: return ['am'] + verb[1:] elif other_functions.plural_noun(sn) == 1: return ['are'] + verb[1:] elif sn[0].noun == ['we'] or sn[0].noun == [ 'you' ] or sn[0].noun == ['they']: return ['are'] + verb[1:] else: #Singular nouns return ['is'] + verb[1:] else: #Plural nouns if other_functions.plural_noun(sn) == 1: return verb else: #Singular nouns for i in ResourcePool().irregular_verbs_present: if i[0] == verb[0]: return [i[1]] + verb[1:] return [verb[0] + 's'] + verb[1:] #For past simple elif tense == 'past simple': if verb[0] == 'be': if sn[0].noun == ['I']: return ['was'] + verb[1:] #Plural nouns elif other_functions.plural_noun(sn) == 1: return ['were'] + verb[1:] else: #Singular nouns return ['was'] + verb[1:] else: for i in ResourcePool().irregular_verbs_past: if i[0] == verb[0]: return [i[1]] + verb[1:] return [verb[0] + 'ed'] + verb[1:] #For progressive forms elif tense == 'present progressive': for m in ResourcePool().irregular_verbs_present: if m[0] == verb[0]: return conjugate_vrb('present simple', ['be'], sn, type, aim) + [m[2]] + verb[1:] return conjugate_vrb('present simple', ['be'], sn, type, aim) + [verb[0] + 'ing'] + verb[1:] elif tense == 'past progressive': for m in ResourcePool().irregular_verbs_present: if m[0] == verb[0]: return conjugate_vrb('past simple', ['be'], sn, type, aim) + [m[2]] + verb[1:] return conjugate_vrb('past simple', ['be'], sn, type, aim) + [verb[0] + 'ing'] + verb[1:] #For perfect forms elif tense == 'present perfect': for i in ResourcePool().irregular_verbs_past: if verb[0] == i[0]: return conjugate_vrb('present simple', ['have'], sn, type, aim) + [i[2]] + verb[1:] return conjugate_vrb('present simple', ['have'], sn, type, aim) + [verb[0] + 'ed'] + verb[1:] elif tense == 'present perfect': for i in ResourcePool().irregular_verbs_past: if verb[0] == i[0]: return ['had'] + [i[2]] + verb[1:] return ['had'] + [verb[0] + 'ed'] + verb[1:] #For passive forms elif tense == 'present passive': return conjugate_vrb('present simple', ['be'], sn, type, aim) + conjugate_vrb( 'present perfect', verb, sn, type, aim)[1:] elif tense == 'past passive': return conjugate_vrb('past simple', ['be'], sn, type, aim) + conjugate_vrb( 'present perfect', verb, sn, type, aim)[1:] #For conditional forms elif tense == 'present conditional': return ['would'] + verb elif tense == 'past conditional': return ['would'] + conjugate_vrb('present perfect', verb, sn, type, aim) #Default case return []
def other_sentence(type, request, sentence): """ process the other from of a sentence Input=type and requesting of sentence and the sentence Output=class Sentence """ #init vg = VerbalGroup([], [], '', [], [], [], [], VerbalGroup.affirmative, []) analysis = Sentence(type, request, [], []) modal = [] if not sentence: return [] #We have to add punctuation if there is not if sentence[len(sentence) - 1] not in ['.', '?', '!']: sentence = sentence + ['.'] #We start with determination of probably second verb in subsentence sentence = other_functions.find_scd_verb_sub(sentence) #We search the subject sbj = analyse_nominal_group.find_sn_pos(sentence, 0) if sbj != [] or type == RELATIVE: #If we haven't a data type => it is a statement if type == '': analysis.data_type = STATEMENT #We have to separate the case using these, this or there if sentence[0] in ResourcePool( ).demonstrative_det and analyse_verb.infinitive( [sentence[1]], 'present simple') == ['be']: #We recover this information and remove it analysis.sn = [NominalGroup([sentence[0]], [], [], [], [])] if sentence[0] == 'there' and sentence[1] == 'are': analysis.sn[0]._quantifier = 'SOME' sentence = sentence[1:] if not analysis.sn: #We recover the subject sentence = analyse_nominal_structure.recover_ns( sentence, analysis, 0) #End of the sentence? -> nominal sentence if sentence == [] or sentence[0] in ['.', '!', '?']: analysis.sv = [] return analysis #We have to know if there is a modal if sentence[0] in ResourcePool().modal: modal = sentence[0] if modal == 'can' or modal == 'must' or modal == 'shall' or modal == 'may': sentence = sentence[1:] #We must take into account all possible cases to recover the sentence's tense if len(sentence) > 1 and sentence[1] == 'not': vg.state = VerbalGroup.negative #Before the negative form we have an auxiliary for the negation if sentence[0] == 'do' or sentence[0] == 'does' or sentence[ 0] == 'did': vg.vrb_tense = analyse_verb.find_tense_statement([sentence[0]]) sentence = sentence[2:] sentence = analyse_verbal_structure.delete_unusable_word( sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) #There is a modal elif modal: sentence = [sentence[0]] + sentence[2:] sentence = analyse_verbal_structure.delete_unusable_word( sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg.vrb_tense = analyse_verb.find_tense_statement(sentence) else: #We remove 'not' and find the tense sentence = sentence[:1] + sentence[2:] sentence = analyse_verbal_structure.delete_unusable_word( sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg.vrb_tense = analyse_verb.find_tense_statement(sentence) #For the affirmative processing else: if sentence[0] == 'not': vg.state = VerbalGroup.negative sentence = sentence[1:] sentence = analyse_verbal_structure.delete_unusable_word(sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg.vrb_tense = analyse_verb.find_tense_statement(sentence) verb = analyse_verb.find_verb_statement(sentence, vg.vrb_tense) verb_main = analyse_verb.return_verb(sentence, verb, vg.vrb_tense) vg.vrb_main = [other_functions.convert_to_string(verb_main)] #We delete the verb sentence = sentence[sentence.index(verb[0]) + len(verb_main):] #We perform the processing with the modal if modal: vg.vrb_main = [modal + '+' + vg.vrb_main[0]] #This is a imperative form else: #re-init analysis.data_type = IMPERATIVE vg.vrb_tense = 'present simple' if sentence[0] in ResourcePool().proposals: sentence = ['.'] + sentence #Negative form if sentence[1] == 'not': sentence = sentence[sentence.index('not') + 1:] sentence = analyse_verbal_structure.delete_unusable_word(sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg.state = VerbalGroup.negative else: sentence = analyse_verbal_structure.delete_unusable_word(sentence) sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) #We process the verb verb = [sentence[0]] verb_main = analyse_verb.return_verb(sentence, verb, vg.vrb_tense) vg.vrb_main = [other_functions.convert_to_string(verb_main)] #We delete the verb sentence = sentence[sentence.index(verb[0]) + len(verb_main):] if sentence and sentence[-1] == '?': analysis.data_type = YES_NO_QUESTION #We recover the conjunctive subsentence sentence = analyse_verbal_structure.process_conjunctive_sub(sentence, vg) #It verifies if there is a secondary verb sec_vrb = analyse_verbal_structure.find_scd_vrb(sentence) if sec_vrb: sentence = analyse_verbal_structure.process_scd_sentence( sentence, vg, sec_vrb) #We recover the subsentence sentence = analyse_verbal_structure.process_subsentence(sentence, vg) if sentence != [] and vg.vrb_main != []: #Process relative changes sentence = analyse_verbal_structure.correct_i_compl( sentence, vg.vrb_main[0]) sentence = analyse_verbal_structure.process_compare(sentence, vg) sentence = analyse_nominal_group.find_plural(sentence) #We recover the direct, indirect complement and the adverbial sentence = analyse_verbal_structure.recover_obj_iobj(sentence, vg) #We have to take off abverbs form the sentence sentence = analyse_verbal_structure.find_adv(sentence, vg) #In case there is a state verb followed by an adjective sentence = analyse_verbal_structure.state_adjective(sentence, vg) #If there is a forgotten sentence = analyse_verbal_structure.find_vrb_adv(sentence, vg) vg = analyse_verbal_structure.DOC_to_IOC(vg) while len(sentence) > 1: stc = analyse_verbal_structure.create_nom_gr(sentence, request) #We recover the direct, indirect complement and the adverbial stc = analyse_verbal_structure.recover_obj_iobj(stc, vg) if stc == sentence: #We leave the loop break else: sentence = stc vg = analyse_verbal_structure.refine_indirect_complement(vg) vg = analyse_verbal_structure.refine_subsentence(vg) vg = analyse_verbal_structure.DOC_to_IOC(vg) analysis.sv = [vg] return analysis
def remove(self, statements): ResourcePool().ontology_server.remove(statements)
class QuestionHandler(object): def __init__(self, current_speaker=None): self._sentence = None self._statements = [] self._current_speaker = current_speaker # This field takes the value True or False when processing a # Yes-No-question and takes a list of returned values from # the ontology when processing a w_question self._answer = False # This field is set to 'None' when the answer of the question # (wh-question) that is being processed aims to give information # about the subject. #It also holds the flags 'QUERY_ON_DIRECT_OBJ' and 'QUERY_ON_INDIRECT_OBJ'. self._query_on_field = None self._process_on_location = False # This field is set to True, when the verb 'to know' occurs in a # sentence. self.process_on_knowing_concept = False # This defines the default model used to resolve queries. self._default_agent = ResourcePool().default_model def clear_statements(self): self._statements = [] def set_current_speaker(self, current_speaker): """ Updates the speaker ID. """ self._current_speaker = current_speaker def get_query_on_field(self): return self._query_on_field 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 _build_situation_statements(self): sit_id = generate_id(with_question_mark=False) stmts = ["%s experiences %s" % (self._current_speaker, sit_id)] stmts += ["%s rdf:type InterrogativeState" % sit_id] for sn in self._sentence.sn: stmts += ["%s hasObject %s" % (sit_id, sn.id)] stmts += ["%s hasAim %s_question_aim" % (sit_id, self._sentence.aim)] stmts += [ "%s hasAnswer %s" % (sit_id, "true" if self._answer else "false") ] return stmts, sit_id def _set_situation_id(self, statements): """This attempts to clarify the ID of an action verbs E.g: statement = [?event rdf:type Go, ?event performedBy myself, ?event actsOnObject xxx] We attemtps to find an existing ontology ID matching '?event' """ stmts = [] find_id = False for s in statements: if '?' in s: find_id = True break if find_id: sit_id = ResourcePool().ontology_server.find(['?event'], statements) if sit_id: logger.debug( "\t/Found a staticSituation matching the yes_no_question query to be checked: " + str(sit_id)) for s in statements: #TODO:the ontology might find severals sit ID matching the query. Should we take this consideration? #The longer the query, the better the result of sit_id stmts.append(s.replace('?event', sit_id[0])) else: stmts = statements # Find process on knowing concept for s in statements: if "knows" in s: self.process_on_knowing_concept = True break return stmts def _extend_statement_from_sentence_aim(self, current_statements, sn=None): """This extends the statements states so that the query answer matches the w_question aim """ #Concept descriptor # E.g: Human, Object, Color ,Size... concept_descriptor = self.get_concept_descriptor(sn) #Case: the statement is complete from statement builder e.g: what is in the box? =>[?concept isIn ?id_box, ?id_box rdf:type Box] for s in current_statements: if '?concept' in s.split(): return current_statements + concept_descriptor #case: the statement is partially build from statement builder stmts = [] if sn: for sv in self._sentence.sv: for verb in sv.vrb_main: role = self.get_role_from_sentence_aim( self._query_on_field, verb) #Case of looking for the object in a location if role == 'objectFoundInLocation': self._process_on_location = True # Case of state verbs if verb.lower() in ResourcePool().state: stmts.append(sn.id + ' ' + role + ' ?concept') # Case of action verb with a passive behaviour elif verb.lower() in ResourcePool( ).action_verb_with_passive_behaviour.keys(): stmts.append(sn.id + ' ' + ResourcePool( ).action_verb_with_passive_behaviour[verb.lower()] + ' ?concept') # Case of know elif verb.lower() == 'know': self.process_on_knowing_concept = True stmts.append(sn.id + ' knows ?concept') # case of action verbs else: stmts.append('?event ' + role + ' ?concept') return current_statements + stmts + concept_descriptor def _set_query_on_field(self, sentence): """ This defines which part of a sentence is supposed to be completed once the answer of a w_question has been retrieved E:g - [W_question] : where is the cube - Answer: table - query_on_field = 'QUERY_ON_INDIRECT_OBJ' - Sentence built from answer, query_on_field, and w_question: the cube is on the table """ if sentence.aim == 'place': return 'QUERY_ON_INDIRECT_OBJ' if not sentence.sn: return None if sentence.sv: if not sentence.sv[0].d_obj: query_on_field = 'QUERY_ON_DIRECT_OBJ' else: query_on_field = 'QUERY_ON_INDIRECT_OBJ' return query_on_field def get_role_from_sentence_aim(self, query_on_field, verb): """ Given specific w_question aim and verb, this function attempts to define the matching object property to built an RDF tuple <S P O>. Cf. QuestionAimDict() for more detail. """ dic_aim = QuestionAimDict().dic_aim try: if verb.lower() in dic_aim[self._sentence.aim][query_on_field]: role = dic_aim[self._sentence.aim][query_on_field][ verb.lower()] else: role = dic_aim[self._sentence.aim][query_on_field][None] except KeyError: if verb.lower() in dic_aim[self._sentence.aim][None]: role = dic_aim[self._sentence.aim][None][verb.lower()] else: role = dic_aim[self._sentence.aim][None][None] return role def get_concept_descriptor(self, ng): """ Get the type or feature of the concept to query if it is not mapped in the QuestionAimDict E.g: What color is the bottle? Here, the aim 'color' is about a feature and it is not in the QuestionAimDict. We return it in concept_descriptor = 'id hasColor ?concept' E.g: What Human do you see? Here, the aim 'human' is not a feature, and is not in the QuestionAimDict We return it in concept_descriptor = '?concept rdf:type Human' """ concept_descriptor = [] agent = self._default_agent aim = self._sentence.aim #Concept's Features if self._sentence.aim in ResourcePool().adjectives_ontology_classes: if ng: concept_descriptor = [ ng.id + " has" + aim.capitalize() + " ?concept" ] self._sentence.aim = "thing" #Concept's Type elif not self._sentence.aim in QuestionAimDict().dic_aim.keys(): logger.debug("\tFound the aim: " + aim + ".Extending statements with [?concept rdf:type aim]") onto = ResourcePool().ontology_server.lookupForAgent( ResourcePool().get_model_mapping(agent), aim) concept_descriptor = [ "?concept rdf:type " + get_class_name(aim, onto) ] self._sentence.aim = "thing" elif self._sentence.aim == "people": concept_descriptor = ["?concept rdf:type Agent"] return concept_descriptor """ what aim => 'thing' what kind => aim = 'thing', sn = [the kind of] what type => aim = 'thing' , sn = [the type of] what time => aim = 'time' which aim => 'choice' when aim => 'date' where aim => 'Place' where (from) => 'origin' why aim => 'reason' who aim => 'person' whose aim => 'owner' whom aim => 'person' how aim => 'place' how long => aim = 'duration' how far => aim = 'distance' how often => aim = 'Frequency' How much => aim = 'Quantity' How many => aim = 'Quantity' """ def _remove_statements_with_no_unbound_tokens(self, statements): """ This remove statement part with no unbound token, for querying the ontology.""" stmts = [] for s in statements: if '?' in s: stmts.append(s) return stmts
def process_verb(self, verbal_group, subject_id, subject_quantifier, second_verb_sit_id): for verb in verbal_group.vrb_main: # Case 1: the state verb 'to be'/ to become""" #Case 2: actions or stative verbs with a specified 'goal' or 'thematic' role: # see '../../share/dialog/thematic_roles' #Case 3: actions verbs with 'passive behaviour' like 'see' #Case 4: special case for 'know' #Case 5: other action or stative verbs # Modal or phrasal verbs. E.g: can+do, look+for , ... # verb = must+do modal = '' if '+' in verb: # Case of Modals [modal, verb] = verb.split('+') if modal in ResourcePool().modal: pass #self._statements.append(sit_id + " rdf:type " + verb.capitalize()) #self._statements.append(subject_id+ " " + modal +"Performs " + sit_id) #Case 1: if verb in ResourcePool().state: if isinstance(subject_id, basestring): subjects_id = [subject_id] else: subjects_id = subject_id agentslist = ResourcePool().ontology_server.listAgents() if agentslist is None: agentslist = [ResourcePool().default_model, self._current_speaker] for subject_id in subjects_id: if subject_id in agentslist: sit_id = generate_id(with_question_mark=False) self._statements.append(subject_id + " experiences " + sit_id) else: #TODO: Will keep only the last one is several ids sit_id = subject_id else: # First, create a situation ID that represent the # semantic situation carried by the verbal phrase #Case : the verbal group that is being processed is the second verbs . i.e : it is held in the field sentence.sv.sv_sec if second_verb_sit_id: sit_id = second_verb_sit_id # Case of question elif self._process_on_question: sit_id = '?event' #case of negation : Creating a fake ID that is to find in the ontology for later removal # Setting up the field process_statement_to_remove to True elif self._process_on_negative: sit_id = generate_id(with_question_mark=True) self._unclarified_ids.append(sit_id) self.process_statements_to_remove = True # General case: we generate an ID else: sit_id = generate_id(with_question_mark=not self._process_on_resolved_sentence) # Then, process the type of verb #Case 2: if verb in ResourcePool().goal_verbs: self._statements.append(subject_id + " desires " + sit_id) if verbal_group.sv_sec: self.process_vrb_sec(verbal_group, subject_id, subject_quantifier, sit_id) #Case 3: action verbs wit passive behaviour elif verb.lower() in ResourcePool().action_verb_with_passive_behaviour.keys(): sit_id = subject_id # Case 4: 'know' elif verb.lower() == 'know': pass #Case 5: other verbs -> reification else: self._statements.append(sit_id + " rdf:type " + verb.capitalize()) self._statements.append(sit_id + " performedBy " + subject_id) if not self._process_on_question and \ not self._process_on_negative \ and self._process_on_resolved_sentence: # If I'm not processing a question, add a label # to this action self._statements.append(sit_id + " rdfs:label \"" + \ verb.capitalize() + " action #" + sit_id + "\"") # Store the situation id self.situation_id = sit_id #Imperative specification, add the goal verb 'desire' if self._process_on_imperative: self._statements.append(self._current_speaker + " desires " + sit_id) #Direct object if verbal_group.d_obj: self.process_direct_object(verbal_group.d_obj, verb, sit_id, subject_quantifier) #Indirect Complement if verbal_group.i_cmpl: self.process_indirect_complement(verbal_group.i_cmpl, verb, sit_id) # Adverbs modifiying the manner of an action verb if verbal_group.vrb_adv: self.process_action_verb_adverb(verbal_group.vrb_adv, verb, sit_id) #verb tense if verbal_group.vrb_tense: self.process_verb_tense(verbal_group, verb, sit_id)
def __init__(self): """ This class consits in building a map of object property regarding the Question's aim attribute and the query_on_field parameter. Below is a description of what should be generated depending of the question that is processed. 'What and which-question': Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' extend statements with [?event OBJ ?concept] where OBJ depends on the verb. e.g: if verb == "get": OBJ = "actsOnObject" if verb == "drive": OBJ = "involves" ... Case # query_on_field = None Nothing to extend Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' Nothing to extend 'Who-question': Case # query_on_field = None extend statements with [* performedBy ?concept] Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' and state verbs extend statements with [* rdfs:label ?concept] E.g: Who is the car's driver? Case # query_on_field = 'QUERY_ON_DIRECT_OBJ' and action verbs same as "what" and "which" question for 'QUERY_ON_DIRECT_OBJ' Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' extend statements with [* receivedBy ?concept] 'Where-question': Case # query_on_field = 'QUERY_ON_INDIRECT_OBJ' extend statements with [* objectFoundInLocation ?concept] """ self.dic_aim = {} #Dictionaries related to thematice roles verbs verbs_dic = ResourcePool().thematic_roles.verbs self.dic_on_direct_obj = dict([(verb, role.id) for verb in verbs_dic.keys() for role in verbs_dic[verb].roles[0:1]]) self.dic_on_direct_obj[None] = 'involves' self.dic_on_direct_obj['be'] = 'owl:sameAs' self.dic_on_indirect_obj = dict([(verb, role.id) for verb in verbs_dic.keys() for role in verbs_dic[verb].roles[1:2] ]) self.dic_on_indirect_obj['be'] = None self.dic_on_indirect_obj[None] = 'owl:sameAs' #Dictionary for sentence.aim = 'place' self.dic_place = {None: self.dic_on_indirect_obj.copy()} self.dic_place[None]['be'] = 'objectFoundInLocation' #Dictionary for sentence.aim = 'thing' self.dic_thing = {None: self.dic_on_direct_obj.copy()} #Dictionary for sentence.aim = 'manner' self.dic_manner = {None: {'be': 'owl:topObjectProperty'}} #Dictionary for sentence.aim = 'people' self.dic_people = { 'QUERY_ON_DIRECT_OBJ': self.dic_on_direct_obj.copy(), 'QUERY_ON_INDIRECT_OBJ': self.dic_on_indirect_obj.copy() } #Dictionary for all question aims #What-question self.dic_aim['thing'] = self.dic_thing #Who-question self.dic_aim['people'] = self.dic_people #Where-question self.dic_aim['place'] = self.dic_place #How-Question self.dic_aim['manner'] = self.dic_manner #which-question self.dic_aim['choice'] = self.dic_thing
def process_sentence_adverb(self, verbal_group): id = generate_id(with_question_mark=False) for a in verbal_group.advrb: if a in ResourcePool().location_adverbs: self._statements += ["%s hasGoal %s" % (self.situation_id, id), "%s rdf:type %sZone" % (id, a.capitalize())]
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