Skip to content

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