class Core: def __init__(self): self.engine = DomainIntentDeterminationEngine() self.engine.register_regex_entity("(?P<Wildcard>.*)", domain="wildcard") self._intents = {} def add_skill(self, skill_class: Callable[[DomainIntentDeterminationEngine], QuiriSkill]): skill = skill_class(self.engine) methods = inspect.getmembers(skill, predicate=inspect.ismethod) for (name, method) in methods: if not hasattr(method, "_intents"): continue for intent in method._intents: skill.register_intent(intent, method) self._intents.update(skill._intents) async def process(self, q, context) -> str: try: intent = next(self.engine.determine_intent(q)) except StopIteration: return None query = Query(q, context, intent) intent_type = intent["intent_type"] skill = self._intents[intent_type] confidence = intent["confidence"] return (await skill(query)).build(intent_type, confidence)
class RegisterRegexEntityTests(unittest.TestCase): """All tests related to the DomainIntentDeterminationEngine.""" def setUp(self): """Setting up testing env.""" self.engine = DomainIntentDeterminationEngine() def test_register_regex_entity(self): """Test to make sure a regex entity can be registered.""" self.engine.register_regex_entity(".*") self.assertEqual(len(self.engine._regex_strings), 1) self.assertEqual(len(self.engine.regular_expressions_entities), 1) def test_register_regex_entity_default_is_empty(self): """Test to make sure that regex entity is empty by default.""" self.assertEqual(len(self.engine._regex_strings), 0) self.assertEqual(len(self.engine.regular_expressions_entities), 0)
class RegisterRegexEntityTests(unittest.TestCase): """All tests related to the DomainIntentDeterminationEngine.""" def setUp(self): """Setting up testing env.""" self.engine = DomainIntentDeterminationEngine() def test_register_regex_entity(self): """Test to make sure a regex entity can be registered.""" self.engine.register_regex_entity(".*") self.assertEqual(len(self.engine._regex_strings), 1) self.assertEqual(len(self.engine.regular_expressions_entities), 1) def test_register_regex_entity_default_is_empty(self): """Test to make sure that regex entity is empty by default.""" self.assertEqual(len(self.engine._regex_strings), 0) self.assertEqual(len(self.engine.regular_expressions_entities), 0)
class SelectBestIntentTests(unittest.TestCase): """All tests related to the DomainIntentDeterminationEngine.""" def setUp(self): """Setting up testing env.""" self.engine = DomainIntentDeterminationEngine() def test_select_best_intent(self): """ Test to make sure that best intent is being returned. This test is to make sure that best intent works identicly to its counter part in the IntentEngine. """ parser1 = IntentBuilder("Parser1").require("Entity1").build() self.engine.register_intent_parser(parser1) self.engine.register_entity("tree", "Entity1") utterance = "go to the tree house" intent = next(self.engine.determine_intent(utterance)) assert intent self.assertEqual(intent['intent_type'], 'Parser1') parser2 = IntentBuilder("Parser2").require("Entity1").require( "Entity2").build() self.engine.register_intent_parser(parser2) self.engine.register_entity("house", "Entity2") intent = next(self.engine.determine_intent(utterance)) assert intent self.assertEqual(intent['intent_type'], 'Parser2') def test_select_best_intent_with_domain(self): """Test to make sure that best intent is working with domains.""" self.engine.register_domain('Domain1') self.engine.register_domain('Domain2') # Creating first intent domain parser1 = IntentBuilder("Parser1").require("Entity1").build() self.engine.register_intent_parser(parser1, domain='Domain1') self.engine.register_entity("tree", "Entity1", domain='Domain1') # Creating second intent domain parser2 = IntentBuilder("Parser1").require("Entity2").build() self.engine.register_intent_parser(parser2, domain="Domain2") self.engine.register_entity("house", "Entity2", domain="Domain2") utterance = "Entity1 Entity2 go to the tree house" intents = self.engine.determine_intent(utterance, 2) intent = next(intents) assert intent self.assertEqual(intent['intent_type'], 'Parser1') intent = next(intents) assert intent self.assertEqual(intent['intent_type'], 'Parser1') def test_select_best_intent_enuse_enitities_dont_register_in_multiple_domains( self): """Test to make sure that 1 entity does not end up in multiple domains.""" self.engine.register_domain('Domain1') self.engine.register_domain('Domain2') # Creating first intent domain parser1 = IntentBuilder("Parser1").require("Entity1").build() self.engine.register_intent_parser(parser1, domain='Domain1') self.engine.register_entity("tree", "Entity1", domain='Domain1') # Creating second intent domain parser2 = IntentBuilder("Parser2").require("Entity2").build() self.engine.register_intent_parser(parser2, domain="Domain2") self.engine.register_entity("house", "Entity2", domain="Domain2") utterance = "go to the house" intents = self.engine.determine_intent(utterance, 1) for intent in intents: self.assertNotEqual(intent['intent_type'], 'Parser1') utterance = "go to the tree" intents = self.engine.determine_intent(utterance, 1) for intent in intents: self.assertNotEqual(intent['intent_type'], 'Parser2') def test_drop_intent_from_domain(self): """Test that intent is dropped from the correct domain.""" self.engine.register_domain('Domain1') self.engine.register_domain('Domain2') # Creating first intent domain parser1 = IntentBuilder("Parser1").require("Entity1").build() self.engine.register_intent_parser(parser1, domain='Domain1') self.engine.register_entity("tree", "Entity1", domain='Domain1') # Creating second intent domain parser2 = IntentBuilder("Parser2").require("Entity2").build() self.engine.register_intent_parser(parser2, domain="Domain2") self.engine.register_entity("house", "Entity2", domain="Domain2") self.engine.drop_intent_parser(domain="Domain2", parser_names=['Parser2']) self.assertEqual(len(self.engine.domains['Domain2'].intent_parsers), 0) def test_drop_entity_from_domain(self): """Test that entity is dropped from domain.""" self.engine.register_domain('Domain1') self.engine.register_domain('Domain2') # Creating first intent domain parser1 = IntentBuilder("Parser1").require("Entity1").build() self.engine.register_intent_parser(parser1, domain='Domain1') self.engine.register_entity("tree", "Entity1", domain='Domain1') # Creating second intent domain parser2 = IntentBuilder("Parser2").require("Entity2").build() self.engine.register_intent_parser(parser2, domain="Domain2") self.engine.register_entity("house", "Entity2", domain="Domain2") self.assertTrue( self.engine.drop_entity(domain="Domain2", entity_type='Entity2')) def testDropRegexEntity(self): self.engine.register_domain("Domain1") self.engine.register_domain("Domain2") self.engine.register_regex_entity(r"the dog (?P<Dog>.*)", "Domain1") self.engine.register_regex_entity(r"the cat (?P<Cat>.*)", "Domain2") self.assertTrue( self.engine.drop_regex_entity(domain='Domain2', entity_type='Cat')) self.assertFalse( self.engine.drop_regex_entity(domain='Domain1', entity_type='Cat'))
class _IntentParser: def __init__(self): self.engine = DomainIntentDeterminationEngine() self.exact_matches = {} # Load all files in ./intents matches = [] for root, dirnames, filenames in os.walk( os.path.join(os.path.dirname(__file__), 'intents')): for filename in fnmatch.filter(filenames, '*.json'): path = os.path.join(root, filename) matches.append(path) if len(matches) == 0: raise Exception("No intent specifications found at ", os.path.join(os.path.dirname(__file__), 'intents')) for path in matches: with open(path) as file: if not self.loadIntentSpec( root.split('/')[-1], json.load(file)): logging.warning( "Something went wrong during parsing of ", os.path.join(os.path.dirname(__file__), 'intents')) 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 parse(self, text, expected_intents=None): """ Returns best match for intent. """ tokenized = ' '.join(tokenize_string(text)).lower() if tokenized in self.exact_matches: return { 'intent_type': self.exact_matches[tokenized], 'confidence': 1.0, 'Keyword': tokenized } for intent in self.engine.determine_intent(text): if intent and intent.get('confidence') > 0.0: if expected_intents and intent.get( 'intent_type') in expected_intents: return intent elif not expected_intents: return intent else: continue return None