Rasa Optional Slots Adalah Aplikasi Apa
Why did we change this?
In short: while our previous methods of filling slots could save some development time in the best case scenario, the cost of this time savings was unexpected behaviour, duplicated effort and developer confusion.
If you used slots in previous versions of Rasa, you may have noticed that there were several ways to fill them. If you had an entity that shared a name with a slot, whenever that entity with that name was extracted it would automatically fill the slot. The downside of this is that it led to numerous problems. For example, in this one, a slot was auto-filled through the entity and slot name matching but interfered with correctly asking for that slot in a later form. And in this one an extracted entity was erroneously filling multiple slots simultaneously.
Perhaps the most commonly unexpected behavior with automated slot filling was in updating slots over the course of a conversation. An entity would be extracted that unexpectedly updated a slot when it was not intended and, since this behavior happened implicitly, it led to a lot of developer frustration.
You could also specify how a slot would be set in a form. However, if you had several similar forms that used the same slot mapping you needed to specify the exact same mapping every time. This resulted in duplication of the same slot mappings across multiple forms, as described in more depth in this issue.
In addition to these problems, having two separate ways to set slot mappings was confusing for developers learning Rasa. It also meant that you needed to dig into multiple files to understand why slots were being set in a certain way. The automated filling of slots also made it easy to confuse entities (extracted spans of user generated text) with slots (variables you store and reference over the course of a conversation). While entities can be used to set slots, entity extraction is not always the best way to set various slots. For something like “accept” or “decline”, for example, it would be easier to use an intent.
In order to address these issues, in Rasa Open Source 3.0 we have a new way of specifying slot mappings: a single, global slot mapping which is specified in the domain file. Internally, slots are now set by a new built in action, action_extract_slots. It is run at the end of the NLU pipeline but before the dialog manager and loops through each slot and it’s mappings and sets them as needed.
The new approach has a number of benefits.
This change does mean slightly more upfront work for a simple assistant if all your slots were set by a single entity, since you will need to explicitly describe how the slots are set. On balance, however, we believe that this change will end up saving considerable time and frustration.
Migration guide & docs
You are of course free to migrate slots by hand from your 2.0 chatbot, but the simplest way to migrate is to use our automatic migration tool using this command:
This will create a 3.0 domain file at the path you specify as well as backing up your current domain file.
If you have a more complex use case check out the documentation for additional details. or ask on the forums. We hope you find the new, explicit slot mappings a helpful update and if you have any questions, please reach out to us on the forums.
What do the new slot mappings look like?
Starting in 3.0, you will need to specify how each slot will be filled in the domain file under the “slot” section. For slots filled from entities, the new format looks like this:
This will explicitly map the entity “cuisine” to the slot “cuisine” when the relevant entity is detected in the text.
For slots filled from intents, the new format will look like this:
Here the outdoor_seating slot will be filled with the value “true” if the affirm intent is detected and “false” if the deny intent is detected. This type of mapping will be most helpful for either very specific intents or if your assistant is very simple.
However, if you only want outdoor_seating to be filled when the relevant intents show up in a form, you’ll need to add additional specifications.
- active_loop: restaurant_form
requested_slot: outdoor_seating
- active_loop: restaurant_form
requested_slot: outdoor_seating
The other major change is in how forms are specified in the domain file. Rather than having to list how each slot in the form will be filled you now nearly need to list the slots you need (since the mappings have already been defined). As a result, the new form syntax much simpler than before.
I wonder what’s the best way of creating slots, that are not obligatory.
What I mean by that? Let me define a form as presented below:
Now, in order to perform an actual search in my database I need either ‘5_service’ or ‘6_specialist_name’ or ‘7_specialization’. I don’t need all 3, although if user provides them in one sentence, then that’s not a problem. I will run a DB search with 3 parameters, not 1 or 2. So how to make form take this into account? It should accept just one response with either 1,2 or 3 parameters (slots). If just one is provided, then it shouldn’t investigate other two? And if two or three are given (in one response), then that’s okey as well.
I saw this issue add possibility to define optional slots for forms · Issue #6939 · RasaHQ/rasa · GitHub, but as I understand - it’s currently on hold, so… What’s the best alternative?
There are two solutions, that I’ve thought of:
What I don’t like about these solutions is neither of them seems to be an elegant one.
You could write validation methods for each of the three slots which fill the other two slots if there’s enough information already. That way it will consider them all filled; they won’t be “optional”, but the user won’t be prompted for them.
Yes. This solution works pretty well Thanks!
The default implementation of the Form Action mandates that all the fields listed in required_fields have to be filled before the submit method is triggered. But I have a slightly different scenario where submit can be triggered as long as some of the slots are filled. For ex: I have the following slots - city, state, country, category, product type. I just need one of city / state / country and one of category / product type to be filled before calling the submit method. I implemented a complicated way of doing it by making required_fields a list of lists as follows: [[city, state, category], [category, skills]] & checking if one slot in each of the list is filled. But is there a better way of implementing this? Any help would be appreciated
Basically I would make an option slot by doing this:
NOT adding it to required_slots
Adding it to slot_mappings
So if the slot is found on the text it would map anyway even when not required. But this would mean it would not ask for the slot. That means if you want to actively ask for it. The best way would be to put it on required_slots and give an “skip” option. It could be a quick-reply for example.
In your case specific case I would do one of the following:
Put everything on required and slotmapping. Add “request_next_slot” and “validate” to the method. On request_next_slot, I would check if at least one of the city/state/country was mapped if yes I would pass in the return: return [SlotSet(REQUESTED_SLOT, slot)] where “slot” would be equal to category or product. Otherwise if category or product was also filled you would return None
Hi @Sekhar-jami can u explain more on how to implement optional slots using your approach list of lists…In my case i just want to check for 2 slots (account number/trans ID)…so i feel your approach will do the job for me.
there are several ways to achieve this @custodio suggests a working example. For the sake of simplicity and if there is no need to validate the slots through the FormAction validators, you could also use a CustomAction instead of a FormAction by using:
So you just would have to decide when to trigger whatever is triggered in your previous submit method.
You can’t perform that action at this time.
Slots in Rasa Open Source 2.x
Note: This is material for Rasa 2.x. The syntax has updated slightly in Rasa 3.0 so we recommend new users to check the new course on Custom Actions found here.
In Rasa, slots are your long term memory in a conversation. If there's any information you'd like to store for later use, you'd typically want to store it in a slot. It's important to understand that a slot is not the same thing as an entity. You could store any information in a slot, even if no entity has been detected. That said, it is very common to fill a slot value with an entity value.
If you want to define a slot, you'll need to define it in your domain.yml file.
influence_conversation: false
You'll notice that in this configuration we've added a influence_conversation tag. The reason is that slots can influence a story. You might have something like this in your stories.yml file.
- story: booking a flight ticket
- intent: book_a_ticket
- destination: Toronto
If your slots are configured to influence the flow of the conversation, you have to include them in your training stories.
Typically, your slot values will be set by detected entities. In these situations your domain.yml file should also include entities.
influence_conversation: false
This way, when an entity is detected it can fill in the slot value. You can also set slot values with custom actions, but we'll discuss how to do that in a later video.
By default, slots that have matching entity names will automatically be filled with the values of those entities. You can disable this behaviour by changing the configuration of the auto_fill parameter to false.
In Rasa, slots have types. This is useful, because certain types of information are better served as a number than a string of text.
Slot type text can be used to store any text information. It can influence the conversation based on whether or not the slot has been set.
influence_conversation: true
Slot type boolean can be used to store information that can get the values True or False.
influence_conversation: true
Slot type categorical can be used to store values that can get one of a predefined set of possible values.
Slot type float can be used to store numerical values.
List slots can be used to store a list of values. When configured, only the presence of the slot can have influence on the flow of the conversation. The values themselves won't be taken into account.
The "any" slot type can be used to store any arbitrary values. Slots of this type don’t have any influence on the conversation flow which means that the value and the presence of the slot doesn’t have any influence on how the conversation goes.
Finally, it's good to know that you can also set a default value on a slot by configuring the initial_value parameter. The value will be assigned to the slot from the beginning of the conversation and can be reset later on by NLU or custom actions.
Try to answer the following questions to test your knowledge.
Note: This is material for Rasa Open Source 3.x. If you're interested in the content for Rasa Open Source 2.x, please see the archived version of this lesson here.
In Rasa, slots are your long term memory in a conversation. If there's any information you'd like to store for later use, you'd typically want to store it in a slot. It's important to understand that a slot is not the same thing as an entity. You could store any information in a slot, even if no entity has been detected. That said, it is very common to fill a slot value with an entity value.
If you want to define a slot, you'll need to define it in your domain.yml file. In general slots can be defined in two ways: using NLU or using a custom. If you're using entity extraction via NLU models then you could extract a slot via a configuration like:
influence_conversation: false
Alternatively, if you're using a custom action to set slots. This is discussed in the custom actions segment of this course.
You'll notice that in these configurations that we've added a influence_conversation tag. The reason is that slots can influence a story. You might have something like this in your stories.yml file.
- story: booking a flight ticket
- intent: book_a_ticket
- destination: Toronto
If your slots are configured to influence the flow of the conversation, you have to include them in your training stories. These slot_was_set events will now be included as training data for the machine learning pipelines in your assistant. Note that you're able to declare multiple values for a slot in a story via the or-operator.
- story: booking a flight ticket
- intent: book_a_ticket
- destination: Toronto
- destination: London
Slot mappings allow you to define how each slot will be filled in. Slot mappings are applied after each user message. For example, let's say that we have an entity called entity_name that we only want to store in a slot if the intent of the user is make_transaction. Then we might configure our slot via;
intent: make_transaction
Alternatively, we might also declare that we only want to detect the slot value if the current intent is not check_transaction. That could be configured via:
not_intent: check_transaction
Slot mappings give you more control over when a slot is stored. This is great because it might prevent you from storing a value in a slot if the user is mentioning an entity out of context.
There are many different types of slot mappings. The most common ones are:
It's also good to know that there are different methods of extracting slots. It's not just entities that are supported.
You can store the full text the user has message as a slot value. This is is done via the from_text slot mapping.
The from_trigger_intent mapping will fill a slot with a specific defined value if a form is activated by a user message with a specific intent.
You can also use a custom action to set the slot value. If none of the predefined slot mappings fit your case, you can creat custom slot mappings using slot validation actions.
In Rasa, slots have types. This is useful, because certain types of information are better served as a number than a string of text.
Slot type text can be used to store any text information. It can influence the conversation based on whether or not the slot has been set.
influence_conversation: true
Slot type boolean can be used to store information that can get the values True or False.
influence_conversation: true
Slot type categorical can be used to store values that can get one of a predefined set of possible values.
Slot type float can be used to store numerical values.
List slots can be used to store a list of values. When configured, only the presence of the slot can have influence on the flow of the conversation. The values themselves won't be taken into account.
The "any" slot type can be used to store any arbitrary values. Slots of this type don’t have any influence on the conversation flow which means that the value and the presence of the slot doesn’t have any influence on how the conversation goes.
Finally, it's good to know that you can also set a default value on a slot by configuring the initial_value parameter. The value will be assigned to the slot from the beginning of the conversation and can be reset later on by NLU or custom actions.
Try to answer the following questions to test your knowledge.
Entities are automatically saved to slots that have the same name.
Let's create a new age entity:
Let's create a new intent as well:
and add it to domain.yml:
We need the chatbot's response as well:
The story now looks like this:
Let's see this in action:
The age entity was automatically saved to the age slot, because the name is the same. Also, you can see that slots can be overwritten. First, the value of the slot was 17 years and then 64.
If a form contains a slot that is filled before the form is activated, that slot is not asked anymore as part of the form loop.
To demonstrate this, let's create the following story:
Normally, the chatbot would ask "What is your email address?" to fill the email slot. But since the slot is filled beforehand, it asks only frequency and notifications.
You can learn more about slots in the documentation or in my previous article.
In the next chapter, we will look at rich responses, such as buttons and images.
Repository for this tutorial:
You can checkout the state of the repository at the end of this tutorial by running:
Hi there! I’m new here. Someone can help me with this issue?
I have three slots to fill
Deadline is optional.
What I want is… if the user send a message with all the three entities together that’s means that he want’s the deadline, so all slot must be filled. But, if he send a message with only the obligatory ones, to be sure he doesn’t miss the deadline, I have to ask for a deadline.
If the answer is a “deny” intent, submit only the obligatory ones (category and activity, e.g. deadline to None). Otherwise the user just send a deadline to fill the slot.
What I have done for the moment is setting a form like follow
but the behavior is not exactly what I’m looking for.
Take a look at the dynamic forms description on the forms page. You can customize required_slots for your deadline.
Explicit is better than implicit. -The Zen of Python, Tim Peters