Script development
At the previous step, we’ve created a chatbot.yaml
configuration file and set the parameters for our bot.
At this step, we will write a script for the bot and also consider the use of slot filling and other options for random value processing.
Creating the script
Create a main.sc
file in the src
folder. It will contain the main script of the bot.
require: slotfilling/slotFilling.sc
module = sys.zb-common
require: common.js
module = sys.zb-common
theme: /
state: Rules
q!: $regex</start>
intent!: /LetsPlay
a: Let's play Guess Number game. I think of a number from 0 to 100, you guess. Ready to start?
go!: /Rules/Agree
state: Agree
state: Yes
intent: /Yes
go!: /Game
state: No
intent: /No
a: That's a pity! If you change your mind, just text "Lets's play"
state: Game
script:
$session.number = $jsapi.random(100) + 1;
$reactions.transition("/CheckNumber");
state: CheckNumber
intent: /Number
script:
var num = $parseTree._Number;
if (num == $session.number) {
$reactions.answer("You won! Let's play one more time?");
$reactions.transition("/Rules/Agree");
}
else
if (num < $session.number)
$reactions.answer(selectRandomArg(["Bigger!", "My number is bigger than yours"]));
else $reactions.answer(selectRandomArg(["Smaller!", "My number is smaller than yours", "Hint: the number is smaller than yours"]));
state: NoMatch || noContext=true
event!: noMatch
random:
a: I don't understand you
a: What do you mean?
a: I don't get you
At the beginning of the script add the slotFilling
and common.js
additional modules using require
tag. We will take a look at how these modules are used in the Script structure section.
The script consists of a few main states:
Rules
— start of the script. The bot welcomes the user, offers them to play the game, and explains the rules.Game
— start of the game. The bot generates a random number.CheckNumber
— checks the number entered by the user and displays the result.NoMatch
— the state is used in case the user’s message does not fit any of the described stages.
Script structure
Rules
The script starts from the Rules
state. The bot sends a welcome message and offers the user to play the game.
state: Rules
q!: $regex</start>
intent!: /LetsPlay
a: Let's play Guess Number game. I think of a number from 0 to 100, you guess. Ready to start?
go!: /Rules/Agree
state: Agree
state: Yes
intent: /Yes
go!: /Game
state: No
intent: /No
a: That's a pity! If you change your mind, just text me "Lets's play"
Let’s create a Letsplay
intent, so we can get to the Rules
state from any other state when the user sends the message Let's play
.
To view the intents settings, go to the CAILA > Intents tab on the control panel. Create an intent and specify phrases in the Training phrases field: let's play
, play
, i want to play
.
Next, perform a transition to the nested Agree
state using go!
tag. The bot will move to the appropriate state Yes
or No
depending on the user’s intent.
No
The bot moves to the No
state if the user sends a negative answer. Create a new No
intent and specify phrases in the Training phrases field: I don't want to play
, no
, nope
. If the bot receives one of these phrases, it will move to No
state immediately.
To make the bot better understand the users, add more phrases to the Training Phrases field. The more phrases there are, the more likely the bot will correctly detect user’s intention.
Yes
If the user’s answer is positive, the bot moves to Yes
state. Create a Yes
intent and add as many training phrases expressing agreement as possible. For example, yes
, agree
, want
. Now, if the bot receives one of these phrases, it will move to the Yes
state.
Number
To move to the next state, it is important to get a number from the user. If they don’t enter a number, the bot will send them a request for one. To do this, let’s use slot filling and create a Number
slot. Slot filling is used when the bot needs to get some specific information from the user, without which it cannot proceed. In our case, this is a number.
Each slot has the Entity field. It defines the type of data that will be placed into the slot. We will use @duckling.number
system entity via the Duckling service.
To connect the Duckling
system entity, go to the CAILA> Entities > System Entities tab on the control panel. Find @duckling.number
in the list of available entities and turn the switch on.
Return to Agree
intent settings. In the Entity field choose @duckling.number
. Set the Required attribute to active and specify clarifying questions in the Questions field. For example:
Make a guess
What's your guess?
The bot will send as many clarifying questions as you’ve specified in the chatbot.yaml
file, when the required slot is not recognized in the user’s message.
The filled slot will be stored in the $parseTree._Number
variable in the CheckNumber
state.
Game
According to the rules, the bot randomly generates a number. So, we need to write a script, in which we pick a random number and then execute transition to the next /CheckNumber
state.
state: Game
script:
# generate random number
$session.number = $jsapi.random(100) + 1;
# go to /CheckNumber state
$reactions.transition("/CheckNumber");
Generating a random number
As we’ve mentioned before, the bot randomly generates a number from 0 to 100.
Let’s write a random number generator using a built-in $jsapi.random()
method. This method returns integer values from 0
to max
(not including max). Therefore, we will write 100
as an argument and add 1
to the random number we get. Add the following code to the script
tag
$session.number = $jsapi.random(100) + 1;
In JS API the $session
variable is used for storing any session data. Assign random number generator function to the $session.number
variable. We will compare the number stored in the $session.number
with the user’s input number.
To make sure the number has been randomly generated by the bot, we will display it in a message My number is * number *
. Insert the following line into the script:
$reactions.answer("My number is {{$session.number}}");
Transitions between states
The $reactions.transition
function executes transition into the specified state. In our case, specify the /CheckNumber
state for the transition:
$reactions.transition("/CheckNumber");
$jsapi
and types of variables in JS APICheckNumber
Configuring intent
Go to the CAILA > Intents tab on the control panel. Create a /Number
intent and specify the phrase @duckling.number
in the Training phrases field, so the bot can recognize and save the entered number.
Conditions execution
state: CheckNumber
intent: /Number
script:
var num = $parseTree._Number;
if (num == $session.number) {
$reactions.answer("You won! Let's play one more time?");
$reactions.transition("/Rules/Agree");
}
else
if (num < $session.number)
$reactions.answer(selectRandomArg(["Bigger!", "My number is bigger than yours"]));
else $reactions.answer(selectRandomArg(["Smaller!", "My number is smaller than yours", "Hint: the number is smaller than yours"]));
$parseTree._Number
contains the number that the user entered. Assign this number to a new num
variable.
Now, compare the generated number with the user’s number using the if/else
statement. If the numbers are equal, the bot will write: You won! Let's play one more time?
and will switch the state to /Rules/Agree
.
Hints
If the user’s number is smaller than the generated one, the bot will randomly choose one of the phrases from the selectRandomArg()
array using $reactions.answer()
. For example, My number is bigger than yours
.
selectRandomArg()
function is used to display a random answer from the array. To use this function, connect common.js
JS-files using require
at the beginning of the main.sc
file.
require: common.js
module = sys.zb-common
Then list the answer choices in selectRandomArg()
by using a comma. For example:
$reactions.answer(selectRandomArg(["Smaller!", "My number is smaller than yours", "Hint: the number is smaller than yours"]))
The last else
statement will be executed if the user’s number is bigger than generated. The bot will randomly choose one of the phrases from the selectRandomArg()
array.
Therefore, the user will stay in the CheckNumber
state until they guess the generated number.
NoMatch
Managing the context
People can make mistakes when typing commands and send the bot a text that differs from all the considered options. For this purpose, the NoMatch
state is used, which processes the end of the script in case the user message does not fit any of the described stages.
When the user enters a message, for example, It's sunny outside
, the noMatch
event is activated, which is specified under the event!
tag in the NoMatch
state.
state: NoMatch || noContext=true
event!: noMatch
random:
a: I don't understand you
a: What do you mean?
a: I don't get you
If we get into this state, for example, from the Rules
state and the user sends the message want
, the bot will answer I don't understand you
. Despite the fact that the entered message corresponds to Yes
intent, the transition will not occur because the context of the dialog has changed. So, nested states from Agree
state are not available.
To prevent changing the context when the user gets into the NoMatch
state, set the noContext
flag to true
. Now, when the user goes into the NoMatch
state, the context will not change, the message want
will be processed in the context of the Agree
state.
Random reactions
Dsl language has the random
tag used to diversify chatbot reactions.
Let’s make the bot’s responses more varied in cases when the user gets into the NoMatch
state. To do this, list the appropriate answer options in the random
tag.
random:
a: I don't understand you
a: What do you mean?
a: I don't get you
Only one of the answers will be displayed as a result of the transition to the NoMatch
state.
Next, move on to testing the script.