Slot values not persisting after validation

This is related to issues Utterance twice for form validation and Forms not requesting list slot.

I’m doing validation in a custom action and when a value is validated and set, it’s being reset at the next input and not persisting.

Following the documentation I did this:

    def validate_list_slot(self, slot_value, dispatcher, tracker, domain):
        if not slot_value:
            return {'list_slot': None}
        return {'list_slot': slot_value}

This, of course, failed because it tries to validate on every input of the form so unless a new value was coming in to fill that slot, it was reset to none. Fair enough. So I rewrote it to this:

    def validate_list_slot(self, slot_value, dispatcher, tracker, domain):
        list_slot = tracker.get_slot('list_slot')
        requested_slot = tracker.get_slot('requested_slot')
        print('-'*20)
        print('slot_values', tracker.current_slot_values())
        print('intent', tracker.get_intent_of_latest_message())
        print('list slot', list_slot)
        print('requested slot', requested_slot)
        if requested_slot == 'list_slot':
            print(1)
            if not list_slot:
                print(2)
                return {'list_slot': None}
            else:
                print(3)
                return {'list_slot': slot_value}
        # When the form is initiated it sets the list slot to an empty list so it will never prompt, so we reset it to None at the beginning of the form
        elif requested_slot is None:
            print(4)
            return {'list_slot': None}
        else:
            print(5)
            return {}

This should be safe as I’m only setting the list value when it’s the requested slot. Or so I thought. I have all of those print commands because something bad was happening. Let me show you:

--------------------
slot_values {'list_slot': [], 'text_slot': None, 'requested_slot': None, 'session_started_metadata': None}
intent form_initializer
list slot []
requested slot None
4
--------------------
slot_values {'list_slot': ['rice'], 'text_slot': None, 'requested_slot': 'list_slot', 'session_started_metadata': None}
intent form_initializer
list slot ['rice']
requested slot list_slot
1
3
--------------------
slot_values {'list_slot': [], 'text_slot': 'mexican', 'requested_slot': 'text_slot', 'session_started_metadata': None}
intent form_initializer
list slot []
requested slot text_slot
5

See how on that third entry list_slot becomes an empty list BEFORE anything in the validation function can do anything.

Is there a way to avoid this slot reset? I’m not sure what is causing it or where it is happening.

The files are the same as in Forms not requesting list slot, so I hope you can excuse me not replicating them here, also. But if needed I can copy them here.

1 Like

Is this happening with all slot types or just lists?

Did you implement the required_slots() methods?

@ChrisRahme Just happening with lists and I haven’t done anything special with required_slots other than defining them in the domain.

Below I’m using append() instead of setting the slot from one value (that’s what you should do anyway, but not sure if that’s the root of the problem here):

    def validate_list_slot(self, slot_value, dispatcher, tracker, domain):
        list_slot = tracker.get_slot('list_slot')
        requested_slot = tracker.get_slot('requested_slot')

        print('-'*20)
        print('slot_values', tracker.current_slot_values())
        print('intent', tracker.get_intent_of_latest_message())
        print('list slot', list_slot)
        print('requested slot', requested_slot)

        if requested_slot == 'list_slot':
            print(1)
            if not list_slot:
                print(2)
                return {'list_slot': list_slot}
            else:
                print(3)
                list_slot.append(slot_value)
                return {'list_slot': list_slot}
        # When the form is initiated it sets the list slot to an empty list so it will never prompt, so we reset it to None at the beginning of the form
        elif requested_slot is None:
            print(4)
            return {'list_slot': list_slot}
        else:
            print(5)
            return {}

Here I returned list_slot instead of None, but if you want to fully reset the slot vs not changing it, use None. So it’s the same as returning {} I guess.

@ChrisRahme If I don’t set the slot to none, it doesn’t prompt for it (Forms not requesting list slot). Appending does not fix the issue. I’m still getting the same output. It’s still entering the validation empty. I’m going to try writing another validation for the text slot to see if I need to validate every field as it goes. Though, if I do need to do that, it’s quite the damper on my spirits and enthusiasm.

1 Like

Ah yes! So stupid of me haha.

Maybe use another list slot that you will append to in the validation from a requested slot, and keep returning None unless, e.g., the length of the list is higher than or equal to 5.

1 Like

Creating another list slot works, so long as it’s not mentioned anywhere in the form definition. I didn’t want to have to go down that path as I have a few list slots in the real project, but if that’s the only work around, I guess that’s what I have to do.

I’ll be creating an issue in github over this. I thought I was doing something wrong, but apparently not.

1 Like

Thanks for the help, @ChrisRahme

1 Like

Glad to be of help! :slight_smile:

And yes, I think creating an issue is the way to go - I see nothing wrong in your code.