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_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_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_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_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_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_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_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")
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")
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_word_case_preservation(self): """Ensure word casing is preserved in raw text.""" ini_text = """ [TestIntent] this is a (test){value} """ graph = intents_to_graph(parse_ini(ini_text)) recognitions = zero_times( recognize("this is a TEST", 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 test") self.assertEqual(recognition.raw_text, "this is a TEST") self.assertEqual(len(recognition.entities), 1) value = recognition.entities[0] self.assertEqual(value.entity, "value") self.assertEqual(value.value, "test") self.assertEqual(value.raw_value, "TEST")
def test_final_optional_entity(self): """Ensure final optional entity is matched.""" ini_text = """ [ChangeDisplay] display (top | bottom){location} [(page | layer){layout}] """ graph = intents_to_graph(parse_ini(ini_text)) recognitions = zero_times(recognize("display bottom layer", graph)) self.assertEqual(len(recognitions), 1) recognition = recognitions[0] self.assertIsNotNone(recognition.intent) entities = {e.entity: e for e in recognition.entities} self.assertIn("location", entities) location = entities["location"] self.assertEqual(location.value, "bottom") self.assertIn("layout", entities) layout = entities["layout"] self.assertEqual(layout.value, "layer")
def test_entity_converters_both(self): """Check sentence with an entity converter and a converter inside the entity.""" intents = parse_ini(""" [TestIntent] this is a test (four:4 point: two:2){number!floatify} """) graph = intents_to_graph(intents) # "four two" -> 4.2 recognitions = zero_times( recognize( "this is a test four point two", graph, fuzzy=False, extra_converters={ "floatify": lambda a, b: [float(f"{a}.{b}")] }, )) self.assertEqual(len(recognitions), 1) recognition = recognitions[0] self.assertTrue(recognition.intent) entities = {e.entity: e for e in recognition.entities} self.assertIn("number", entities) number = entities["number"] self.assertEqual(number.value, 4.2)
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")
def test_entity_converter(self): """Check sentence with an entity converter.""" intents = parse_ini(""" [TestIntent] this is a test (four: point: two:4.2){number!float} """) graph = intents_to_graph(intents) # "four point two" -> 4.2 recognitions = zero_times( recognize("this is a test four point two", 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("number", entities) number = entities["number"] self.assertEqual(number.value, 4.2)
def test_converters_in_entities(self): """Check sentence with converters inside an entity.""" intents = parse_ini(""" [TestIntent] this is a test (ten:10!int){number} """) graph = intents_to_graph(intents) # ten -> 10 (int) recognitions = zero_times( recognize("this is a test ten", 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("number", entities) number = entities["number"] self.assertEqual(number.value, 10)
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 test_strict_simple(self): """Check exact parse.""" recognitions = zero_times( recognize("set a timer for ten minutes", self.graph, fuzzy=False)) self.assertEqual(len(recognitions), 1) recognition = recognitions[0] self.assertTrue(recognition.intent) self.assertEqual( recognition.entities, [ Entity( entity="minutes", value="10", raw_value="ten", start=16, raw_start=16, raw_end=19, end=18, tokens=["10"], raw_tokens=["ten"], ) ], )