Easy Steps 2 Use form action with your Rasa Chat-bot

1
0

OVERVIEW

In this post, you will learn how to fill the slots and to use them further using the Form action. Now you must be thinking that if we are going to fill the slots only then why are we using the form action for that. So the reason is we want to build an effective and reliable chatbot with lesser efforts than before. So, what is forms and form action and how it builds an effective and reliable chatbot with fewer efforts?

What are Form Action?

One of the most common conversation patterns is to collect few pieces of information from a user in order to do something (like booking a restaurant, calling an API, searching the database, etc.). This is also called slot filling. If you want to collect multiple pieces of information in a row, we recommended that you to create a Form Action. This Form Action is the single action which have the logic to loop over the required slots and ask the user for the information until all the slots are filled. So, this is the most important and the required logic in the chatbot to save many lines of code and also to save efforts for the same process.

So, how do we do it to with rasa chatbot to make it effective, reliable with less efforts. For the form action we need to make the updation in the project files, which are, config.yml, actions.py, stories.md and domain.yml.

Let’s start one by one and understand the basic functionality of each of them:

Setup Configuration

Firstly, we need to include the FormPolicy in to the configuration file to make the whole process function properly. In this way,

 policies: 
 - name: FormPolicy

The FormPolicy is extremely simple and just always predicts the form action. This comes into action when the form action is called for the first time.

You can also check this video for more clarification,

Adding the stories

To add the stories as per the forms is the most important step to call the Form Action and to repeatedly ask the user for the information until all the slots are filled. Now lets understand it more briefly with the example problem that we are going to cover in this post. Like we will add the below story or let’s say the happy path,

## happy path
* network_issue
  - form_info
  - form{"name": "form_info"}
  - form{"name": null}
* affirm
  - utter_goodbye

So, above is the happy path for calling the FormAction. In this story “network_issue” is the user intent to which the bot will redirect to the Form Action which is “form_info”. Here, “form{“name”: “form_info”}” is used to activate the form and “form{“name”: null}” is used to deactivate the form again. Once the FormAction is activated, the boty can execute any kind of action outside the form.

The above “happy path” means that once the FormAction is active it can fo outside of the form and perform any action until all requested slots are filled without interruption. For example, if the user starts the conversation and says “My name is Ashish and I am using One Plus mobile.” Then the slots “NAME” and “BRAND” are automatically filled so, the bot will not ask you the question related to these slots.

To make your story work in such a way your first step is to set your slots as unfeaturized. But if the slots are not of the type unfeaturized or let’s say it’s featurized, then in that case you have to include slot{} events to show these slots being set. Not it seems to be confusing like when to use the form and when to use slot, So, to make it easier it’s not compulsory that you have to add the stories manually, you can also add them using the Interactive learning.

So this was all about adding the stories as per the FormAction. Similarly, you can add more stories according to the chatbot architecture.

Updating the actions file

In the above story, you have seen we have added the happy path as per the form action. Now we will learn what actually is happening when the form action is called. To do this you first need to define three methods:

  • name: the name of this action (form_info in our case)
  • required_slots: a list of slots that need to be filled for the submit method to work.
  • submit: what to do at the end of the form, when all the slots have been filled.

Here, what happens is firstly when the FormAction is called for the first time, then form gets activated and FormPolicy jumps in. The FormPolicy is extremely simple and just always predicts the form action. To identify which form has been called the first method is to be added to the to the actions.py file, i.e.,

def name(self) -> Text:
"""Unique identifier of the form"""
return "form_info"

When the bot identifies which FormAction is to be called then it moves to the next static method which is requested_slots where all the slots are set in the order to be called when requested and here with respect to these requested slot names an utter_ask_{slot_name} is called from the domain.yml file where all the bot response are set. The static method that is to be added to the action file is :

@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""A list of required slots that the form has to fill"""
return ["NAME", "BRAND"]

Here you can see we are returning the list for the static method and this list specifies the order of the slots to be requested to fill values for each of them. So, it simply means firstly utter_ask_NAME will be called and vice versa.
Once all the slots are filled, submit() method is called where we can use the collected information in whatever way we want use it. For example, asking for booking confirmation with your details. This method will be added in actions.py file,

def submit(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
"""Define what the form has to do
after all required slots are filled"""
# utter submit template
dispatcher.utter_message(template="utter_submit", name=tracker.get_slot('NAME'),
handset=tracker.get_slot('BRAND'))
return []

Slot Mapping

If you do not define slot mappings in the actions file, slots will be only filled by the entities with the same name as the slot that is picked up from the user input. Slots can be picked with the single entity but FormAction supports inputs like yes/no questions and free-text input. The slot_mappings method defines how to extract slot values from user responses. Add the below method to your action file to extract the required information from the user response.

def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message
or a list of them, where a first match will be picked"""
return {
"name": self.from_entity(entity="NAME", intent='my_name_is'),
"headset": self.from_entity(entity="BRAND", intent="headset"),
}

The predefined functions work as follows:

  • self.from_entity(entity=entity_name, intent=intent_name) will look for an entity called entity_name to fill a slot slot_name regardless of user intent if intent_name is None else only if the users intent is intent_name.
  • self.from_intent(intent=intent_name, value=value) will fill slot slot_name with value if user intent is intent_name. Note: Slot will not be filled with user intent of message triggering the form action. Use self.from_trigger_intent below.
  • self.from_trigger_intent(intent=intent_name, value=value) will fill slot slot_name with value if form was triggered with user intent intent_name.
  • self.from_text(intent=intent_name) will use the next user utterance to fill the text slot slot_name regardless of user intent if intent_name is None else only if user intent is intent_name.
  • If you want to allow a combination of these, provide them as a list as in the example above

Once you understand this just add the above methods inside a class as shown below:

class ActionFormInfo(FormAction):
def name(self) -> Text:
"""Unique identifier of the form"""
return "form_info"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""A list of required slots that the form has to fill"""
return ["NAME", "BRAND"]
def submit(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
"""Define what the form has to do
after all required slots are filled"""
# utter submit template
dispatcher.utter_message(template="utter_submit", name=tracker.get_slot('NAME'),
handset=tracker.get_slot('BRAND'))
return []
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message
or a list of them, where a first match will be picked"""
return {
"name": self.from_entity(entity="NAME", intent='my_name_is'),
"headset": self.from_entity(entity="BRAND", intent="headset"),
}

Updating Domain file

Now to link the core and nlu to the action file add the following line of code to your existing chatbot in domain.yml file

forms:
- form_info
slots:
BRAND:
type: unfeaturized
NAME:
type: unfeaturized
requested_slot:
type: unfeaturized
templates:
utter_ask_BRAND:
- text: Sir, I would like to tell you that your issues will be resolved. Could I
please know which handset you are using?
utter_ask_NAME:
- text: Ok. Please provide your fist name?
utter_submit:
- text: Your name is {name} and your handset is {handset}

Execution
When you are done with the above steps and have understood all the things clearly then train your model and test it

$ rasa train
$ rasa x
or
$ rasa shell –debug # to check the backend functionality of the form action.

You will see the output something like this in the debug mode.

form action in rasa chatbot

After this execution, you will really feel that you have reduced the number of lines of code and have built an effective and reliable chatbot with different features added to it.

Time to wrap up now. Hope you liked our content on How to use form action in Rasa chatbot. See you in our next blog, thanks for reading our blog and do leave a comment below to help us improve the content to serve you all of our experience with you. Stay tuned with us for more Rasa Chatbot contents.

Also check out our other playlist Rasa Chatbot, Internet of things, Docker, Python Programming, etc.
Become a member of our social family on youtube here.

Ashish Saini
Ashish Saini

I am a software developer for Python/Machine Learning. Also, I’m Rasa Hero at Rasa. Also, I’m a youtuber where I regulary uploads the videos to help this generation learn about the technology just like they are playing games.

Leave a Reply