Hi Johannes,
Thanks for your detailed reply.
We have followed your exact guidelines, but the new trained-model appears to detect only the intent (‘integer’) and not the role itself.
As a result, all the slots (age, weight, height) are set with the same value (age):
- utter_ask_age: “how old are you?”
- user responds with an answer, e.g. “37”
- intent is detected as ‘integer’ (no role)
- age, weight and height are set to “37” (second from_entity mapper, without role)
We are currently mainly using the RasaX edition. Could it be that it’s a RasaX issue, i.e. roles are not supported there (we got this impression from this discussion)?
We were looking for a way to tell RASA that age shall be set after utter_ask_age, weight shall be set after utter_ask_weight and finally height shall be set after utter_ask_height.
We eventually ended-up with getting the desired behavior with requested_slot and with validate methods:
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 {
"age": [
self.from_entity(entity="integer", role="age"),
self.from_entity(entity="integer"),
],
"weight": [
self.from_entity(entity="integer", role="weight"),
self.from_entity(entity="integer"),
],
"height": [
self.from_entity(entity="integer", role="height"),
self.from_entity(entity="integer"),
],
}
def validate_age(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate age value."""
requested_slot = tracker.get_slot("requested_slot")
age_slot = tracker.get_slot("age")
if requested_slot == "age":
return {"age": value}
elif age_slot:
return {"age": age_slot}
else:
return {"age": None}
def validate_weight(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate weight value."""
requested_slot = tracker.get_slot("requested_slot")
weight_slot = tracker.get_slot("weight")
if requested_slot == "weight":
return {"weight": value}
elif weight_slot:
return {"weight": weight_slot}
else:
return {"weight": None}
def validate_height(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate height value."""
requested_slot = tracker.get_slot("requested_slot")
height_slot = tracker.get_slot("height")
if requested_slot == "height":
return {"height": value}
elif height_slot:
return {"height": age_slot}
else:
return {"height": None}
With the following story:
## Introduction
* Bot_introduction
- profile_form
- form{"name":"profile_form"}
- slot{"requested_slot":"gender"}
* inform{"gender":"male"}
- profile_form
- slot{"gender":"male"}
- slot{"requested_slot":"age"}
* inform{"integer":"38"}
- profile_form
- slot{"age":"38"}
- slot{"requested_slot":"weight"}
* inform{"integer":"72"}
- profile_form
- slot{"weight":"72"}
- slot{"requested_slot":"height"}
* inform{"integer":"172"}
- profile_form
- slot{"height":"172"}
- slot{"requested_slot":null}
- form{"name":null}
- utter_slot_getter_username
This appears to be a proper workaround for our end.
Thanks,
Newt Team