Beispiel #1
0
    def test_optional_entity(self):
        """Ensure entity inside optional is recognized."""
        ini_text = """
        [playBook]
        read me ($audio-book-name){book} in [the] [($assistant-zones){zone}]
        """

        replacements = {
            "$audio-book-name":
            [Sentence.parse("the hound of the baskervilles")],
            "$assistant-zones": [Sentence.parse("bedroom")],
        }

        graph = intents_to_graph(parse_ini(ini_text), replacements)

        recognitions = zero_times(
            recognize(
                "read me the hound of the baskervilles in the bedroom",
                graph,
                fuzzy=False,
            ))
        self.assertEqual(len(recognitions), 1)
        recognition = recognitions[0]
        self.assertTrue(recognition.intent)

        entities = {e.entity: e for e in recognition.entities}
        self.assertIn("book", entities)
        book = entities["book"]
        self.assertEqual(book.value, "the hound of the baskervilles")

        self.assertIn("zone", entities)
        zone = entities["zone"]
        self.assertEqual(zone.value, "bedroom")
Beispiel #2
0
    def test_walk(self):
        """Test Expression.walk with rule and slot reference."""
        ini_text = """
        [SetAlarm]
        minutes = $minute minutes
        set alarm for <minutes>
        """

        intents = parse_ini(ini_text)
        sentences, replacements = split_rules(intents)
        replacements["$minute"] = [Sentence.parse("2 | 3")]

        def num2words(word):
            if not isinstance(word, Word):
                return

            try:
                n = int(word.text)
                if n == 2:
                    word.text = "two"
                    word.substitution = "2"
                elif n == 3:
                    word.text = "three"
                    word.substitution = "3"
            except ValueError:
                pass

        for s in sentences["SetAlarm"]:
            walk_expression(s, num2words, replacements)

        # Verify minute digits were replaced
        minute = replacements["$minute"][0]
        self.assertEqual(
            minute,
            Sentence(
                text="2 | 3",
                type=SequenceType.GROUP,
                items=[
                    Sequence(
                        text="2 | 3",
                        type=SequenceType.ALTERNATIVE,
                        items=[
                            Word("two", substitution="2"),
                            Word("three", substitution="3"),
                        ],
                    )
                ],
            ),
        )
Beispiel #3
0
 def test_words(self):
     """Basic word sequence."""
     s = Sentence.parse("this is a test")
     self.assertEqual(
         s.items,
         [Word("this"), Word("is"),
          Word("a"), Word("test")])
Beispiel #4
0
    def test_escape(self):
        """Test escaped optional."""
        ini_text = """
        [TestIntent1]
        \\[this] is a test
        """

        intents = parse_ini(ini_text)
        self.assertEqual(
            intents,
            {
                "TestIntent1": [
                    Sentence(
                        text="[this] is a test",
                        items=[
                            Sequence(
                                text="this",
                                type=SequenceType.ALTERNATIVE,
                                items=[Word("this"), Word("")],
                            ),
                            Word("is"),
                            Word("a"),
                            Word("test"),
                        ],
                    )
                ]
            },
        )
Beispiel #5
0
 def test_nested_optionals(self):
     """Optional inside an optional."""
     s = Sentence.parse("this [[is] a] test")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="[is] a",
                 type=SequenceType.ALTERNATIVE,
                 items=[
                     Sequence(
                         text="[is] a",
                         type=SequenceType.GROUP,
                         items=[
                             Sequence(
                                 text="is",
                                 type=SequenceType.ALTERNATIVE,
                                 items=[Word("is"), Word("")],
                             ),
                             Word("a"),
                         ],
                     ),
                     Word(""),
                 ],
             ),
             Word("test"),
         ],
     )
Beispiel #6
0
    def test_intent_filter(self):
        """Test filtering intents."""
        ini_text = """
        [TestIntent1]
        this is a test

        [TestIntent2]
        this is another test
        """

        intents = parse_ini(ini_text,
                            intent_filter=lambda n: n != "TestIntent2")
        self.assertEqual(
            intents,
            {
                "TestIntent1": [
                    Sentence(
                        text="this is a test",
                        items=[
                            Word("this"),
                            Word("is"),
                            Word("a"),
                            Word("test")
                        ],
                    )
                ]
            },
        )
Beispiel #7
0
 def test_slot_reference(self):
     """Basic slot reference."""
     s = Sentence.parse("this $is-a test")
     self.assertEqual(
         s.items,
         [Word("this"), SlotReference(text="$is-a", slot_name="is-a"), Word("test")],
     )
Beispiel #8
0
 def test_tag_word(self):
     """Tag a word."""
     s = Sentence.parse("this{is} a{test}")
     self.assertEqual(
         s.items,
         [Word("this", tag=Tag(tag_text="is")), Word("a", tag=Tag(tag_text="test"))],
     )
Beispiel #9
0
 def test_tagged_group_in_optional(self):
     """Tagged group inside an optional."""
     s = Sentence.parse("this is a [($test){tag}]")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Word("is"),
             Word("a"),
             Sequence(
                 text="($test){tag}",
                 type=SequenceType.ALTERNATIVE,
                 items=[
                     Sequence(
                         text="$test",
                         type=SequenceType.GROUP,
                         tag=Tag(tag_text="tag"),
                         items=[
                             SlotReference(slot_name="test", text="$test")
                         ],
                     ),
                     Word(""),
                 ],
             ),
         ],
     )
Beispiel #10
0
 def test_sequence_substition_in_alternative(self):
     """Test sequence substitution inside an alternative."""
     s = Sentence.parse(
         "((light one):light_1 | (light two):light_2) {name} :domain{light}"
     )
     self.assertEqual(
         s.items,
         [
             Sequence(
                 text="(light one):light_1 | (light two):light_2",
                 type=SequenceType.ALTERNATIVE,
                 tag=Tag(tag_text="name"),
                 items=[
                     Sequence(
                         text="light one",
                         substitution="light_1",
                         type=SequenceType.GROUP,
                         items=[Word("light"), Word("one")],
                     ),
                     Sequence(
                         text="light two",
                         substitution="light_2",
                         type=SequenceType.GROUP,
                         items=[Word("light"), Word("two")],
                     ),
                 ],
             ),
             Word(text="", substitution="domain", tag=Tag(tag_text="light")),
         ],
     )
Beispiel #11
0
 def test_den_overhead(self):
     """Sequence of optionals/alternatives plus tag substitution."""
     s = Sentence.parse(
         "toggle [the] (den | playroom) [light] {light_name:den_overhead}")
     self.assertEqual(
         s.items,
         [
             Word("toggle"),
             Sequence(
                 text="the",
                 type=SequenceType.ALTERNATIVE,
                 items=[Word("the"), Word("")],
             ),
             Sequence(
                 text="den | playroom",
                 type=SequenceType.GROUP,
                 items=[
                     Sequence(
                         text="den | playroom",
                         type=SequenceType.ALTERNATIVE,
                         items=[Word("den"), Word("playroom")],
                     )
                 ],
             ),
             Sequence(
                 text="light",
                 type=SequenceType.ALTERNATIVE,
                 items=[Word("light"), Word("")],
                 tag=Tag(tag_text="light_name",
                         substitution="den_overhead"),
             ),
         ],
     )
Beispiel #12
0
    def test_slot_case_inside_substitution(self):
        """Ensure word casing doesn't interfere with group substitution."""
        ini_text = """
        [TestIntent]
        this is a ($test){value}
        """

        replacements = {
            "$test": [Sentence.parse("(Bar:bar | Baz:baz):barorbaz")]
        }
        graph = intents_to_graph(parse_ini(ini_text), replacements)

        recognitions = zero_times(
            recognize("this is a bar",
                      graph,
                      fuzzy=False,
                      word_transform=str.lower))
        self.assertEqual(len(recognitions), 1)
        recognition = recognitions[0]
        self.assertIsNotNone(recognition.intent)

        # Check sequence substitution
        self.assertEqual(recognition.text, "this is a barorbaz")
        self.assertEqual(recognition.raw_text, "this is a bar")

        self.assertEqual(len(recognition.entities), 1)
        value = recognition.entities[0]
        self.assertEqual(value.entity, "value")
        self.assertEqual(value.value, "barorbaz")
        self.assertEqual(value.raw_value, "bar")
        self.assertEqual(value.source, "test")
Beispiel #13
0
    def test_slot_sequence_replacement(self):
        """Ensure word sequences in slots can be replaced."""
        ini_text = """
        [PlayMusic]
        play me ($music_genre){genre}
        """

        replacements = {
            "$music_genre": [
                Sentence.parse("(rock | hard rock):(Hard Rock)"),
                Sentence.parse("classical:(Classical Music)"),
            ]
        }
        graph = intents_to_graph(parse_ini(ini_text), replacements)

        for text in ["play me rock", "play me hard rock"]:
            recognitions = zero_times(recognize(text, graph, fuzzy=False))
            self.assertEqual(len(recognitions), 1)
            recognition = recognitions[0]
            self.assertIsNotNone(recognition.intent)

            # Check sequence substitution
            self.assertEqual(recognition.text, "play me Hard Rock")

            # Check entity source
            self.assertEqual(len(recognition.entities), 1)
            genre = recognition.entities[0]
            self.assertEqual(genre.source, "music_genre")

        recognitions = zero_times(
            recognize("play me classical", graph, fuzzy=False))
        self.assertEqual(len(recognitions), 1)
        recognition = recognitions[0]
        self.assertIsNotNone(recognition.intent)

        # Check sequence substitution
        self.assertEqual(recognition.text, "play me Classical Music")

        # Check entity source
        self.assertEqual(len(recognition.entities), 1)
        genre = recognition.entities[0]
        self.assertEqual(genre.source, "music_genre")
Beispiel #14
0
 def test_entity_converters(self):
     """Test multiple converters on a tag/entity"""
     s = Sentence.parse("this is a{test!c1!c2}")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Word("is"),
             Word("a", tag=Tag(tag_text="test", converters=["c1", "c2"])),
         ],
     )
Beispiel #15
0
 def test_word_substitution(self):
     """Single word substitutions."""
     s = Sentence.parse("this: :is a:test")
     self.assertEqual(
         s.items,
         [
             Word("this", substitution=""),
             Word("", substitution="is"),
             Word("a", substitution="test"),
         ],
     )
Beispiel #16
0
 def test_word_converters(self):
     """Test multiple converters on a single word"""
     s = Sentence.parse("this is a test!c1!c2")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Word("is"),
             Word("a"),
             Word("test", converters=["c1", "c2"]),
         ],
     )
Beispiel #17
0
    def test_rule_reference(self):
        """Basic rule references."""
        s = Sentence.parse("this <is-a> test")
        self.assertEqual(
            s.items,
            [
                Word("this"),
                RuleReference(text="<is-a>", rule_name="is-a"),
                Word("test"),
            ],
        )

        s = Sentence.parse("this <is.a> test")
        self.assertEqual(
            s.items,
            [
                Word("this"),
                RuleReference(text="<is.a>", grammar_name="is", rule_name="a"),
                Word("test"),
            ],
        )
Beispiel #18
0
    def test_parse(self):
        """Test ini/JSGF parser."""
        ini_text = """
        [TestIntent1]
        this is a test

        [TestIntent2]
        this is another test
        """

        intents = parse_ini(ini_text)
        self.assertEqual(
            intents,
            {
                "TestIntent1": [
                    Sentence(
                        text="this is a test",
                        items=[
                            Word("this"),
                            Word("is"),
                            Word("a"),
                            Word("test")
                        ],
                    )
                ],
                "TestIntent2": [
                    Sentence(
                        text="this is another test",
                        items=[
                            Word("this"),
                            Word("is"),
                            Word("another"),
                            Word("test")
                        ],
                    )
                ],
            },
        )
Beispiel #19
0
 def test_optional(self):
     """Basic optional."""
     s = Sentence.parse("this is [a] test")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Word("is"),
             Sequence(text="a",
                      type=SequenceType.ALTERNATIVE,
                      items=[Word("a"), Word("")]),
             Word("test"),
         ],
     )
Beispiel #20
0
 def test_optional_alternative(self):
     """Combined optional and alternative."""
     s = Sentence.parse("this [is | a] test")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is | a",
                 type=SequenceType.ALTERNATIVE,
                 items=[Word("is"), Word("a"), Word("")],
             ),
             Word("test"),
         ],
     )
Beispiel #21
0
 def test_alternative(self):
     """Basic alternative."""
     s = Sentence.parse("this (is | a) test")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is | a",
                 type=SequenceType.ALTERNATIVE,
                 items=[Word("is"), Word("a")],
             ),
             Word("test"),
         ],
     )
Beispiel #22
0
 def test_tag_alternative(self):
     """Tag an alternative."""
     s = Sentence.parse("[this is a]{test}")
     self.assertEqual(s.tag, Tag(tag_text="test"))
     self.assertEqual(
         s.items,
         [
             Sequence(
                 text="this is a",
                 type=SequenceType.GROUP,
                 items=[Word("this"), Word("is"), Word("a")],
             ),
             Word(""),
         ],
     )
Beispiel #23
0
 def test_sequence_converters(self):
     """Test multiple converters on a sequence"""
     s = Sentence.parse("this (is a test)!c1!c2")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is a test",
                 type=SequenceType.GROUP,
                 items=[Word("is"), Word("a"),
                        Word("test")],
                 converters=["c1", "c2"],
             ),
         ],
     )
Beispiel #24
0
 def test_substitution_and_converters(self):
     """Test substitution and converters on a sequence"""
     s = Sentence.parse("this (is a):test!c1!c2")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is a",
                 type=SequenceType.GROUP,
                 items=[Word("is"), Word("a")],
                 substitution="test",
                 converters=["c1", "c2"],
             ),
         ],
     )
Beispiel #25
0
    def test_final_optional_entity(self):
        """Ensure final optional entity has tag."""

        ini_text = """
        [ChangeDisplay]
        display [(page | layer){layout}]
        """

        intents = parse_ini(ini_text)
        self.assertEqual(
            intents,
            {
                "ChangeDisplay": [
                    Sentence(
                        text="display [(page | layer){layout}]",
                        items=[
                            Word("display"),
                            Sequence(
                                text="(page | layer){layout}",
                                type=SequenceType.ALTERNATIVE,
                                items=[
                                    Sequence(
                                        text="page | layer",
                                        type=SequenceType.GROUP,
                                        tag=Tag(tag_text="layout"),
                                        items=[
                                            Sequence(
                                                text="page | layer",
                                                type=SequenceType.ALTERNATIVE,
                                                items=[
                                                    Word("page"),
                                                    Word("layer")
                                                ],
                                            )
                                        ],
                                    ),
                                    Word(""),
                                ],
                            ),
                        ],
                    )
                ]
            },
        )
Beispiel #26
0
    def test_walk(self):
        """Test walk_expression."""
        s = Sentence.parse("set alarm for (2 | 3) minutes")

        def num2words(word):
            if not isinstance(word, Word):
                return

            try:
                n = int(word.text)
                if n == 2:
                    word.text = "two"
                    word.substitution = "2"
                elif n == 3:
                    word.text = "three"
                    word.substitution = "3"
            except ValueError:
                pass

        walk_expression(s, num2words)
        self.assertEqual(
            s.items,
            [
                Word("set"),
                Word("alarm"),
                Word("for"),
                Sequence(
                    text="2 | 3",
                    type=SequenceType.GROUP,
                    items=[
                        Sequence(
                            text="2 | 3",
                            type=SequenceType.ALTERNATIVE,
                            items=[
                                Word("two", substitution="2"),
                                Word("three", substitution="3"),
                            ],
                        )
                    ],
                ),
                Word("minutes"),
            ],
        )
Beispiel #27
0
 def test_implicit_sequence_with_rule(self):
     """Implicit sequence around alternative with a rule reference."""
     s = Sentence.parse("this | is a <test>")
     self.assertEqual(s.type, SequenceType.ALTERNATIVE)
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is a <test>",
                 type=SequenceType.GROUP,
                 items=[
                     Word("is"),
                     Word("a"),
                     RuleReference(text="<test>", rule_name="test"),
                 ],
             ),
         ],
     )
Beispiel #28
0
 def test_implicit_sequences(self):
     """Implicit sequences around alternative."""
     s = Sentence.parse("this is | a test")
     self.assertEqual(s.type, SequenceType.ALTERNATIVE)
     self.assertEqual(
         s.items,
         [
             Sequence(
                 text="this is",
                 type=SequenceType.GROUP,
                 items=[Word("this"), Word("is")],
             ),
             Sequence(
                 text="a test",
                 type=SequenceType.GROUP,
                 items=[Word("a"), Word("test")],
             ),
         ],
     )
Beispiel #29
0
 def test_alternative_substitution(self):
     """Alternative substitution."""
     s = Sentence.parse("this [is a]:isa test")
     self.assertEqual(
         s.items,
         [
             Word("this"),
             Sequence(
                 text="is a",
                 type=SequenceType.ALTERNATIVE,
                 substitution="isa",
                 items=[
                     Sequence(
                         text="is a",
                         type=SequenceType.GROUP,
                         items=[Word("is"), Word("a")],
                     ),
                     Word(""),
                 ],
             ),
             Word("test"),
         ],
     )
Beispiel #30
0
    def test_walk_multiple_words(self):
        """Test walk_expression with a multi-word replacement."""
        s = Sentence.parse("set alarm for 23 minutes")

        def num2words(word):
            if not isinstance(word, Word):
                return

            try:
                n = int(word.text)
                if n == 23:
                    return Sequence(
                        text="23",
                        type=SequenceType.GROUP,
                        items=[Word("twenty"), Word("three")],
                        substitution="23",
                    )
            except ValueError:
                pass

        walk_expression(s, num2words)
        self.assertEqual(
            s.items,
            [
                Word("set"),
                Word("alarm"),
                Word("for"),
                Sequence(
                    text="23",
                    type=SequenceType.GROUP,
                    items=[Word("twenty"), Word("three")],
                    substitution="23",
                ),
                Word("minutes"),
            ],
        )