else: results.append(False) if results[1] == True: position = 0 for term in terms: if term == main_terms_to_find[1]: break else: position = position + 1 year = int(terms[position - 1]) if results[0] == True: year = year + 1 return year else: year = 0 if __name__ == "__main__": from pprint import pprint duck_data = duckling.parse("Hoteles de dos estrellas", language="es", dim_filter="number") pprint(duck_data)
class Brain: MODULE_BASE_PATH = 'lucia.tasks.' def __init__(self): self.model = None self.r = sr.Recognizer() self.nlp = spacy.load(conf.get_property('spacy')['model']) self.espeak = conf.get_property('espeak') # Load low-level Duckling model self.duckling = Duckling() self.duckling.load( languages=conf.get_property('duckling')['languages']) # Remember tasks self.task_memory = [] def create_model(self): # Create a DeepSpeech model with model path self.model = Model(conf.get_property('deepspeech')['model_path']) # Enable decoding using an external scorer self.model.enableExternalScorer( conf.get_property('deepspeech')['scorer_path']) def listen(self, debug_mode=False): while True: with sr.Microphone(sample_rate=conf.get_property( 'speech_recognition')['audio_rate']) as source: # Listen for a while and adjust the energy threshold to start and stop recording voice to account for ambient noise self.r.adjust_for_ambient_noise( source, duration=conf.get_property( 'speech_recognition')['energy_threshold']) self.r.dynamic_energy_threshold = True if debug_mode is False: print("Say something") audio = self.r.listen(source) # Speech to text audio = np.frombuffer(audio.frame_data, np.int16) text = self.model.stt(audio) self.speak(text) else: text = input() # Wake up on hearing the wake word #if any(subtext in text for subtext in conf.get_property('wake_words')): # self.understand(text) self.understand(text) def speak(self, text): subprocess.call('espeak-ng -v {}+{}{} "{}"'.format( self.espeak['language'], self.espeak['gender'], self.espeak['pitch'], text), shell=True) def understand(self, sentence): # Break paragraph into sentences tokenized_sentence = sent_tokenize(sentence) # Break sentence into words for sent in tokenized_sentence: tokenized_word = word_tokenize(sent) # Tag corpora with universal POS tagset # For tag list, read https://www.nltk.org/book/ch05.html#tab-universal-tagset pos_tags = nltk.pos_tag(tokenized_word, tagset='universal') # Divide sentence into noun phrases with regular expression grammar = 'NOUN: {<DET>?<ADJ>*<NOUN>}' cp = nltk.RegexpParser(grammar) # Find chunk structure cs = cp.parse(pos_tags) # B-{tag} beginning, I-{tag} inside, O-{tag} outside iob_tags = np.asarray(tree2conlltags(cs)).tolist() # Recognize named entities doc = self.nlp(sent) # Parse word into numeral, ordinal, and time parse = lambda ne: dict([[ _['dim'], _['value']['value'] ] for _ in self.duckling.parse( ne, dim_filter=conf.get_property('duckling')['dimensions'])]) # [Word, character positions and entity type]. For all entity types, read https://spacy.io/api/annotation#named-entities ne = list([ ent.text, ent.start_char, ent.end_char, ent.label_, parse(ent.text) ] for ent in doc.ents) ne_tags = [_.ent_type_ for _ in doc] # Merge iob tags and named entity tags tagged_sent = [ list(np.append(iob_tags[i], ne_tags[i])) for i in range(len(iob_tags)) ] tagged_sent = ''.join(str(x) for x in tagged_sent) self.decide(tagged_sent, ne) def think(self, pattern, tagged_sent): # Match tagged sentence against combinations of POS tags, words in any order: (?=.*\bword\b)(?=.*\bADJ\bNOUN\b).* r = re.compile( '(?=.*\\b' + pattern.replace(' ', '\\b.*\\b').replace(' ', '\\b)(?=.*\\b') + '\\b).*') return r.search(tagged_sent) def decide(self, tagged_sent, named_entity): for task in conf.get_property('tasks'): for pattern in conf.get_property('tasks')[task]: # If sentence matches any pattern, dynamtically create class if self.think(pattern, tagged_sent): # Split module name and class name with dot module = importlib.import_module(self.MODULE_BASE_PATH + task.rsplit('.', 1)[0]) instance = getattr(module, task.rsplit('.', 1)[1])() print(instance) # Search whether task_memory contains the same class instance _run = False for mem in self.task_memory: if type(instance) == type(mem): mem.run(self, tagged_sent, named_entity) _run = True break if not _run: # If not exists, store new class instance in task_memory self.task_memory = [ instance.run(self, tagged_sent, named_entity) ] + self.task_memory break
def test_not_load(): duckling = Duckling() assert duckling._is_loaded is False with pytest.raises(RuntimeError): duckling.parse('')
class AppointmentForm(FormAction): """Example of a custom form action""" def __init__(self): self.d = Duckling() self.d.load() def name(self): # type: () -> Text """Unique identifier of the form""" return "appointment_form" @staticmethod def required_slots(tracker: Tracker) -> List[Text]: """A list of required slots that the form has to fill""" return ["date", "time", "pet", "petName"] def slot_mappings(self): return {"date": [self.from_entity(entity="date"), self.from_text()], "time": [self.from_entity(entity="time"), self.from_text()], "pet": [self.from_entity(entity="pet"), self.from_text()], "petName": [self.from_entity(entity="petName"), self.from_text()], } @staticmethod def pet_db(): # type: () -> List[Text] """Database of supported cuisines""" return ["dog", "cat", "bird", "tortoise", "rabbit", "guinea pig", "mouse", "hamster", "turtles"] def parseRet(self, value:Text, dim:Text, grain:Text) -> Text: parses = self.d.parse(value) for parse in parses: if parse ['dim'] == dim: if parse['value'].get('grain') == grain: return parse ['value']['value'] return None def validate_date(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]: """Validate date value.""" date = self.parseRet(value, 'time', 'day') if (date != None): return {"date": date} else: dispatcher.utter_template('utter_wrong_date', tracker) # validation failed, set this slot to None, meaning the # user will be asked for the slot again return {"date": None} def validate_pet(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]: """Validate pet value.""" if value.lower() in self.pet_db(): # validation succeeded return {"pet":value} else: dispatcher.utter_template('utter_wrong_pet', tracker) # validation failed, set this slot to None, meaning the # user will be asked for the slot again return {"pet": None} def validate_time(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]: """Validate time value.""" time = self.parseRet(value, 'time', 'minute') if (time != None): return {"time":time} else: dispatcher.utter_template('utter_wrong_time', tracker) # validation failed, set slot to None return {"time": None} def validate_petName(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]: """Validate petName value.""" print (value) return {"petName": value} def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict]: """Define what the form has to do after all required slots are filled""" # utter submit template print("petName: "+tracker.get_slot("petName")) print("pet: "+tracker.get_slot("pet")) print("time: "+tracker.get_slot("time")) print("date: "+tracker.get_slot("date")) url = 'https://dimo1.ii.uam.es:8443/VeterinarioApi/Rasa' myobj = {'petName': tracker.get_slot("petName"), 'pet': tracker.get_slot("pet"), 'time': tracker.get_slot("time"), 'date': tracker.get_slot("date"),} x = requests.post(url, json = myobj) print(x.text) dispatcher.utter_message(x.text) #dispatcher.utter_template('utter_submit', tracker) return [SlotSet("petName", None), SlotSet("pet", None), SlotSet("time", None), SlotSet("date", None)]