Ejemplo n.º 1
0
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
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'))
Ejemplo n.º 5
0
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