Base skill¶
Provides basic behaviour like responding to hello, bye, help, purpose, etc.
Overview¶
Base implements all intents commonly needed for control flow of your chatbot, like opening the conversation, closing it, offering help, explaining it's name, function and purpose, handling fallback and responding to smalltalk. Base relies on the Defaults skill for it's intents and trainingsentences.
Intents¶
intent | example |
---|---|
@reset |
i want to start over |
@stop |
stop |
@cancel |
i want to cancel this |
@back |
i want to go back |
@bye |
goodbye, bye |
@close |
i want to close this conversation |
@hello |
hello, hi there |
@continue |
please continue |
@question |
i have a question |
@help |
can you help me? |
@allskills |
what can you do? |
@alltopics |
what do you know? |
@learn |
can you please learn this? |
@explain |
explain this please |
@about |
what are you? |
@purpose |
what is your purpose? |
@bot_name |
what is your name? |
@now_date |
what is the date? |
@now_time |
what is the time? |
@thanks |
thank you |
@success |
this is good |
@wrong |
this is wrong |
@more |
give me more |
@other |
i want something else |
@repeat |
can you repeat that? |
@dontunderstand |
i don't understand |
@dontknow |
i don't know |
@again |
i want to try again |
@no |
no, nothing |
@feedback |
i want to leave a message |
@escalate |
i want to talk to a human |
@smalltalk_agent_talk_to_me |
tell me something |
@smalltalk_user_wants_to_talk |
can i talk to you? |
@smalltalk_user_needs_advice |
i need some advice |
@smalltalk_user_does_not_want_to_talk |
bad time for talking |
@smalltalk_appraisal_bad |
this sucks |
@smalltalk_appraisal_good |
you are ok |
@smalltalk_appraisal_well_done |
well done |
@smalltalk_user_good |
i'm doing good |
@smalltalk_greetings_whatsup |
hey what's up? |
@smalltalk_weather |
what is the weather today? |
@smalltalk_joke |
tell me a joke |
@smalltalk_agent_age |
how old are you? |
@smalltalk_agent_born |
when are you born? |
@smalltalk_agent_sure |
are you sure? |
@smalltalk_agent_there |
are you there? |
@smalltalk_dialog_hold_on |
hold on please |
@smalltalk_user_here |
i'm here |
@smalltalk_user_waits |
i'm waiting |
@smalltalk_user_will_be_back |
i'll be back in a second |
@smalltalk_dialog_i_do_not_care |
i don't care |
@smalltalk_dialog_sorry |
i'm sorry |
@smalltalk_emotions_ha_ha |
ha ha |
@smalltalk_greetings_goodevening |
good evening |
@smalltalk_greetings_goodmorning |
good morning |
@smalltalk_greetings_goodnight |
good night |
@smalltalk_greetings_how_are_you |
how are you? |
@smalltalk_greetings_nice_to_meet_you |
nice to meet you |
@smalltalk_greetings_nice_to_see_you |
nice to see you |
@smalltalk_user_wants_to_see_agent_again |
can i see you again? |
How to use¶
It will work out of the box in any empty chatbot. You don't need any dialog in your main file for it to work. You can then start to overwrite which ever dialog you want from base in your own main
file.
Minimum¶
The most minimum implementation is to define your own dialogs and triggers and simply inject quick replies into the root prompt of Base.
You can simply add menu items by defining inner dialogs in root
like this:
@favorite_color intent(label: "My favorite color", match: "favorite color")
dialog favorite_color, trigger: @favorite_color do
say "My favorite color is red."
end
Then you can inject a quick reply in the root prompt by defining a dialog into root like this:
dialog root.my_fav_color, label: "My favorite color" do
invoke favorite_color
end
Extending¶
The above is the most minimum implementation. A lot of the times you would want to define your own main
dialog to customize your welcome message and your own root
dialog to define your own menu. Like this:
dialog main do
say "Welcome at Restaurant Sienna"
invoke about
end
dialog root do
prompt ["What can I do for you?", "What else can I do for you?"]
end
You can easily extend or replace other behaviour of this base skill by defining your own versions of these dialogs. Suppose you want your own version of hello, you can easily redefine the hello
dialog like this:
dialog hello do
say "What's up?"
end
If you want to extend the root prompt with some quick replies you can define inner dialogs within the root dialog like this:
dialog root do
prompt ["What can I do for you?", "What else can I do for you?"]
dialog label: "Menu" do
say "We serve Pizza Margherita, Pizza Pepperoni and Pizza Venezia."
end
dialog label: "Order" do
ask "What pizza do you want to order?
say "We will start preparing your #{answer}"
end
end
This works very good for small dialogs. But once your dialogs become bigger, it is much cleaner to keep your inner dialogs very small (only for dispatching) and define the real dialogs outside of your root dialog, like this:
dialog root do
prompt ["What can I do for you?", "What else can I do for you?"]
dialog label: "Menu" do
invoke menu
end
dialog label: "Order" do
invoke order
end
end
dialog menu do
say "We serve Pizza Margherita, Pizza Pepperoni and Pizza Venezia."
end
dialog order do
ask "What pizza do you want to order?
say "We will start preparing your #{answer}"
end
It is even more clean to use the single line version of a dialog definition, like this:
dialog root do
prompt ["What can I do for you?", "What else can I do for you?"]
dialog label: "Menu", do: invoke menu
dialog label: "Order", do: invoke order
end
How it works¶
Base includes four files each having their own responsibility.
file | description |
---|---|
base.bb |
to respond to all basic intents, like hello, bye, etc |
smalltalk.bb |
responds in the most minimal way to the most commonly used smalltalk intents |
subjects.bb |
responsible for extracting the subjct out of any uttered sentence |
unknown.bb |
responsible for all the different fallback possibilities |
Base.bb¶
This file is used to set initial bot settings and holding the triggers and dialogs for all important intents.
Smalltalk.bb¶
Holds the less important intent triggers and dialogs, needed to respond to smalltalk.
Subjects.bb¶
The subjects file holds a task that is capable of evaluating the uttered message and try to extract the most important words out of it as it's subjects. The subjects will be added to the message in the stats. You can try this to see how it works:
# message.stats.subjects is filled with the subjects found in the message
dialog __unknown__ do
say "subjects found: " + join_and(message.stats.subjects)
end
Unknown.bb¶
As already mentioned about, nothing is more annoying than a chatbot not understanding anything. However, this will be the case in lot's of occurences. That is why applying proper fallback is of paramount importance. This is why our base skill includes five different fallback dialogs.
Message too vague¶
When a message doesn't include a subject, or it is in a language we cannot recognise, it is probably not an intent worth handling. Since most of the chatbots will choose to escalate to live chat as soon as the chatbot doesn't know, it is important to differentiate rubbish from actual intents. Therefore we have an unknown handling vague messages.
First it will just excuse itself and then asking to specify more clearly.
dialog unknown_vague do
invoke sorry
invoke specify
end
Message too long¶
Another good reason to treat a message differently from all others is when it is too long. When we found more than 15 words in one message, it is probably too specific for a chatbot to handle. Therefore we use this unknown variant to explain it is too long.
dialog unknown_long do
tag "utterance_too_long"
invoke sorry
once do
say _"I respond best to short commands 🤖"
end
invoke rephrase
end
This variant is used in for instance the chat skill, that supports escalation to live chat, to escalate a message directly when it is too long to handle by the chatbot. The chat skill simply redefines this dialog and invokes the escalate dialog.
Note that you can adjust the amount of words to use for this trigger in the constant @max_words
.
Messages that are exactly the same as before¶
When a message is uttered twice, it is no use to answer again.
dialog unknown_repeat do
say _("Yes, you just said this…")
invoke rephrase
end
Unknown¶
All other messages that do not trigger any dialog will be captured by the unknown dialog. The first time it will say sorry, that it doesn't understand, explain that it is just a chatbot and ask to rephrase. After this time it will never do the explain again due to the once construction. It quickly becomes anoying otherwise.
# first time unknown
dialog unknown when count("unknown", dialog.stack) == 0 do
invoke sorry
invoke fallback
once do
invoke explain
end
invoke rephrase
end
If unknown is triggered again while we are handling the rephrase it will do something else. This is arranged by checking in the guard the amount of times the unknown dialog is triggered in the current stack. This time it'll start saying it still doesn't understand. It will then explain it's purpose and asks to rephrase again. The next time this unknown is fired it will say it'll mark this as something to learn instead of explaining it's purpose again after which it will just reset to root. No need to keep on trying when it doesn't seem to work.
# 2nd and 3rd time unknown
dialog unknown when count("unknown", dialog.stack) < 3 do
invoke fallback_again
once do
invoke purpose
end
invoke rephrase
end
The fourth time it is triggered within the current stack it will mark this conversation with the tag "learn" so the owner of the Bot can address the issue. The conversation will reset now since it is no use trying to get this intent to work since it obviously isn't supported.
# 4th time unknown
dialog unknown when count("unknown", dialog.stack) >= 3 do
invoke fallback_again
invoke learn
reset
end
Unknown from inner dialogs¶
Messages that are not understood within a running dialog should be handled simpler. They should be handled by the dialog itself by defining an inner dialog. Base skill has the following dialog ready to use for you.
dialog unknown_dialog do
once do
invoke sorry
invoke sorry
end
invoke fallback
end
As you see we don't appologize more than twice. It'll get anoying otherwise.
Make sure to invoke this dialog yourself whenever you are building a dialog. You can do it like this:
dialog my_dialog do
say "Something nice"
ask "How do you do?", expecting: ["good", "bad"]
say "So you are doing #{answer}"
# to make sure we are not using the regular unknown
dialog __unknown__ do
invoke unknown_in_dialog
end
end