From 4badb43176721828e426a77734a5c346e6c5662e Mon Sep 17 00:00:00 2001 From: NotBioWaste905 <59259188+NotBioWaste905@users.noreply.github.com> Date: Mon, 25 Dec 2023 10:40:44 +0300 Subject: [PATCH 1/4] Add: multiple fallback tutorial Add tutorial that utilizes local transitions to local fallback nodes to handle fallbacks. --- .../script/core/10_multiple_fallback_nodes.py | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tutorials/script/core/10_multiple_fallback_nodes.py diff --git a/tutorials/script/core/10_multiple_fallback_nodes.py b/tutorials/script/core/10_multiple_fallback_nodes.py new file mode 100644 index 000000000..dd93a5ef0 --- /dev/null +++ b/tutorials/script/core/10_multiple_fallback_nodes.py @@ -0,0 +1,127 @@ +# %% [markdown] +""" +# Core: 10. Multiple fallback nodes + +This tutorial shows basics of creating a separate fallback node for every flow. In this case it is done via local transitions (LINK). + +Let's do all the necessary imports from DFF: +""" + +# %pip install dff + + +"""Importing all the necessary modules:""" + +# %% +from dff.pipeline import Pipeline +from dff.script import TRANSITIONS, RESPONSE, Message +import dff.script.conditions as cnd + +# %% [markdown] +""" +Let's create a script that will consist of several flows, that can be accessed through dialogue: +""" + +# %% +toy_script = { + "greeting_flow": { + "start_node": { + RESPONSE: Message(), + TRANSITIONS: { + ("greeting_flow", "say_hi_node"): cnd.true() + } + }, + + "say_hi_node": { + RESPONSE: Message(text="Hello, how can I help you?"), + TRANSITIONS: { + ("authorization_flow", "response_node"): cnd.exact_match(Message(text="auth")), + ("information_flow", "response_node"): cnd.exact_match(Message(text="info")), + ("fallback_node"): cnd.true() + } + }, + + "fallback_node": { + RESPONSE: Message(text="Unknown Command. Try again."), + TRANSITIONS: {"say_hi_node": cnd.exact_match(Message(text="hi")) + } + } + }, + "authorization_flow": { + "response_node": { + RESPONSE: Message(text="Write your name, please."), + TRANSITIONS: { + ("authorization_flow", "auth_success_node"): + cnd.exact_match(Message(text="admin")), + ("authorization_fallback_node"): + cnd.true() + } + }, + + "auth_success_node": { + RESPONSE: Message(text="Authentication successful."), + TRANSITIONS: { + ("authorization_flow", "response_node"): + cnd.exact_match(Message(text="")) + } + }, + + "authorization_fallback_node": { + RESPONSE: Message(text="User not found."), + TRANSITIONS: { + ("authorization_flow", "response_node"): + cnd.exact_match(Message(text="")) + } + } + }, + + "information_flow": { + "response_node": { + RESPONSE: Message(text="What information you would like to know?"), + TRANSITIONS: { + ("information_flow", "weather_node"): + cnd.exact_match(Message(text="weather")), + ("information_flow", "time_node"): + cnd.exact_match(Message(text="time")), + ("information_fallback_node"): + cnd.true() + } + }, + "weather_node": { + RESPONSE: Message(text="It's sunny now!"), + TRANSITIONS: { + ("information_flow", "response_node"): + cnd.true() + } + }, + "time_node": { + RESPONSE: Message(text="It's tea time!"), + TRANSITIONS: { + ("information_flow", "response_node"): + cnd.true() + } + }, + "information_fallback_node": { + RESPONSE: Message(text="I don't know that information!"), + TRANSITIONS: { + ("information_flow", "response_node"): + cnd.true() + } + } + } +} + +# %% [markdown] +""" +As you can see, we've created specific fallback node for each individual flow (e.g. `authorization_fallback_node` for `authorization_flow`). We define transition to them in response node of the flow (actually it can be defined in any node in the flow) using `("information_fallback_node"): cnd.true()`. Due to the low priority this condition will trigger automatically if no other condition was triggered. + +And now let's run our script: +""" +# %% +pipeline = Pipeline.from_script( + toy_script, + start_label=("greeting_flow", "start_node") + ) + +if __name__ == "__main__": + pipeline.run() From 0d180579f50c9f465dac389d25a8ef3955042f33 Mon Sep 17 00:00:00 2001 From: NotBioWaste905 Date: Thu, 28 Dec 2023 17:27:14 +0300 Subject: [PATCH 2/4] Update: now using LOCAL transitions --- .../script/core/10_multiple_fallback_nodes.py | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tutorials/script/core/10_multiple_fallback_nodes.py b/tutorials/script/core/10_multiple_fallback_nodes.py index dd93a5ef0..1c806ed52 100644 --- a/tutorials/script/core/10_multiple_fallback_nodes.py +++ b/tutorials/script/core/10_multiple_fallback_nodes.py @@ -2,7 +2,7 @@ """ # Core: 10. Multiple fallback nodes -This tutorial shows basics of creating a separate fallback node for every flow. In this case it is done via local transitions (LINK). +This tutorial shows basics of creating a separate fallback node for every flow. In this case it is done via `LOCAL` nodes. Let's do all the necessary imports from DFF: """ @@ -14,7 +14,7 @@ # %% from dff.pipeline import Pipeline -from dff.script import TRANSITIONS, RESPONSE, Message +from dff.script import TRANSITIONS, RESPONSE, Message, LOCAL import dff.script.conditions as cnd # %% [markdown] @@ -36,8 +36,7 @@ RESPONSE: Message(text="Hello, how can I help you?"), TRANSITIONS: { ("authorization_flow", "response_node"): cnd.exact_match(Message(text="auth")), - ("information_flow", "response_node"): cnd.exact_match(Message(text="info")), - ("fallback_node"): cnd.true() + ("information_flow", "response_node"): cnd.exact_match(Message(text="info")) } }, @@ -48,13 +47,17 @@ } }, "authorization_flow": { + LOCAL: { + TRANSITIONS: { + ("authorization_fallback_node"): + cnd.true() + } + }, "response_node": { RESPONSE: Message(text="Write your name, please."), TRANSITIONS: { ("authorization_flow", "auth_success_node"): - cnd.exact_match(Message(text="admin")), - ("authorization_fallback_node"): - cnd.true() + cnd.exact_match(Message(text="admin")) } }, @@ -76,15 +79,19 @@ }, "information_flow": { + LOCAL: { + TRANSITIONS: { + ("information_fallback_node"): + cnd.true() + } + }, "response_node": { RESPONSE: Message(text="What information you would like to know?"), TRANSITIONS: { ("information_flow", "weather_node"): cnd.exact_match(Message(text="weather")), ("information_flow", "time_node"): - cnd.exact_match(Message(text="time")), - ("information_fallback_node"): - cnd.true() + cnd.exact_match(Message(text="time")) } }, "weather_node": { @@ -113,14 +120,16 @@ # %% [markdown] """ -As you can see, we've created specific fallback node for each individual flow (e.g. `authorization_fallback_node` for `authorization_flow`). We define transition to them in response node of the flow (actually it can be defined in any node in the flow) using `("information_fallback_node"): cnd.true()`. Due to the low priority this condition will trigger automatically if no other condition was triggered. +As you can see, we've created specific fallback node for each individual flow using `LOCAL` node. Due to the low priority this condition will trigger automatically if no other condition in any node in the flow was triggered. +Also we defined `fallback_label` in our `Pipeline` which is being overwritten with `LOCAL` nodes in flows they defined in. And now let's run our script: """ # %% pipeline = Pipeline.from_script( toy_script, - start_label=("greeting_flow", "start_node") + start_label=("greeting_flow", "start_node"), + fallback_label=("greeting_flow", "fallback_node") ) if __name__ == "__main__": From 646a65ef72461282d6c602da150254d818ecfa71 Mon Sep 17 00:00:00 2001 From: NotBioWaste905 Date: Thu, 28 Dec 2023 18:15:18 +0300 Subject: [PATCH 3/4] Update: added more branching to show utility of LOCAL node --- .../script/core/10_multiple_fallback_nodes.py | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/tutorials/script/core/10_multiple_fallback_nodes.py b/tutorials/script/core/10_multiple_fallback_nodes.py index 1c806ed52..9a4f073c4 100644 --- a/tutorials/script/core/10_multiple_fallback_nodes.py +++ b/tutorials/script/core/10_multiple_fallback_nodes.py @@ -49,15 +49,17 @@ "authorization_flow": { LOCAL: { TRANSITIONS: { - ("authorization_fallback_node"): + ("auth_fallback_node"): cnd.true() } }, "response_node": { RESPONSE: Message(text="Write your name, please."), TRANSITIONS: { + ("authorization_flow", "auth_password_node"): + cnd.exact_match(Message(text="admin")), ("authorization_flow", "auth_success_node"): - cnd.exact_match(Message(text="admin")) + cnd.exact_match(Message(text="John Doe")) } }, @@ -69,7 +71,15 @@ } }, - "authorization_fallback_node": { + "auth_password_node": { + RESPONSE: Message(text="Password required. Enter your password."), + TRANSITIONS: { + ("authorization_flow", "auth_success_node"): + cnd.exact_match(Message(text="123")) + } + }, + + "auth_fallback_node": { RESPONSE: Message(text="User not found."), TRANSITIONS: { ("authorization_flow", "response_node"): @@ -88,19 +98,33 @@ "response_node": { RESPONSE: Message(text="What information you would like to know?"), TRANSITIONS: { - ("information_flow", "weather_node"): + ("information_flow", "weather_city_node"): cnd.exact_match(Message(text="weather")), ("information_flow", "time_node"): cnd.exact_match(Message(text="time")) } }, - "weather_node": { - RESPONSE: Message(text="It's sunny now!"), + "weather_city_node": { + RESPONSE: Message(text="What city are interested in?"), TRANSITIONS: { - ("information_flow", "response_node"): - cnd.true() + ("information_flow", "weather_moscow_node"): + cnd.exact_match(Message(text="Moscow")), + ("information_flow", "weather_new_york_node"): + cnd.exact_match(Message(text="New York")) } }, + "weather_moscow_node": { + RESPONSE: Message(text="It's -5 Celsius"), + TRANSITIONS: { + ("response_node"): cnd.true() + } + }, + "weather_new_york_node": { + RESPONSE: Message(text="It's +14 Celsius"), + TRANSITIONS: { + ("response_node"): cnd.true() + } + }, "time_node": { RESPONSE: Message(text="It's tea time!"), TRANSITIONS: { From e22a874a528f428a0da0524c48bebd63387b7355 Mon Sep 17 00:00:00 2001 From: NotBioWaste905 Date: Mon, 22 Jan 2024 14:12:11 +0300 Subject: [PATCH 4/4] Added explicit priority, fixed fallback node transitions --- .../script/core/10_multiple_fallback_nodes.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tutorials/script/core/10_multiple_fallback_nodes.py b/tutorials/script/core/10_multiple_fallback_nodes.py index 9a4f073c4..74aadb39d 100644 --- a/tutorials/script/core/10_multiple_fallback_nodes.py +++ b/tutorials/script/core/10_multiple_fallback_nodes.py @@ -35,8 +35,8 @@ "say_hi_node": { RESPONSE: Message(text="Hello, how can I help you?"), TRANSITIONS: { - ("authorization_flow", "response_node"): cnd.exact_match(Message(text="auth")), - ("information_flow", "response_node"): cnd.exact_match(Message(text="info")) + ("authorization_flow", "response_node"): cnd.exact_match(Message(text="/auth")), + ("information_flow", "response_node"): cnd.exact_match(Message(text="/info")) } }, @@ -49,7 +49,7 @@ "authorization_flow": { LOCAL: { TRANSITIONS: { - ("auth_fallback_node"): + ("auth_fallback_node", 0.1): cnd.true() } }, @@ -66,8 +66,8 @@ "auth_success_node": { RESPONSE: Message(text="Authentication successful."), TRANSITIONS: { - ("authorization_flow", "response_node"): - cnd.exact_match(Message(text="")) + ("greeting_flow", "start_node"): + cnd.true() } }, @@ -80,10 +80,10 @@ }, "auth_fallback_node": { - RESPONSE: Message(text="User not found."), + RESPONSE: Message(text="User is not found or password is incorrect."), TRANSITIONS: { - ("authorization_flow", "response_node"): - cnd.exact_match(Message(text="")) + ("greeting_flow", "say_hi_node"): + cnd.true() } } }, @@ -91,7 +91,7 @@ "information_flow": { LOCAL: { TRANSITIONS: { - ("information_fallback_node"): + ("information_fallback_node", 0.1): cnd.true() } }, @@ -116,19 +116,19 @@ "weather_moscow_node": { RESPONSE: Message(text="It's -5 Celsius"), TRANSITIONS: { - ("response_node"): cnd.true() + ("greeting_flow", "start_node"): cnd.true() } }, "weather_new_york_node": { RESPONSE: Message(text="It's +14 Celsius"), TRANSITIONS: { - ("response_node"): cnd.true() + ("greeting_flow", "start_node"): cnd.true() } }, "time_node": { RESPONSE: Message(text="It's tea time!"), TRANSITIONS: { - ("information_flow", "response_node"): + ("greeting_flow", "start_node"): cnd.true() } }, @@ -144,7 +144,7 @@ # %% [markdown] """ -As you can see, we've created specific fallback node for each individual flow using `LOCAL` node. Due to the low priority this condition will trigger automatically if no other condition in any node in the flow was triggered. +As you can see, we've created specific fallback node for each individual flow using `LOCAL` node. Due to the low priority (explicitly set as `0.1`) this condition will trigger automatically if no other condition in any node in the flow was triggered. Also we defined `fallback_label` in our `Pipeline` which is being overwritten with `LOCAL` nodes in flows they defined in. And now let's run our script: