Skip to main content

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.

Intent Letsplay

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.

Intent No

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.

Intent Yes

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.

System entity Duckling

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.

Slot filling

The filled slot will be stored in the $parseTree._Number variable in the CheckNumber state.

tip
Learn more about slot filling

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");

CheckNumber

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.

Intent 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.