Exemple #1
0
    def test_rules(self):
        """Make sure local and remote rules work."""
        intents = parse_ini("""
        [Intent1]
        rule = a test
        this is <rule>

        [Intent2]
        rule = this is
        <rule> <Intent1.rule>
        """)

        graph = intents_to_graph(intents)

        # Lower confidence with no stop words
        recognitions = zero_times(recognize("this is a test", graph))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="Intent1", confidence=1.0),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                ),
                Recognition(
                    intent=Intent(name="Intent2", confidence=1.0),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                ),
            ],
        )
Exemple #2
0
    def test_multiple_sentences(self):
        """Identical sentences from two different intents."""
        intents = parse_ini("""
        [TestIntent1]
        this is a test

        [TestIntent2]
        this is a test
        """)

        graph = intents_to_graph(intents)

        # Should produce a recognition for each intent
        recognitions = zero_times(recognize("this is a test", graph))
        self.assertEqual(len(recognitions), 2)
        self.assertIn(
            Recognition(
                intent=Intent(name="TestIntent1", confidence=1.0),
                text="this is a test",
                raw_text="this is a test",
                tokens=["this", "is", "a", "test"],
                raw_tokens=["this", "is", "a", "test"],
            ),
            recognitions,
        )
        self.assertIn(
            Recognition(
                intent=Intent(name="TestIntent2", confidence=1.0),
                text="this is a test",
                raw_text="this is a test",
                tokens=["this", "is", "a", "test"],
                raw_tokens=["this", "is", "a", "test"],
            ),
            recognitions,
        )
Exemple #3
0
    def test_stop_words(self):
        """Check sentence with stop words."""
        intents = parse_ini("""
        [TestIntent]
        this is a test
        """)

        graph = intents_to_graph(intents)

        # Failure without stop words
        recognitions = zero_times(
            recognize("this is a abcd test", graph, fuzzy=False))
        self.assertFalse(recognitions)

        # Success with stop words
        recognitions = zero_times(
            recognize("this is a abcd test",
                      graph,
                      stop_words={"abcd"},
                      fuzzy=False))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )
Exemple #4
0
    def test_stop_words(self):
        """Check sentence with stop words."""
        intents = parse_ini("""
        [TestIntent]
        this is a test
        """)

        graph = intents_to_graph(intents)

        # Lower confidence with no stop words
        recognitions = zero_times(recognize("this is a abcd test", graph))
        self.assertEqual(len(recognitions), 1)
        self.assertEqual(recognitions[0].intent.confidence, 1 - (1 / 4))

        # Higher confidence with stop words
        recognitions = zero_times(
            recognize("this is a abcd test", graph, stop_words={"abcd"}))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent",
                                  confidence=float(1 - (0.1 / 4))),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )
Exemple #5
0
    def test_intent_filter(self):
        """Identical sentences from two different intents with filter."""
        intents = parse_ini("""
        [TestIntent1]
        this is a test

        [TestIntent2]
        this is a test
        """)

        graph = intents_to_graph(intents)

        def intent_filter(name):
            return name == "TestIntent1"

        # Should produce a recognition for first intent only
        recognitions = zero_times(
            recognize("this is a test", graph, intent_filter=intent_filter))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent1", confidence=1.0),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )
Exemple #6
0
    def test_converter_args(self):
        """Check converter with arguments."""
        intents = parse_ini("""
        [TestIntent]
        this is a test ten:10!int!pow,3
        """)

        graph = intents_to_graph(intents)

        def pow_converter(*args, converter_args=None):
            exponent = int(converter_args[0]) if converter_args else 1
            return [x**exponent for x in args]

        # Should convert "ten" -> 10 -> 1000
        recognitions = zero_times(
            recognize(
                "this is a test ten",
                graph,
                fuzzy=False,
                extra_converters={"pow": pow_converter},
            ))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this is a test 1000",
                    raw_text="this is a test ten",
                    tokens=["this", "is", "a", "test", 1000],
                    raw_tokens=["this", "is", "a", "test", "ten"],
                )
            ],
        )
Exemple #7
0
    def test_single_sentence(self):
        """Single intent, single sentence."""
        intents = parse_ini("""
        [TestIntent]
        this is a test
        """)

        graph = intents_to_graph(intents)

        # Exact
        recognitions = zero_times(
            recognize("this is a test", graph, fuzzy=False))
        print(recognitions)
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this is a test",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )

        # Too many tokens (lower confidence)
        recognitions = zero_times(
            recognize("this is a bad test", graph, fuzzy=False))
        self.assertFalse(recognitions)

        # Too few tokens (failure)
        recognitions = zero_times(recognize("this is a", graph, fuzzy=False))
        self.assertFalse(recognitions)
Exemple #8
0
    def test_converters(self):
        """Check sentence with converters."""
        intents = parse_ini("""
        [TestIntent]
        this is a test!upper ten:10!int!square
        """)

        graph = intents_to_graph(intents)

        # Should upper-case "test" and convert "ten" -> 10 -> 100
        recognitions = zero_times(
            recognize(
                "this is a test ten",
                graph,
                fuzzy=False,
                extra_converters={
                    "square": lambda *args: [x**2 for x in args]
                },
            ))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this is a TEST 100",
                    raw_text="this is a test ten",
                    tokens=["this", "is", "a", "TEST", 100],
                    raw_tokens=["this", "is", "a", "test", "ten"],
                )
            ],
        )
Exemple #9
0
    def test_single_sentence(self):
        """Single intent, single sentence."""
        intents = parse_ini("""
        [TestIntent]
        this is a test?
        """)

        graph = intents_to_graph(intents)
        examples = train(graph)

        # Exact
        recognitions = zero_times(recognize("this is a test", graph, examples))

        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1),
                    text="this is a test?",
                    raw_text="this is a test",
                    tokens=["this", "is", "a", "test?"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )

        # Mispellings, too many tokens (lower confidence)
        for sentence in ["this is a bad test", "this iz b tst"]:
            recognitions = zero_times(recognize(sentence, graph, examples))
            self.assertEqual(len(recognitions), 1)

            intent = recognitions[0].intent
            self.assertIsNotNone(intent)
            self.assertLess(intent.confidence, 1.0)
Exemple #10
0
    def test_evaluate_perfect(self):
        """Test intent evaluation with a perfect match."""
        expected = {
            "test1": Recognition(
                intent=Intent(name="TestIntent"),
                entities=[Entity(entity="testEntity", value="testValue")],
                text="this is a test",
            )
        }

        actual = expected
        report = evaluate_intents(expected, actual)

        self.assertEqual(1, report.num_wavs)
        self.assertEqual(1, report.num_intents)
        self.assertEqual(1, report.num_entities)

        self.assertEqual(1, report.correct_intent_names)
        self.assertEqual(1, report.correct_entities)
        self.assertEqual(1, report.correct_intent_and_entities)
Exemple #11
0
    def test_sequence_converters(self):
        """Check sentence with sequence converters."""
        intents = parse_ini("""
        [TestIntent]
        this (is a test)!upper
        """)

        graph = intents_to_graph(intents)

        # Should upper-case "is a test"
        recognitions = zero_times(
            recognize("this is a test", graph, fuzzy=False))
        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this IS A TEST",
                    raw_text="this is a test",
                    tokens=["this", "IS", "A", "TEST"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )
Exemple #12
0
    def test_drop_group(self):
        """Test dropping a group."""
        intents = parse_ini("""
        [TestIntent]
        this is (a | another): test
        """)

        graph = intents_to_graph(intents)

        recognitions = zero_times(
            recognize("this is a test", graph, fuzzy=False))

        self.assertEqual(
            recognitions,
            [
                Recognition(
                    intent=Intent(name="TestIntent", confidence=1.0),
                    text="this is test",
                    raw_text="this is a test",
                    tokens=["this", "is", "test"],
                    raw_tokens=["this", "is", "a", "test"],
                )
            ],
        )
Exemple #13
0
def recognize(
    text: str,
    engine: SnipsNLUEngine,
    slots_dict: typing.Optional[typing.Dict[str, typing.List[str]]] = None,
    slot_graphs: typing.Optional[typing.Dict[str, nx.DiGraph]] = None,
    **parse_args,
) -> typing.List[Recognition]:
    """Recognize intent using Snips NLU."""
    result = engine.parse(text, **parse_args)
    intent_name = result.get("intent", {}).get("intentName")

    if not intent_name:
        # Recognition failure
        return []

    slots_dict = slots_dict or {}
    slot_graphs = slot_graphs or {}

    recognition = Recognition(text=text,
                              raw_text=text,
                              intent=Intent(name=intent_name, confidence=1.0))

    # Replace Snips slot values with Rhasspy slot values (substituted)
    for slot in result.get("slots", []):
        slot_name = slot.get("slotName")
        slot_value_dict = slot.get("value", {})
        slot_value = slot_value_dict.get("value")

        entity = Entity(
            entity=slot_name,
            source=slot.get("entity", ""),
            value=slot_value,
            raw_value=slot.get("rawValue", slot_value),
            start=slot["range"]["start"],
            end=slot["range"]["end"],
        )
        recognition.entities.append(entity)

        if (not slot_name) or (not slot_value):
            continue

        slot_graph = slot_graphs.get(slot_name)
        if not slot_graph and (slot_name in slots_dict):
            # Convert slot values to graph
            slot_graph = rhasspynlu.sentences_to_graph({
                slot_name: [
                    rhasspynlu.jsgf.Sentence.parse(slot_line)
                    for slot_line in slots_dict[slot_name]
                    if slot_line.strip()
                ]
            })

            slot_graphs[slot_name] = slot_graph

        entity.tokens = slot_value.split()
        entity.raw_tokens = list(entity.tokens)

        if slot_graph:
            # Pass Snips value through graph
            slot_recognitions = rhasspynlu.recognize(entity.tokens, slot_graph)
            if slot_recognitions:
                # Pull out substituted value and replace in Rhasspy entitiy
                new_slot_value = slot_recognitions[0].text
                entity.value = new_slot_value
                entity.tokens = new_slot_value.split()

    return [recognition]