Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: multiple fallback tutorial #316

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions tutorials/script/core/10_multiple_fallback_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# %% [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` nodes.

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, LOCAL
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": {
RESPONSE: Message(text="Unknown Command. Try again."),
TRANSITIONS: {"say_hi_node": cnd.exact_match(Message(text="hi"))
}
}
},
"authorization_flow": {
LOCAL: {
TRANSITIONS: {
("auth_fallback_node", 0.1):
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="John Doe"))
}
},

"auth_success_node": {
RESPONSE: Message(text="Authentication successful."),
TRANSITIONS: {
("greeting_flow", "start_node"):
cnd.true()
}
},

"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 is not found or password is incorrect."),
TRANSITIONS: {
("greeting_flow", "say_hi_node"):
cnd.true()
}
}
},

"information_flow": {
LOCAL: {
TRANSITIONS: {
("information_fallback_node", 0.1):
cnd.true()
}
},
"response_node": {
RESPONSE: Message(text="What information you would like to know?"),
TRANSITIONS: {
("information_flow", "weather_city_node"):
cnd.exact_match(Message(text="weather")),
("information_flow", "time_node"):
cnd.exact_match(Message(text="time"))
}
},
"weather_city_node": {
RESPONSE: Message(text="What city are interested in?"),
TRANSITIONS: {
("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: {
("greeting_flow", "start_node"): cnd.true()
}
},
"weather_new_york_node": {
RESPONSE: Message(text="It's +14 Celsius"),
TRANSITIONS: {
("greeting_flow", "start_node"): cnd.true()
}
},
"time_node": {
RESPONSE: Message(text="It's tea time!"),
TRANSITIONS: {
("greeting_flow", "start_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 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:
"""
# %%
pipeline = Pipeline.from_script(
toy_script,
start_label=("greeting_flow", "start_node"),
fallback_label=("greeting_flow", "fallback_node")
)

if __name__ == "__main__":
pipeline.run()