Form - wrong intent detection

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

1 Like