def test_unexpected_input_macro(): df = DialogueFlow("root", initial_speaker=Speaker.USER) df.add_user_transition("root", "x", "#UNX") df.add_system_transition("x", "y", '"So, whats for dinner?"') df.user_turn("blah blah blah blah blah blah") tokens = df.system_turn().split() assert len(tokens) > 4 and "So, whats for dinner?" == " ".join(tokens[-4:])
def test_user_transition_list_disjunction(): df = DialogueFlow("root", initial_speaker=Speaker.USER) nlu = ["hello", "hi", "how are you"] df.add_user_transition("root", "x", nlu) df.update_state_settings("root", error_successor="y") df.user_turn("hi") assert df.state() == "x"
def test_unexpected_input_macro(): df = DialogueFlow('root', initial_speaker=Speaker.USER) df.add_user_transition('root', 'x', '#UNX') df.add_system_transition('x', 'y', '"So, whats for dinner?"') df.user_turn('blah blah blah blah blah blah') tokens = df.system_turn().split() assert len(tokens) > 4 and 'So, whats for dinner?' == ' '.join(tokens[-4:])
def test_user_transition_list_disjunction(): df = DialogueFlow('root', initial_speaker=Speaker.USER) nlu = [ 'hello', 'hi', 'how are you' ] df.add_user_transition('root', 'x', nlu) df.update_state_settings('root', error_successor='y') df.user_turn('hi') assert df.state() == 'x'
def test_transitions_to_transitions(): df = DialogueFlow("root", initial_speaker=Speaker.SYSTEM) transitions = { "state": "root", '"Hello World!"': {"state": "state_2", "error": {'"Hi,"': "root->state_2"}}, } df.load_transitions(transitions, speaker=Speaker.SYSTEM) assert df.system_turn() == "Hello World!" df.user_turn("blah") assert df.system_turn() == "Hi, Hello World!"
def __init__(self, initial_state, system_error_state, user_error_state, initial_speaker=DialogueFlow.Speaker.SYSTEM, macros=None, kb=None): if isinstance(system_error_state, str): system_error_state = ('SYSTEM', system_error_state) if isinstance(user_error_state, str): user_error_state = ('SYSTEM', user_error_state) # the dialogue flow currently controlling the conversation self._controller = DialogueFlow(initial_state, initial_speaker, macros, kb) self._controller_name = 'SYSTEM' # namespace : dialogue flow mapping self._components = {} self.add_component(self._controller, 'SYSTEM') self._system_error_state = system_error_state self._user_error_state = user_error_state
def test_transitions_to_transitions(): df = DialogueFlow('root', initial_speaker=Speaker.SYSTEM) transitions = { 'state': 'root', '"Hello World!"': { 'state': 'state_2', 'error': { '"Hi,"': 'root->state_2' } } } df.load_transitions(transitions, speaker=Speaker.SYSTEM) assert df.system_turn() == 'Hello World!' df.user_turn('blah') assert df.system_turn() == 'Hi, Hello World!'
def test_virtual_transitions_cross_module(): df = DialogueFlow('root') transitions = { 'state': 'root', 'hello': { 'state': 'test', 'a': {'something typical'}, '#VT(two:other)': 'blah' } } df.load_transitions(transitions) df2 = DialogueFlow('r2') transitions2 = { 'not taken': { 'state': 'other', 'score': 0, 'x': { 'you win': { 'state': 'success' } }, 'y': { 'you win': { 'state': 'success' } } } } df2.load_transitions(transitions2) cdf = CompositeDialogueFlow('one:root', 'e', 'e') cdf.add_component(df, 'one') cdf.add_component(df2, 'two') cdf.set_state('one:root') cdf.system_turn() assert cdf.state() == ('one', 'test') cdf.user_turn('x', debugging=True) assert cdf.system_turn() == 'you win' assert cdf.state() == ('two', 'success')
def test_virtual_transitions_cross_module(): df = DialogueFlow("root") transitions = { "state": "root", "hello": { "state": "test", "a": {"something typical"}, "#VT(two:other)": "blah", }, } df.load_transitions(transitions) df2 = DialogueFlow("r2") transitions2 = { "not taken": { "state": "other", "score": 0, "x": { "you win": { "state": "success" } }, "y": { "you win": { "state": "success" } }, } } df2.load_transitions(transitions2) cdf = CompositeDialogueFlow("one:root", "e", "e") cdf.add_component(df, "one") cdf.add_component(df2, "two") cdf.set_state("one:root") cdf.system_turn() assert cdf.state() == ("one", "test") cdf.user_turn("x", debugging=True) assert cdf.system_turn() == "you win" assert cdf.state() == ("two", "success")
def test_user_transition(): df = DialogueFlow(States.B) df.add_user_transition(States.B, States.C, "[{hi, hello, hey, [how, you]}]") df.add_user_transition(States.B, States.D, "[{bye, goodbye, see you, see ya, later}]") assert df.user_transition("oh hey there", df.state()) == States.C assert df.user_transition("well see ya later", df.state()) == States.D
class CompositeDialogueFlow: def __init__( self, initial_state, system_error_state, user_error_state, initial_speaker=DialogueFlow.Speaker.SYSTEM, macros=None, kb=None, ): if isinstance(system_error_state, str): system_error_state = ("SYSTEM", system_error_state) if isinstance(user_error_state, str): user_error_state = ("SYSTEM", user_error_state) # the dialogue flow currently controlling the conversation self._controller = DialogueFlow(initial_state, initial_speaker, macros, kb) self._controller_name = "SYSTEM" # namespace : dialogue flow mapping self._components = {} self.add_component(self._controller, "SYSTEM") self._system_error_state = system_error_state self._user_error_state = user_error_state def run(self, debugging=False): """ test in interactive mode :return: None """ while True: if self.controller().speaker() == DialogueFlow.Speaker.SYSTEM: t1 = time() response = self.system_turn(debugging=debugging) if debugging: print("System turn in {:5}".format(time() - t1)) print("S:", response) else: user_input = input("U: ") t1 = time() self.user_turn(user_input, debugging=debugging) if debugging: print("User turn in {:5}".format(time() - t1)) def system_turn(self, debugging=False): """ an entire system turn comprising a single system utterance and one or more system transitions :return: the natural language system response """ visited = {self._controller.state()} self.controller().vars()["__goal_return_state__"] = "None" responses = [] while self.controller().speaker() is DialogueFlow.Speaker.SYSTEM: try: response, next_state = self.controller().system_transition( self.controller().state(), debugging=debugging) assert next_state is not None self.controller().set_state(next_state) except Exception as e: print() print(e) print( "Error in CompositeDialogueFlow. Component: {} State: {}". format(self.controller_name(), self.controller().state())) traceback.print_exc(file=sys.stdout) response, next_state = "", self._system_error_state visited = visited - {next_state} if isinstance(next_state, tuple): self.set_control(*next_state) responses.append(response) if next_state in visited or not self.state_settings( *self.state()).system_multi_hop: self.controller().set_speaker(DialogueFlow.Speaker.USER) visited.add(next_state) full_response = " ".join(responses) self.controller().vars()["__selected_response__"] = full_response return full_response def user_turn(self, natural_language, debugging=False): """ an entire user turn comprising one user utterance and one or more user transitions :param natural_language: :param debugging: :return: None """ self.controller().vars()["__user_utterance__"] = natural_language try: self.controller().apply_update_rules(natural_language, debugging=debugging) next_state = self.controller().state() except Exception as e: print() print(e) print("Error in CompositeDialogueFlow. Component: {} State: {}". format(self._controller_name, self.controller().state())) traceback.print_exc(file=sys.stdout) next_state = self._user_error_state visited = {self.controller().state()} while self.controller().speaker() is DialogueFlow.Speaker.USER: try: next_state = self.controller().user_transition( natural_language, self.controller().state(), debugging=debugging) assert next_state is not None self.controller().set_state(next_state) except Exception as e: print() print(e) print( "Error in CompositeDialogueFlow. Component: {} State: {}". format(self._controller_name, self.controller().state())) traceback.print_exc(file=sys.stdout) next_state = self._user_error_state next_state = module_state(next_state) if isinstance(next_state, tuple): self.set_control(*next_state) if self.state_settings(*self.state()).user_multi_hop: self.controller().apply_update_rules(natural_language, debugging=debugging) if next_state in visited or not self.state_settings( *self.state()).user_multi_hop: self.controller().set_speaker(DialogueFlow.Speaker.SYSTEM) visited.add(next_state) next_state = module_state(next_state) if isinstance(next_state, tuple): self.set_control(*next_state) if self.controller().speaker() is DialogueFlow.Speaker.USER: self.controller().apply_update_rules(natural_language, debugging=debugging) def set_control(self, namespace, state): state = module_state(state) speaker = self.controller().speaker() old_state = self.controller().state() self.component(namespace).set_state(old_state) self.set_controller(namespace) self.controller().set_speaker(speaker) if isinstance(state, tuple): umh = self.state_settings(*state).user_multi_hop smh = self.state_settings(*state).system_multi_hop else: umh = self.state_settings(namespace, state).user_multi_hop smh = self.state_settings(namespace, state).system_multi_hop if speaker == DialogueFlow.Speaker.USER and not umh: self.controller().change_speaker() elif speaker == DialogueFlow.Speaker.SYSTEM and not smh: self.controller().change_speaker() self.controller().set_state(state) def precache_transitions(self, process_num=1): start = time() transition_data_sets = [] for i in range(process_num): transition_data_sets.append([]) # count = 0 if process_num == 1: for name, df in self._components.items(): df.precache_transitions(process_num) else: # for name,df in self._components.items(): # for transition in df._graph.arcs(): # transition_data_sets[count].append(df._graph.arc_data(*transition)) # count = (count + 1) % process_num # # print("multiprocessing...") # p = Pool(process_num) # results = p.map(precache, transition_data_sets) # for i in range(len(results)): # result_list = results[i] # t_list = transition_data_sets[i] # for j in range(len(result_list)): # parsed_tree = result_list[j] # t = t_list[j] # t['natex']._compiler._parsed_tree = parsed_tree raise NotImplementedError() print("Elapsed: ", time() - start) def add_state(self, state, error_successor=None): state = module_state(state) if isinstance(state, tuple): ns, state = state else: ns = "SYSTEM" self._components[ns].add_state(state, error_successor) def add_user_transition(self, source, target, natex_nlu, **settings): source, target = module_source_target(source, target) if isinstance(source, tuple): ns, source = source else: ns = "SYSTEM" self._components[ns].add_user_transition(source, target, natex_nlu, **settings) def add_system_transition(self, source, target, natex_nlg, **settings): source, target = module_source_target(source, target) if isinstance(source, tuple): ns, source = source else: ns = "SYSTEM" self._components[ns].add_system_transition(source, target, natex_nlg, **settings) def add_component(self, component, namespace): self._components[namespace] = component component.set_is_module(self) component.set_namespace(namespace) component.set_gates(self.component("SYSTEM").gates()) def component(self, namespace): return self._components[namespace] def components(self): return self._components.values() def set_state(self, state): state = module_state(state) if isinstance(state, tuple): if self.component(state[0]) != self.controller(): self.component(state[0]).set_state(self.controller().state( )) # so __system_state__ is set properly self.set_controller(state[0]) state = state[1] self.controller().set_state(state) def set_controller(self, controller_name): old_controller_vars = self._controller.vars() if self._controller_name != controller_name: del old_controller_vars["__state__"] self._controller = self.component(controller_name) self._controller_name = controller_name new_controller_vars = self._controller.vars() new_controller_vars.update(old_controller_vars) self._controller.set_vars(new_controller_vars) def transition_natex(self, namespace, source, target, speaker): source, target = module_source_target(source, target) if isinstance(source, tuple): source = source[1] if isinstance(target, tuple): target = target[1] return self.component(namespace).transition_natex( source, target, speaker) def state_settings(self, namespace, state): return self.component(namespace).state_settings(state) def set_vars(self, vars): self._controller.set_vars(vars) def reset(self): gates = None goals = None for name, component in self._components.items(): component.reset() if gates is None: gates = component.gates() goals = component.goals() component.set_gates(gates) component.set_goals(goals) self.set_controller("SYSTEM") def controller(self): return self._controller def controller_name(self): return self._controller_name def state(self): return self._controller_name, self._controller.state() def serialize(self): """ Returns json serialized dict of {'vars': vars, 'gates': gates, 'state': state} """ config = { "vars": self._controller.vars(), "gates": self._controller.gates(), "state": self.state() } return json_serialize_flexible(config, speaker_enum_mapping) def deserialize(self, config_str): config = json_deserialize_flexible(config_str, speaker_enum_rmapping) self.reset() self.set_state(config["state"]) self.set_vars(config["vars"]) gates = defaultdict(list, config["gates"]) for name, component in self._components.items(): component.set_gates(gates) def new_turn(self, toplevel="SYSTEM"): self.reset() self.set_controller(toplevel)
def test_single_user_transition(): df = DialogueFlow(States.B) df.add_user_transition(States.B, States.C, "[{hi, hello, hey, [how, you]}]") assert df.user_transition("oh hey there", df.state()) == States.C
def test_system_transition(): for _ in range(6): df = DialogueFlow(States.A) df.add_system_transition(States.A, States.B, "hello", score=2.0) df.add_system_transition(States.A, States.C, "hey") assert df.system_transition(df.state()) == ("hello", States.B) df = DialogueFlow(States.A) df.add_system_transition(States.A, States.B, "hello") df.add_system_transition(States.A, States.C, "hey", score=2.0) assert df.system_transition(df.state()) == ("hey", States.C)
def test_virtual_transitions(): df = DialogueFlow("root") transitions = { "state": "root", "hello": { "state": "test", "a": { "something typical": "nope" }, "#VT(other)": "blah", }, "not taken": { "state": "other", "score": 0, "x": { "you win": { "state": "success" } }, "y": { "you win": { "state": "success" } }, }, } df.load_transitions(transitions) df.system_turn() assert df.state() == "test" df.user_turn("x", debugging=True) assert df.system_turn() == "you win" assert df.state() == "success"
def test_information_state_based_dialogue(): df = DialogueFlow("root", initial_speaker=Speaker.USER) df.add_user_transition("root", "one", "$x=[{cat, dog}]") df.set_error_successor("root", "one") df.add_system_transition("one", "root", "i am a stupid state machine") df.add_update_rule("[$x={ice cream, candy}]") df.add_update_rule("#ANY($x=candy)", "$y=blah") df.add_update_rule("#ANY($x=ice cream)", "$y=None") df.add_update_rule("#ANY($y=blah)", "i am a smart info state manager (2.0)") df.user_turn("candy", debugging=True) assert df.system_turn().strip() == "i am a smart info state manager" df.user_turn("ice cream", debugging=True) assert df.system_turn(debugging=True).strip() == "i am a stupid state machine" df.user_turn("ice cream", debugging=True) assert df.system_turn(debugging=True).strip() == "i am a stupid state machine" df.user_turn("ice cream", debugging=True) assert df.system_turn(debugging=True).strip() == "i am a stupid state machine" df.user_turn("ice cream", debugging=True) assert df.system_turn(debugging=True).strip() == "i am a stupid state machine"
def test_gate_none(): df = DialogueFlow("root") transitions = { "state": "root", "#GATE(var:None) hello": { "state": "greet", "score": 2.0, "hi": {"#SET($var=True) how are ya": {"error": "root"}}, "error": {"how are you": {"error": "root"}}, }, "hi": "greet", } df.load_transitions(transitions) assert df.system_turn().strip() == "hello" df.user_turn("hi") assert df.system_turn().strip() == "how are ya" df.user_turn("fine") assert df.system_turn().strip() == "hi" df.user_turn("oh") assert df.system_turn().strip() == "how are you"
def test_stack(): df = DialogueFlow("root") transitions = { "state": "root", "`What should I do?`": "gma_hospital", "#GOAL(grandma_hospital) #GATE" "`I cannot concentrate on a lot of things right now. " "My grandma is in the hospital. " "What should I do?`": { "state": "gma_hospital", "score": 2.0, "[{[{dont,shouldnt,not},worry],calm,relax,distract,[mind,off]}]": { "state": "dont_worry", "#GATE " "\"Okay, I will try my best not to worry. It's hard because she lives by " "herself and won't let anyone help her very much, so I feel like this " 'will just happen again."': { "state": "happen_again", "[{sorry,sucks,hard}]": { '"yeah, thanks."': {} }, "[will,better]": { '"I really hope you are right."': {} }, "error": { "state": "feel_better", '"I actually feel a little bit better after talking with you. Thanks for listening. "': {}, }, }, "#DEFAULT": "feel_better", }, "#IDK": { '"yeah, i dont know either. Its so tough."': {} }, }, } gma = { "#GOAL(why_grandma_hospital) " "[{[why,hospital],wrong,happened}]": { "state": "why_grandma_hospital", '"She is just so frail. I can hardly believe it. ' 'She fell off of a stool in the kitchen and broke her hip."': { "[dont worry]": {"#GRET(grandma_hospital,dont_worry)"}, "error": { "#GRET": "return" }, }, }, "#GOAL(grandma_hospital_before) " "[{has,was},{she,grandma},hospital,{before,earlier,previously}]": { "state": "grandma_hospital_before", '"No, this is the first time, thank goodness."': { "error": { "#GRET": "return" } }, }, } df.load_transitions(transitions) df.load_transitions(gma, speaker=DialogueFlow.Speaker.USER) df.add_global_nlu( "why_grandma_hospital", "#GOAL(why_grandma_hospital) [{[why,hospital],wrong,happened}]", score=0.7, ) df.add_global_nlu( "grandma_hospital_before", "#GOAL(grandma_hospital_before) [{has,was},{she,grandma},hospital,{before,earlier,previously}]", score=0.7, ) # r = df.system_turn() df.system_turn() assert df.vars()["__goal__"] == "grandma_hospital" assert len(df.vars()["__stack__"]) == 0 assert df.state() == "gma_hospital" df.user_turn("what happened") assert df.state() == "why_grandma_hospital" assert df.vars()["__goal_return_state__"] == "None" assert df.vars()["__goal__"] == "why_grandma_hospital" assert len(df.vars()["__stack__"]) == 1 assert df.vars()["__stack__"][0][0] == "grandma_hospital" assert "fell off of a stool" in df.system_turn() df.user_turn("oh no", debugging=True) assert "What should I do" in df.system_turn(debugging=True) assert df.state() == "gma_hospital" assert df.vars()["__goal__"] == "grandma_hospital" assert len(df.vars()["__stack__"]) == 0 df.user_turn("dont worry") assert df.state() == "dont_worry" assert "she lives by herself" in df.system_turn() df.user_turn("has your grandma been in the hospital before this") assert df.state() == "grandma_hospital_before" assert df.vars()["__goal__"] == "grandma_hospital_before" assert len(df.vars()["__stack__"]) == 1 assert df.vars()["__stack__"][0][0] == "grandma_hospital" assert "this is the first time" in df.system_turn() df.user_turn("ok that is good") assert "feel a little bit better" in df.system_turn() assert df.vars()["__goal__"] == "grandma_hospital" assert len(df.vars()["__stack__"]) == 0
def test_system_multi_hop(): df = DialogueFlow(States.A, initial_speaker=Speaker.SYSTEM) df.add_state(States.B, error_successor=States.B, system_multi_hop=True) df.add_state(States.C, error_successor=States.A, system_multi_hop=True) df.add_state(States.D, error_successor=States.A) df.add_state(States.E, error_successor=States.A) df.add_system_transition(States.A, States.B, "{hey, hello}") df.add_system_transition(States.A, States.C, "excuse me") df.add_system_transition(States.B, States.D, "how are you") df.add_system_transition(States.C, States.E, "what") for _ in range(100): df.set_state(States.A) df.set_speaker(Speaker.SYSTEM) response = df.system_turn() assert response in {"hey how are you", "hello how are you", "excuse me what"}
def test_user_multi_hop(): df = DialogueFlow(States.A, initial_speaker=Speaker.USER) df.add_state(States.B, error_successor=States.B, user_multi_hop=True) df.add_state(States.C, error_successor=States.A, user_multi_hop=True) df.add_state(States.D, error_successor=States.A) df.add_state(States.E, error_successor=States.A) df.add_user_transition(States.A, States.B, "[{hey, hello}]") df.add_user_transition(States.A, States.C, "[{excuse, pardon}]") df.add_user_transition(States.B, States.D, "[how, you]") df.add_user_transition(States.C, States.E, "[{where, how, what}]") df.set_state(States.A) df.user_turn("hey", debugging=False) assert df.state() == States.B df.set_state(States.A) df.set_speaker(Speaker.USER) df.user_turn("hey how are you") assert df.state() == States.D df.set_state(States.A) df.set_speaker(Speaker.USER) df.user_turn("excuse me where do i go") assert df.state() == States.E df.set_state(States.A) df.set_speaker(Speaker.USER) df.user_turn("excuse me") assert df.state() == States.A
def test_information_state_state_set(): df = DialogueFlow("root", initial_speaker=Speaker.USER) transitions = { "state": "root", "error": { "state": "one", "okay": {"state": "two", "error": {"state": "three", "sure": "root"}}, }, "something": {"state": "special", "that is great": "root"}, } df.add_update_rule("[{read, watched}]", "#TRANSITION(special, 2.0)") df.load_transitions(transitions, speaker=Speaker.USER) df.user_turn("hi") assert df.system_turn() == "okay" df.user_turn("i read a book") assert df.state() == "special" assert df.system_turn() == "that is great" assert df.state() == "root"
def test_add_transitions(): df = DialogueFlow("States.A") df.add_system_transition("States.A", "States.B", "hello") df.add_user_transition("States.B", "States.C", "[{hi, hello, hey, [how, you]}]") df.add_user_transition("States.B", "States.D", "[{dog, cat, parrot}]") df.add_system_transition("States.D", "States.A", "so") assert df.graph().arcs() == { ("States.A", "States.B", DialogueFlow.Speaker.SYSTEM), ("States.B", "States.C", DialogueFlow.Speaker.USER), ("States.B", "States.D", DialogueFlow.Speaker.USER), ("States.D", "States.A", DialogueFlow.Speaker.SYSTEM), } assert isinstance(df.transition_natex("States.A", "States.B", Speaker.SYSTEM), NatexNLG) assert isinstance(df.transition_natex("States.B", "States.C", Speaker.USER), NatexNLU)
def test_reset(): df = DialogueFlow(States.A, initial_speaker=Speaker.SYSTEM) df.add_state(States.B, error_successor=States.E) df.add_state(States.C, error_successor=States.E) df.add_system_transition(States.A, States.B, "B") df.add_system_transition(States.A, States.C, "C") df.add_system_transition(States.E, States.E, "E") # response = df.system_turn() df.system_turn() df.user_turn("") assert df.state() == States.E df.reset() assert df.state() == "States.A" assert df.speaker() == Speaker.SYSTEM # response = df.system_turn() df.system_turn() df.user_turn("") assert df.state() == States.E df.system_turn() assert df.state() == States.E df.reset() assert df.state() == States.A assert df.speaker() == Speaker.SYSTEM # response = df.system_turn() df.system_turn() df.user_turn("") assert df.state() == States.E df.system_turn() assert df.state() == States.E
def test_global_transition_list_disjunction(): df = DialogueFlow("root", initial_speaker=Speaker.USER) nlu = ["hi", "hello"] df.add_state("root", "x") df.add_system_transition("x", "y", "hello") df.add_global_nlu("x", nlu) df.user_turn("ok") df.system_turn() df.user_turn("hi") assert df.state() == "x"
def test_enter_natex(): df = DialogueFlow("root") transitions = { "state": "root", "hello": {"state": "one", "score": 2.0, "enter": "#GATE", "error": "root"}, "hi": {"state": "two", "score": 1.0, "enter": "#GATE", "error": "root"}, "bye": { "state": "one", "score": 1.0, }, "goodbye": {"state": "three", "score": 0.0, "error": "end"}, } df.load_transitions(transitions) assert df.system_turn() == "hello" df.user_turn("hello") assert df.system_turn() == "hi" df.user_turn("hi") assert df.system_turn() == "goodbye"
def test_check(): df = DialogueFlow(States.A) df.add_state(States.B, error_successor=States.C) df.add_state(States.D, error_successor=States.A) df.add_system_transition(States.A, States.B, "hello") df.add_user_transition(States.B, States.C, "[{hi, hello, hey, [how, you]}]") df.add_user_transition(States.B, States.A, "[{bye, goodbye, see you, see ya, later}]") df.add_system_transition(States.C, States.D, "ok") assert df.check() df = DialogueFlow(States.A) df.add_state(States.B, error_successor=States.C) df.add_system_transition(States.A, States.B, "hello") df.add_user_transition(States.B, States.C, "[{hi, hello, hey, [how, you]}]") df.add_user_transition(States.B, States.A, "[{bye, goodbye, see you, see ya, later}]") df.add_system_transition(States.C, States.D, "ok") assert not df.check() df = DialogueFlow(States.A) df.add_state(States.B, error_successor=States.C) df.add_state(States.D, error_successor=States.A) df.add_system_transition(States.A, States.B, "hello") df.add_user_transition(States.B, States.C, "[{hi, hello, hey, [how, you]}]") df.add_user_transition(States.B, States.A, "[{bye, goodbye, see you, see ya, later}]") df.add_system_transition(States.C, States.D, "ok then $X alright") assert not df.check()
def test_serialization(): df = DialogueFlow(States.A, initial_speaker=Speaker.SYSTEM) df.add_state(States.B, error_successor=States.E) df.add_state(States.C, error_successor=States.E) df.add_system_transition(States.A, States.B, "#GATE $spoken=B") df.add_system_transition(States.A, States.C, "#GATE(spoken) $spoken=C") df.add_system_transition(States.E, States.E, "$spoken=E") df.add_user_transition(States.B, States.A, "$heard=b") df.add_user_transition(States.E, States.A, "$heard=e") df.system_turn() assert df.state() == States.B assert df.vars()["spoken"] == "B" df.user_turn("b") df.system_turn() assert df.state() == States.C assert df.vars()["spoken"] == "C" expected_gates = {"States.B": [{}], "States.C": [{"spoken": "B"}]} assert df.gates() == expected_gates df.vars()["testing_none"] = None d = df.serialize() df2 = DialogueFlow(States.A, initial_speaker=Speaker.SYSTEM) df2.add_state(States.B, error_successor=States.E) df2.add_state(States.C, error_successor=States.E) df2.add_system_transition(States.A, States.B, "#GATE $spoken=B") df2.add_system_transition(States.A, States.C, "#GATE(spoken) $spoken=C") df2.add_system_transition(States.E, States.E, "$spoken=E") df2.add_user_transition(States.B, States.A, "$heard=b") df2.add_user_transition(States.E, States.A, "$heard=e") assert df2.state() == States.A assert "spoken" not in df2.vars() and "heard" not in df2.vars() assert len(df2.gates()) == 0 df2.deserialize(d) assert df.vars() == df2.vars() assert df.gates() == df2.gates() assert df.state() == df2.state() assert df2.vars()["testing_none"] is None
("panther", "sound", "growl"), ("growl", "quality", "scary"), ("also", "type", "also_syns"), ("too", "type", "also_syns"), ("basketball", "type", "unknown_hobby"), ("basketball", "expr", "bball"), ("john", "type", "male"), ("mary", "type", "female"), ("male", "type", "person"), ("female", "type", "person"), ("friend", "type", "person"), ]) ont = {"ontology": {"person": ["mom", "dad", "sister", "brother"]}} kb.load_json(ont) df = DialogueFlow(initial_state="start") df.add_state("start", "start") df.add_system_transition("start", "start", "hello") macros = { # "ONT": ONTE(kb), # "KBQ": KBE(kb), # "EXP": EXP(kb), # "U": UnionMacro(), # "I": Intersection(), # "DIF": Difference(), # "SET": SetVars(), # "ALL": CheckVarsConjunction(), # "ANY": CheckVarsDisjunction(), # "NOT": NOT(), # "ISP": IsPlural(),
def test_single_system_transition(): df = DialogueFlow(States.A) df.add_system_transition(States.A, States.B, "hello") assert df.system_transition(df.state()) == ("hello", States.B)
def test_global_transition_priority(): df = DialogueFlow("root") transitions = { "state": "root", "hello": { "[oh]": {"score": 0.6, "okay": {}}, "[wow]": {"score": 2.0, "alright": {}}, }, } df.add_global_nlu("root", "/.*/", score=0.7) df.load_transitions(transitions) df.system_turn() df.user_turn("oh wow") assert df.system_turn() == "alright"
def test_constructor(): df = DialogueFlow(States.A) assert df.state() == States.A assert df.speaker() == Speaker.SYSTEM