Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
8.1 kB · 170 lines
Python
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171import unittestfrom pathlib import Path
from sidecar import da_schema as schemafrom sidecar.classify import QUESTIONS, Utterance, build_state, classify, interpretfrom sidecar.config import load_settingsfrom sidecar.jev_client import ChoiceAnswer
SETTINGS = load_settings(env_path=Path("does-not-exist.env"), environ={})
def answer(choice, probability=0.9): return ChoiceAnswer(choice=choice, confidence=probability, probabilities={choice: probability})
def answers(**overrides): """A full answer set where nothing is detected unless overridden.""" base = {"act": answer(schema.OTHER_ACT), "addressee": answer("both")} for family in schema.FAMILIES.values(): base[family.name] = answer("none") if family.none_description else answer( next(iter(family.options)), probability=0.0) base.update(overrides) return base
class FakeClient: def __init__(self, canned): self.canned = canned self.calls = []
def decide(self, state, questions): self.calls.append((state, questions)) return self.canned
def real(result): """The acts other than the always-present SystemDoesntUnderstand fallback.""" return [a for a in result.acts if a.da_id != schema.SYSTEM_DOESNT_UNDERSTAND]
class InterpretTests(unittest.TestCase): def test_fallback_act_always_rides_last(self): result = interpret(answers(act=answer("agree")), SETTINGS) self.assertEqual([a.da_id for a in result.acts], [0, schema.SYSTEM_DOESNT_UNDERSTAND])
def test_reference_is_never_addressed(self): result = interpret(answers(reference=answer("couch"), addressee=answer("grace")), SETTINGS) self.assertEqual(real(result)[0].char_id, -1)
def test_simple_act_with_addressee(self): result = interpret(answers(act=answer("agree"), addressee=answer("grace")), SETTINGS) self.assertTrue(result.understood) self.assertEqual([(a.da_id, a.char_id, a.param1) for a in real(result)], [(0, 0, -1)])
def test_act_with_parameter(self): result = interpret(answers( act=answer("explain"), addressee=answer("trip"), explAdv=answer("controlling")), SETTINGS) act = result.acts[0] self.assertEqual((act.da_id, act.char_id, act.param1), (23, 1, 100))
def test_three_slot_act(self): result = interpret(answers( act=answer("explBig"), subject=answer("trip"), relation=answer("cheating"), object=answer("maria")), SETTINGS) act = result.acts[0] self.assertEqual((act.param1, act.param2, act.param3), (125, 128, 129))
def test_unsure_parameter_is_left_unset(self): result = interpret(answers(act=answer("express"), emotion=answer("sad", 0.2)), SETTINGS) self.assertEqual((result.acts[0].da_id, result.acts[0].param1), (5, -1))
def test_reference_rides_along_with_an_act(self): result = interpret(answers(act=answer("praise"), reference=answer("couch")), SETTINGS) self.assertEqual([(a.da_id, a.param1) for a in real(result)], [(11, -1), (10, 80)])
def test_reference_alone(self): result = interpret(answers(reference=answer("italyPicture")), SETTINGS) self.assertEqual([(a.da_id, a.param1, a.param2) for a in real(result)], [(10, 91, 147)])
def test_reference_carries_its_question_word(self): result = interpret(answers(reference=answer("italyPicture"), questionWord=answer("where")), SETTINGS) self.assertEqual([(a.da_id, a.param1, a.param2) for a in real(result)], [(10, 91, 145)])
def test_split_between_two_real_acts_picks_the_winner(self): # 'trip, stop': two good readings drag Jev's spread-based confidence # down, but it still picked a real act over "other". torn = ChoiceAnswer(choice="oppose", confidence=0.31, probabilities={"oppose": 0.51, "pacify": 0.33, "other": 0.02}) result = interpret(answers(act=torn, addressee=answer("trip")), SETTINGS) self.assertTrue(result.understood) self.assertEqual([(a.name, a.char_id) for a in real(result)], [("oppose", 1)])
def test_other_winning_a_split_still_deflects(self): lost = ChoiceAnswer(choice="other", confidence=0.3, probabilities={"other": 0.33, "getAttention": 0.27}) self.assertFalse(interpret(answers(act=lost), SETTINGS).understood)
def test_low_probability_act_deflects(self): result = interpret(answers(act=answer("flirt", 0.2)), SETTINGS) self.assertFalse(result.understood) self.assertEqual([a.da_id for a in result.acts], [schema.SYSTEM_DOESNT_UNDERSTAND])
def test_other_deflects(self): result = interpret(answers(), SETTINGS) self.assertEqual([a.da_id for a in result.acts], [schema.SYSTEM_DOESNT_UNDERSTAND])
class RequestShapeTests(unittest.TestCase): def test_every_family_and_the_core_questions_are_asked(self): questions = QUESTIONS self.assertEqual(set(questions), {"act", "addressee"} | set(schema.FAMILIES)) for question in questions.values(): self.assertEqual(question["type"], "choice") self.assertLessEqual(len(question["criteria"]), 255) self.assertIn(schema.OTHER_ACT, questions["act"]["criteria"]) self.assertNotIn("referTo", questions["act"]["criteria"])
def test_state_only_carries_what_is_known(self): self.assertEqual(set(build_state(Utterance("hi"))), {"scene", "player_said"}) full = build_state(Utterance("yes", contexts=("Context_GlobalMixIn", "Context_FAskDrink", "Context_Novel"), recent_dialogue=("TRIP: Drink?",))) self.assertEqual(full["trip_and_grace_just_said"], ["TRIP: Drink?"]) # Engine-mode contexts are dropped, known ones described, unknown passed through. self.assertEqual(len(full["what_is_happening"]), 2) self.assertIn("offering the player a drink", full["what_is_happening"][0]) self.assertEqual(full["what_is_happening"][1], "Context_Novel")
def test_lowercase_names_are_capitalised_for_jev(self): self.assertEqual(build_state(Utterance("trip stop"))["player_said"], "Trip stop") self.assertEqual(build_state(Utterance("what a trippy graceful place"))["player_said"], "what a trippy graceful place")
def test_an_empty_line_is_not_sent_to_jev(self): client = FakeClient(answers(act=answer("greet"))) result = classify(Utterance(" "), client, SETTINGS) self.assertEqual(client.calls, []) self.assertEqual([a.da_id for a in result.acts], [schema.SYSTEM_DOESNT_UNDERSTAND])
def test_classify_makes_one_round_trip(self): client = FakeClient(answers(act=answer("greet"))) result = classify(Utterance("hello"), client, SETTINGS) self.assertEqual(len(client.calls), 1) self.assertEqual(result.acts[0].da_id, 30)
class SchemaTests(unittest.TestCase): def test_act_ids_are_unique_text_acts(self): ids = [act.da_id for act in schema.ACTS.values()] self.assertEqual(len(ids), len(set(ids))) self.assertTrue(all(0 <= i <= 34 for i in ids)) self.assertNotIn(schema.REFER_TO, ids)
def test_slots_name_real_families(self): for act in schema.ACTS.values(): self.assertLessEqual(len(act.slots), 3) for family in act.slots: self.assertIn(family, schema.FAMILIES)
def test_family_ids_stay_in_their_datype_ranges(self): ranges = {"emotion": (54, 57), "reference": (59, 99), "explAdv": (100, 121), "relation": (123, 125), "subject": (127, 132), "object": (127, 132), "questionWord": (143, 148)} for name, (low, high) in ranges.items(): ids = [i for i, _ in schema.FAMILIES[name].options.values()] self.assertEqual(len(ids), len(set(ids)), name) self.assertTrue(all(low <= i <= high for i in ids), name)
if __name__ == "__main__": unittest.main()