Specify different requested slots based on intent that started the form

Hi there!

I have a simple contact form that asks the user for an email, phone number, and address. We use that form in various parts of our bot. Depending on the intent that triggered this form, I would like to change the requested slots and only ask for the email and phone number.

How could I achieve this?

My initial idea was to use the trigger_message from the tracker.active_form in the required_slots function. However, this does not work as the trigger message is not set in the first pass of the form (ie: the first question) and it is also set to the intent of the previous answer afterward. It is only correctly set to the real form trigger for the second question.

How could I achieve what I’d like to do? Did I misunderstand what’s in the tracker.active_form?

I really do not want to create yet another form (even by inheriting from the main one). Indeed, it is so painful to deal with unhappy paths such as FAQs in forms that I do not want to add yet another form for something that simple.

Maybe @Ghostvv would know? I believe you implemented the trigger_message in forms?

Thanks a lot and cheers! Nicolas

Sounds like you’re looking for the requested_slots() method in the FormAction class.

According to the Formbot Tutorial (See Step 4) you can implement some custom logic to decide what slots your form should ask for.

You’re looking to implement this method in your FormAction class:

def required_slots(tracker):
    # type: () -> List[Text]
    """A list of required slots that the form has to fill"""

    # This line MAY OR MAY NOT WORK since firing the form is also an intent, 
    # but the general idea is you want to grab the latest intent that was fired. 
    triggering_intent = tracker.latest_message.get('intent')['name']


    if triggering_intent == 'some_intent':
        return ["slotA", "slotB", "slotC"]
    elif triggering_intent == 'some_other_intent':
        return ["SlotA", "SlotC", "SlotD"]
    elif...
    .
    .
    .
    .
    else:
        return ["SlotA", "SlotB", "SlotC", "SlotD"]
2 Likes

Hi @ActuallyAcey, thanks a lot for your response!

In the end, I had to do something between what you are suggesting and what I initially thought. The problem is that tracker.latest_message will only work for the very first question as required_slots is run at every turn. I had to combine this with tracker.active_form which is only set after the first turn (not sure why though).

In order to get the trigger intent, I therefore used:

def get_trigger_intent(tracker):
    return tracker.active_form.get("trigger_message", {}).get("intent", {}).get("name") or tracker.latest_message.get("intent", {}).get("name")

Putting this into the code you suggested functions correctly :slight_smile:

Cheers, Nicolas