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"], ), ], )
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, )
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"], ) ], )
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"], ) ], )
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"], ) ], )
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"], ) ], )
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)
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"], ) ], )
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)
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)
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"], ) ], )
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"], ) ], )
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]