def adapt_intents(self): intents = {} for intent_name in self.intents: intents[intent_name] = [] keywords = self.samples2keywords(self.intents[intent_name], lang=self.lang) self.strict = True # TODO WIP if self.strict: intent = AdaptBuilder(intent_name) for kw in keywords: if kw["required"]: intent.require(kw["name"]) else: intent.optionally(kw["name"]) intents[intent_name] += [{ "intent": intent.build().__dict__, "entities": keywords }] else: print("WARNING: strict is an experimental setting, heavy WIP") required_kws = [ k for k in keywords if k["required"] and not k.get("regex") ] optional_kws = [ k for k in keywords if not k["required"] and not k.get("regex") ] for k in required_kws: for s in k["samples"]: new_required_keywords = [] for t in tokenize(s): if t in self.stop_words: continue kw = { "name": t + "_token", "required": True, "samples": [t] } new_required_keywords.append(kw) intent = AdaptBuilder(intent_name) for kw in new_required_keywords: if kw["required"]: intent.require(kw["name"]) else: intent.optionally(kw["name"]) intents[intent_name] += [{ "intent": intent.build().__dict__, "entities": new_required_keywords + optional_kws }] return intents
def wrapper(self): for intent_name, info in func(self).iteritems(): intent = IntentBuilder(intent_name) if "require" not in info: info["require"] = [] if "optionally" not in info: info["optionally"] = [] if "one of" not in info: info["one of"] = [] for require in info["require"]: intent.require(require) for optionally in info["optionally"]: intent.optionally(optionally) for one_of in info["one of"]: intent.one_of(one_of) intent = intent.build() logger.debug("Adding {} intent through {} plugin".format( intent_name, self.__class__.__name__)) engine_handler.get_engine().register_intent_parser(intent) plugins_handler.set_intent_plugin(intent_name, self.__class__.__name__) return func(self)
def initialize_intent_parser(self): self._intents_container = IntentContainer("%s_cache" % self._name) self._adapt_intent_engine = DomainIntentDeterminationEngine() self._adapt_intent_engine.register_domain(self._name) for intent_name, intent_file_path in self.get_intent_names(): #print ("###### IntentBuilder: %s, %s" % (intent_name, intent_file_path)) adapt_intent_builder = IntentBuilder(intent_name) for intent_name, intent_example_sentences_array in self.intent_training_file_content( intent_file_path, 'intent'): #print ("add intent %s, %s" % (intent_name, intent_example_sentences_array)) self._intents_container.add_intent( intent_name, intent_example_sentences_array) for entity_name, entities_array in self.intent_training_file_content( intent_file_path, 'entities'): #print ("add entity %s, %s " % (entity_name, entities_array)) self._intents_container.add_entity(entity_name, entities_array) # adapt if entity_name.endswith("_keyword"): for k in entities_array: #print ("add keyword %s to %s" % (k, intent_name)) self._adapt_intent_engine.register_entity( k, entity_name, domain=self._name) adapt_intent_builder.require(entity_name) adapt_intent = adapt_intent_builder.build() self._adapt_intent_engine.register_intent_parser(adapt_intent, domain=self._name) self._intents_container.train(debug=False)
def load_engine(self) -> None: """Configure Adapt engine if not already cached.""" if self.engine is None: from adapt.intent import IntentBuilder from adapt.engine import IntentDeterminationEngine config_path = self.profile.read_path("adapt_config.json") if not os.path.exists(config_path): return # Create empty engine self.engine = IntentDeterminationEngine() assert self.engine is not None # { intents: { ... }, entities: [ ... ] } with open(config_path, "r") as config_file: config = json.load(config_file) # Register entities for entity_name, entity_values in config["entities"].items(): for value in entity_values: self.engine.register_entity(value, entity_name) # Register intents for intent_name, intent_config in config["intents"].items(): intent = IntentBuilder(intent_name) for required_entity in intent_config["require"]: intent.require(required_entity) for optional_entity in intent_config["optionally"]: intent.optionally(optional_entity) self.engine.register_intent_parser(intent.build()) self._logger.debug("Loaded engine from config file %s", config_path)
def register_intent(self, intent_name, samples=None, optional_samples=None, rx_samples=None): """ :param intent_name: intent_name :param samples: list of required registered entities (names) :param optional_samples: list of optional registered samples (names) :return: """ super().register_intent(intent_name, samples) if not samples: samples = [intent_name] self.register_entity(intent_name, samples) optional_samples = optional_samples or [] # structure intent intent = IntentBuilder(intent_name) for kw in samples: intent.require(kw) for kw in optional_samples: intent.optionally(kw) self.engine.register_intent_parser(intent.build()) return intent
def build(self): """ Builds out all the options specified and compiles them into the intent engine. """ for intent_name, entities in self.entities.items(): new_intent = IntentBuilder(intent_name) for entity_name, data in entities.items(): # If regex entity. if 'values' not in data: self.engine.register_regex_entity(entity_name) # Parse out name in regex (assume between < and >). keyword = entity_name.split('<')[1].split('>')[0] if data['required']: new_intent = new_intent.require(keyword) else: new_intent = new_intent.optionally(keyword) else: for value in data['values']: self.engine.register_entity(value, entity_name) if data['required']: new_intent = new_intent.require(entity_name) else: new_intent = new_intent.optionally(entity_name) new_intent = new_intent.build() self.engine.register_intent_parser(new_intent)
def testEmptyTags(self): # Validates https://github.com/MycroftAI/adapt/issues/114 engine = IntentDeterminationEngine() engine.register_entity("Kevin", "who") # same problem if several entities builder = IntentBuilder("Buddies") builder.optionally("who") # same problem if several entity types engine.register_intent_parser(builder.build()) intents = [i for i in engine.determine_intent("Julien is a friend")] assert len(intents) == 0
def make_intents(self, rx): rx_combos = [rx] rx_combos = expand_rx(rx.strip()) intents = [] if interact: pdb.set_trace() for combo in rx_combos: i_name = '{}{}Intent'.format(self.h_prefix, hash_sum(combo)) #self.log.debug('combo = {}'.format(combo)) if re.match('^[a-z0-9 ]+$', combo): # keywords only entity_type = self.make_entity_type(combo) intent = IntentBuilder( re.sub('Keywords?', 'Intent', entity_type)).require(entity_type).build() intents.append(intent) continue self.register_regex(combo) parts = re.split('(\(|\))', combo) intent_builder = IntentBuilder(i_name) section = '' for idx in range(len(parts)): # separate keywords from names part = parts[idx] if section and part == '(': # got a complete keyword entity_type = self.make_entity_type(section) intent_builder.require(entity_type) section = '(' continue section += part match = re.match('\(\?P<\w+>.+\)', section) if match: # got a named group span = re.search('<\w+>', section).span() entity_type = section[span[0] + 1:span[1] - 1] if not idx == len(parts) - 1 and re.match( '(\?|\*).*', parts[idx + 1]): intent_builder.optionally(entity_type) else: intent_builder.require(entity_type) section = '' continue intents.append(intent_builder.build()) self.log.info('Created intent: {}'.format(str( intents[-1].__dict__))) return intents
def train(self): # print("Words:") # pprint(self.words) # print("") # print("Intents:") # pprint(self.intent_map['intents']) # print("Keywords:") # pprint(self.keywords) for intent in self.intent_map['intents']: required_words = [] optional_words = [] # print("Training {}".format(intent)) # pprint(self.keywords) for word in self.intent_map['intents'][intent]['words']: intents_count = len(self.intent_map['intents']) word_appears_in = len(self.words[word]) # print("Word: {} Weight: {} Intents: {} Appears in: {}".format(word, weight, intents_count, word_appears_in)) self.intent_map['intents'][intent]['words'][word][ 'weight'] = self.intent_map['intents'][intent]['words'][ word]['weight'] * (intents_count - word_appears_in) / intents_count if (self.intent_map['intents'][intent]['words'][word] ['required']): # add the word as required. # print("adding '{}' as required".format(word_token)) required_words.append(self.add_word(intent, word)) else: # if the word is a keyword list, add it if (word[:1] + word[-1:] == "{}"): optional_words.append(self.add_word(intent, word)) else: if (self.intent_map['intents'][intent]['words'][word] ['weight'] > 0.35): # print("adding '{}' as optional".format(word_token)) optional_words.append(self.add_word(intent, word)) construction = IntentBuilder(intent) for keyword in required_words: # print("Required word: {}".format(keyword)) construction = construction.require(keyword) for keyword in optional_words: # print("Optional word: {}".format(keyword)) construction = construction.optionally(keyword) if (construction): # print("Building {}".format(intent)) self.engine.register_intent_parser(construction.build()) # pprint(self.intent_map['intents']) # print("") self.trained = True
def register_intent(name, engine, *keywords, **kwargs): for keyword in keywords: engine.register_entity(keyword, name.title() + "Keyword") for index, values in kwargs.items(): for value in values: engine.register_entity(value, name.title() + index.title()) intent = IntentBuilder(name.title() + "Intent")\ .require("RecycleKeyword")\ .require(name.title() + "Keyword") for index in kwargs: intent = intent.optionally(name.title() + index.title()) intent = intent.build() engine.register_intent_parser(intent)
def loadIntentSpec(self, domain, data): if not 'intent' in data: return False if not domain in self.engine.domains: self.engine.register_domain(domain) new_intent = IntentBuilder(data['intent']) if 'exact' in data: for term in data['exact']: self.exact_matches[term] = data['intent'] if 'required' in data: for entity in data['required']: for key, value in entity.iteritems(): if isinstance(value, basestring): self.engine.register_regex_entity(value, domain=domain) new_intent = new_intent.require(key) continue for keyword in value: self.engine.register_entity(keyword, key, domain=domain) new_intent = new_intent.require(key) if 'optionally' in data: for entity in data['optionally']: for key, value in entity.iteritems(): for keyword in value: self.engine.register_entity(keyword, key, domain=domain) new_intent = new_intent.optionally(key) new_intent = new_intent.build() self.engine.register_intent_parser(new_intent, domain=domain) return True
def register_keyword_intent(self, name, samples=None, optionals=None, handler=None, ignore_default_kw=False): optionals = optionals or [] samples = samples or [name] intent_name = self.object_type + ':' + name intent = IntentBuilder(intent_name) if samples and isinstance(samples, list): samples = {samples[0]: samples} if optionals and isinstance(optionals, list): optionals = {optionals[0]: optionals} if not ignore_default_kw: data = self.load_resource(name) if data: # merge file data for new in data: if new not in samples[name]: samples[name].append(new) for optional in optionals: data = self.load_resource(optional) if data: # merge file data for new in data: optionals[optional] = optionals[optional] or [] if new not in optionals[optional]: optionals[optional].append(new) for required in samples: for kw in samples[required]: self.adapt.register_entity(required, kw) intent.require(required) for optional in optionals: for kw in optionals[optional]: self.adapt.register_entity(optional, kw) intent.optionally(optional) self.adapt.register_intent_parser(intent.build()) self.intents[intent_name] = handler
def make_intents_struct(self, struct_list): # process new style intent for i18n intents = [] for struct in struct_list: # single language for i_inf in struct['utterances']: # intent info i_name = '{}{}Intent'.format(self.h_prefix, hash_sum(str(i_inf))) builder = IntentBuilder(i_name) for section in i_inf: section = ''.join(ch for ch in section if re.match(r'A-Za-z0-9:\|', ch)) entity_type = self.make_entity_type(section.split(':')[1]) if section.startswith('req:'): builder.require(entity_type) continue elif section.startswith('opt:'): builder.optionally(entity_type) continue elif section.startswith('one:'): entity_types = [ self.make_entity_type(e) for e in section.split(':')[1].split('|') ] builder.one_of(entity_types) continue else: # shouldn't be here self.log.error( 'Something wrong with the struct: {}'.format( struct)) intents.append(builder.build()) return intents
for intent in DOMTree.getElementsByTagName("intent"): builder = IntentBuilder(intent.attributes["name"].value) for node in intent.getElementsByTagName("keyword"): keyword = node.attributes["name"].value required = node.attributes["required"].value ktype = node.attributes["type"].value if ktype == 'normal': for child in node.getElementsByTagName("item"): engine.register_entity(child.childNodes[0].nodeValue, keyword) else: engine.register_regex_entity(node.childNodes[0].nodeValue) if required == 'true': builder.require(keyword) else: builder.optionally(keyword) engine.register_intent_parser(builder.build()) # create and register weather vocabulary '''weather_keyword = [ "weather" ] for wk in weather_keyword: engine.register_entity(wk, "WeatherKeyword") weather_types = [ "snow", "rain", "wind", "sleet", "sun"
from adapt.intent import IntentBuilder from adapt.engine import IntentDeterminationEngine engine = IntentDeterminationEngine() schema = json.loads(sys.argv[1]) for entity in schema["entities"]: if entity["type"] == "string": for value in entity["values"]: engine.register_entity(value, entity["name"]) elif entity["type"] == "regex": engine.register_regex_entity(entity["pattern"]) for intent in schema["intents"]: ib = IntentBuilder(intent["name"].encode("utf-8")) for requirement in intent["requirements"]: ib.require(requirement["entity"], requirement["attribute"]) for optional in intent["optionals"]: ib.optionally(optional["entity"], optional["attribute"]) engine.register_intent_parser(ib.build()) if __name__ == "__main__": while True: line = sys.stdin.readline() query = json.loads(line) intents = list(engine.determine_intent(query["input"])) response = {"intents": intents} print(json.dumps(response)) sys.stdout.flush()