Chitchat is not working during form custom slot mapping

chitchat works fine during pre-defined slot mapping, but it fails during custom slot mapping, This is the rule I use for my form

- rule:  Room Booking form when other no other forms are active
  condition:
  - active_loop : null
  steps:
  - intent: room_booking
  - action: hotel_booking_form
  - active_loop: hotel_booking_form

- rule: Deactivate Room Booking Form
  condition:
  - active_loop: hotel_booking_form
  steps:
  - action: hotel_booking_form
  - active_loop: null
  -  slot_was_set:
       - requested_slot: null
  - action: action_clear_data

Likewise i have two rules for other two forms. The rule for chitchat is as follows

- rule: respond to FAQs
  steps:
  - intent: faq
  - action: utter_faq
- rule: respond to chitchat
  steps:
  - intent: chitchat
  - action: utter_chitchat

should I have to write chitchat rules for each and every form, separately?

@fkoerner

To intentionally reject the form execution, you can also return an ActionExecutionRejected event as part of your custom validations or slot mappings.

To handle situations that might cause a form’s execution to be rejected, you can write rules or stories that include the expected interruptions. For example, if you expect your users to chitchat with your bot, you could add a rule to handle this:

rules:

  • rule: Example of an unhappy path condition:

    Condition that form is active.

    • active_loop: restaurant_form steps:

    This unhappy path handles the case of an intent chitchat.

    • intent: chitchat
    • action: utter_chitchat

    Return to form after handling the chitchat intent

    • action: restaurant_form
    • active_loop: restaurant_form In some situations, users may change their mind in the middle of the form action and decide not to go forward with their initial request. In cases like this, the assistant should stop asking for the requested slots.

You can handle such situations gracefully using a default action action_deactivate_loop which will deactivate the form and reset the requested slot. An example story of such conversation could look as follows:

stories:

  • story: User interrupts the form and doesn’t want to continue steps:
    • intent: request_restaurant
    • action: restaurant_form
    • active_loop: restaurant_form
    • intent: stop
    • action: utter_ask_continue
    • intent: stop
    • action: action_deactivate_loop
    • active_loop: null

Hi, what behaviour are you seeing? I think your problem may be that this rule kicks in, rather than the chitchat rules.

- rule: Deactivate Room Booking Form
  condition:
  - active_loop: hotel_booking_form
  steps:
  - action: hotel_booking_form
  - active_loop: null
  -  slot_was_set:
       - requested_slot: null
  - action: action_clear_data

should I have to write chitchat rules for each and every form, separately?

No, you shouldn’t have to :slight_smile:

I have a form, in which few slots are filled by predefined slot mapping and some by custom slot mapping, when a prompt for custom slot mapping is asked and if the user respond with FAQ/chitchat , my bot doesn’t respond back with FAQ/chitchat, Instead it will ask the prompt for that slot. This happens only during custom slot mapping prompts.

I think the below rule will work, but i have 3 forms, so i would have to write 6 rules (faq and chitchat)

- rule: chitchat during hotel room booking
  condition:
  - active_loop: hotel_booking_form
  steps:
  - intent: chitchat
  - action: utter_chitchat
  - action: hotel_booking_form

Is there a better way to handle this? at least one single rule to handle all active forms?

- rule: respond to FAQs
  steps:
  - intent: faq
  - action: utter_faq
- rule: respond to chitchat
  steps:
  - intent: chitchat
  - action: utter_chitchat

The rules above will kick in if the form action is rejected. This might happen if a slot was requested, but then not filled, for example during a validation action. However, if you want the form loop to be picked up again, you will have to write those 6 rules you describe. This is also how we do this in our demo

In the above example it asks for slot name and slot check in, name is custom mapped slot and checkin in predefined mapping. During the prompt " what’s your name" (custom mapping), if a user respond with some faq question, the bot doesn’t reply with answer for that faq question, But during the prompt " what are the checkin and check-out time?" bot gives relevant faq reply.

I checked this demo, I have 3 forms so I should write 3 rules for each form , right? Or is it possible to write one single rule for any active loop?

I wrote rule like this , but the bot didn’t respond with faq, instead it continued asking prompt

- rule: respond to FAQs
  condition:
  - active_loop: hotel_booking_form
  steps:
  - intent: faq
  - action: utter_faq
  - action: hotel_booking_form

@fkoerner

What does your custom slot mapping look like? Is it rejecting the slot when you ask for check in times?

"what are the check -in and check-out time " is an faq

This is how my custom slot mapping looks like

def name_change( dispatcher, tracker):
    extractor_list = tracker.latest_message['entities']
    old_name = tracker.get_slot("person")
    person_name = None
    if len(extractor_list)>0:
        confid = 0
        for elements in extractor_list[::-1]:
            if elements['entity']== 'PERSON':
                if elements['extractor'] == 'SpacyEntityExtractor':
                    person_name = elements['value']
                    break
                if elements['extractor'] == 'DIETClassifier':
                    if elements['confidence_entity'] > confid:
                        person_name = elements['value']
    if not old_name:
        return person_name

    if person_name:
        dispatcher.utter_message(text=f"Hey!! Your name have been changed to {person_name}")
    else:
        dispatcher.utter_message(text=f"Yes you can change your name")
    return person_name

class ValidateHotelBookingForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_hotel_booking_form"

    async def required_slots(
            self,
            slots_mapped_in_domain: List[Text],
            dispatcher: "CollectingDispatcher",
            tracker: "Tracker",
            domain: "DomainDict",
    ) -> Optional[List[Text]]:
        if tracker.get_slot('state_inter') is False:
            return['state_final']
        if tracker.get_slot('state_final') is not None:
            return[]
        custom_slot_list = ["hotelname","person"]
        for i in custom_slot_list:
            if not tracker.get_slot(i) :
                return [i] + slots_mapped_in_domain
        if tracker.get_slot("checkin") and tracker.get_slot("checkout") and not tracker.get_slot("count"):
            return ["count"]
        if room_details_filled(tracker):
            return ['state_final']
        return slots_mapped_in_domain

    def extract_person(self, dispatcher, tracker, domain):
        person_name = name_change(dispatcher, tracker)
        return{"person":person_name}

    async def validate(self, dispatcher, tracker, domain):
       
         if intent == "name_negative":
            person_name = name_change(dispatcher, tracker)
            return [SlotSet('person', person_name)]

name_negative is an intent that means user wants to change his name

Looks like the problem is that you’re not rejecting the requested name slot

how do I reject a requested slot?

You can do this in a form validation action. See here

I tried this but It didn’t work. If I return None, Bot again ask prompt instead of responding with FAQ response.

return empty dict if slot is not filled

return {}