FormAction: redo slot after asking for confirmation

Hi!

I have a FormAction and in the submit method I summarize the relevant slots and ask if the user wants to continue or change any of the slots. My approach was to create a change intent with the field name as entity and an action that resets the respective slot and then restarts the form.

## intent:change
- I need to change [priority](slot_to_change)
- [priority](slot_to_change)
- Let me change the [problem](slot_to_change) description
- [problem](slot_to_change)
- Change [user](slot_to_change)
- [user](slot_to_change)
* change{"slot_to_change": "priority"}
  - action_unset_slot
  - form{"name": "ticket_form"}
  - form{"name": null}
class UnsetSlotAction(Action):
    def run(.....):
        .....
        return [SlotSet(slot_to_change, None)]

However the form does not get reactivated. Am I not correctly unfilling the slot? When using rasa shell --debug I can see that the slot_to_change slot is filled and the requested slot is reset with the action above. After that, the requested_slots method of the FormAction is called, but the form does not reactivate.

Am I missing a detail or is this approach not possible?

An alternative approach I could imagine is creating an extra slot per slot like priority_slot_change_requested and implement the logic in the slot_mapping method. Anyway I’m not quite sure how to implement that and if that would work.

Help is appreciated. Thanks!

Hi, it seems to me like your approach in general is fine. A few questions to help you figure out why it doesn’t work:

In your UnsetSlotAction, what is the variable slot_to_change? From your description it sounds like there should be a line slot_to_change = tracker.get_slot("slot_to_change"), is that correct?

And what version of rasa-sdk are you using? / What do you mean by the requested_slots method of the FormAction? In the current Rasa SDK 1.10.2 there is no such method, and as far as I’m aware also not in older versions. Or did you mean required_slots or request_next_slot?

Can you maybe just post the full debug log?

Hi, thanks for the answer. Regarding slot_to_change yes thats correct. Since you said the approach in general is fine, I’ve created a minimal working example from scratch:

data/nlu.md:

## intent:greet
- hey
- hello
- hi
- hey there

## intent:affirm
- yes
- indeed
- of course
- correct

## intent:change
- change [name](slot_to_change)
- pls change [address](slot_to_change)
- change my [name](slot_to_change) pls
- switch [address](slot_to_change)

## intent:inform
- my name is [john](name)
- im [john](name)
- i live in [stuttgart](address)
- my address is [stuttgart](address)

data/stories.md:

## address change
* greet
  - test_form
  - form{"name": "test_form"}
  - form{"name": null}
* change{"slot_to_change": "address"}
  - action_unset_slot
  - form{"name": "test_form"}
  - form{"name": null}
* affirm
  - utter_goodbye

domain.yml:

intents:
  - greet
  - affirm
  - change
  - inform

entities:
  - name
  - address
  - slot_to_change

slots:
  name:
    type: unfeaturized
  address:
    type: unfeaturized
  slot_to_change:
    type: text
  
actions:
  - action_unset_slot

forms:
  - test_form

responses:
  utter_goodbye:
  - text: "Bye"

  utter_sum_info:
  - text: "Name: {name}; address: {address}; OK?"

  utter_ask_name:
  - text: "Name:"

  utter_ask_address:
  - text: "Address:"

session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true

actions.py:

from typing import Any, Text, Dict, List

from rasa_sdk import Action, Tracker, forms
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.events import EventType, SlotSet
import logging

class TicketFormAction(forms.FormAction):
    def name(self) -> Text: 
        return "test_form"
    def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, 
                domain: Dict[Text, Any]) -> List[Dict]:
        logging.info("submit")
        dispatcher.utter_message(template="utter_sum_info")
        return []
    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        logging.info("required_slots")
        return ["name", "address"]


class UnsetSlotAction(Action):
    def name(self) -> Text:
        return "action_unset_slot"
    def run(self, dispatcher: CollectingDispatcher, tracker: Tracker, 
                domain: Dict[Text, Any]) -> List[EventType]:
        logging.info("unset")
        slot_to_change = tracker.get_slot("slot_to_change")
        return [SlotSet(slot_to_change, None)]

After running rasa init the only other changes are adding the FormPolicy in config and the actions endpoint in endpoints.yml.

Versions:

> pip list | grep rasa
rasa                    1.10.5
rasa-sdk                1.10.1 
> python --version
Python 3.6.9

So here is the full output when running rasa shell --debug:

2020-07-03 13:47:45 DEBUG    rasa.model  - Extracted model to '/tmp/tmpng1llwrb'.
2020-07-03 13:47:45 DEBUG    rasa.cli.utils  - Parameter 'endpoints' not set. Using default location 'endpoints.yml' instead.
2020-07-03 13:47:45 DEBUG    rasa.cli.utils  - Parameter 'credentials' not set. Using default location 'credentials.yml' instead.
2020-07-03 13:47:45 DEBUG    rasa.model  - Extracted model to '/tmp/tmp7z23wccc'.
2020-07-03 13:47:46 INFO     root  - Connecting to channel 'cmdline' which was specified by the '--connector' argument. Any other channels will be ignored. To connect to all given channels, omit the '--connector' argument.
2020-07-03 13:47:46 DEBUG    sanic.root  - CORS: Configuring CORS with resources: {'/*': {'origins': [''], 'methods': 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT', 'allow_headers': ['.*'], 'expose_headers': None, 'supports_credentials': True, 'max_age': None, 'send_wildcard': False, 'automatic_options': True, 'vary_header': True, 'resources': {'/*': {'origins': ''}}, 'intercept_exceptions': True, 'always_send': True}}
2020-07-03 13:47:46 DEBUG    rasa.core.utils  - Available web server routes: 
/webhooks/rest                                     GET                            custom_webhook_CmdlineInput.health
/webhooks/rest/webhook                             POST                           custom_webhook_CmdlineInput.receive
/                                                  GET                            hello
2020-07-03 13:47:46 INFO     root  - Starting Rasa server on http://localhost:5005
2020-07-03 13:47:46 DEBUG    rasa.core.utils  - Using the default number of Sanic workers (1).
2020-07-03 13:47:46 INFO     root  - Enabling coroutine debugging. Loop id 92481752.
2020-07-03 13:47:46 DEBUG    rasa.model  - Extracted model to '/tmp/tmp3je2eke2'.
2020-07-03 13:47:47 DEBUG    rasa.utils.tensorflow.models  - Loading the model ...
2020-07-03 13:47:47.033836: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
2020-07-03 13:47:47 DEBUG    rasa.utils.tensorflow.models  - Finished loading the model.
2020-07-03 13:47:47 DEBUG    rasa.utils.tensorflow.models  - Building tensorflow prediction graph...
2020-07-03 13:47:52 DEBUG    rasa.utils.tensorflow.models  - Finished building tensorflow prediction graph.
2020-07-03 13:47:52 DEBUG    rasa.nlu.classifiers.diet_classifier  - Failed to load model for 'ResponseSelector'. Maybe you did not provide enough training data and no model was trained or the path '/tmp/tmp3je2eke2/nlu' doesn't exist?
2020-07-03 13:47:52 DEBUG    rasa.core.tracker_store  - Connected to InMemoryTrackerStore.
2020-07-03 13:47:52 DEBUG    rasa.core.lock_store  - Connected to lock store 'InMemoryLockStore'.
2020-07-03 13:47:53 DEBUG    rasa.model  - Extracted model to '/tmp/tmpugj58xaz'.
2020-07-03 13:47:53 DEBUG    pykwalify.compat  - Using yaml library: /home/kvn2fe/chatbots/venv/lib/python3.6/site-packages/ruamel/yaml/__init__.py
2020-07-03 13:47:53 DEBUG    rasa.utils.tensorflow.models  - Loading the model ...
2020-07-03 13:47:53 DEBUG    rasa.utils.tensorflow.models  - Finished loading the model.
2020-07-03 13:47:53 DEBUG    rasa.utils.tensorflow.models  - Building tensorflow prediction graph...
2020-07-03 13:47:54 DEBUG    rasa.utils.tensorflow.models  - Finished building tensorflow prediction graph.
2020-07-03 13:47:54 DEBUG    rasa.core.nlg.generator  - Instantiated NLG to 'TemplatedNaturalLanguageGenerator'.
2020-07-03 13:47:54 INFO     root  - Rasa server is up and running.
Bot loaded. Type a message and press enter (use '/stop' to exit): 
Your input ->  hi                                                                
2020-07-03 13:47:59 DEBUG    rasa.core.tracker_store  - Creating a new tracker for id '079efbf3a8624af9b95b7dbfea5d6f5f'.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Starting a new session for conversation ID '079efbf3a8624af9b95b7dbfea5d6f5f'.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Action 'action_session_start' ended with events '[<rasa.core.events.SessionStarted object at 0x7fa47c12c4e0>, <rasa.core.events.ActionExecuted object at 0x7fa47c12c4a8>]'.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Current slot values: 
        address: None
        name: None
        requested_slot: None
        slot_to_change: None
2020-07-03 13:47:59 DEBUG    rasa.nlu.classifiers.diet_classifier  - There is no trained model for 'ResponseSelector': The component is either not trained or didn't receive enough training data.
2020-07-03 13:47:59 DEBUG    rasa.nlu.selectors.response_selector  - Adding following selector key to message property: default
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Received user message 'hi' with intent '{'name': 'greet', 'confidence': 0.9999135136604309}' and entities '[]'
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Logged UserUtterance - tracker now has 4 events.
2020-07-03 13:47:59 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, None, None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}]
2020-07-03 13:47:59 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'test_form'
2020-07-03 13:47:59 DEBUG    rasa.core.policies.form_policy  - There is no active form
2020-07-03 13:47:59 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_MemoizationPolicy
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Predicted next action 'test_form' with confidence 1.00.
2020-07-03 13:47:59 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'test_form'.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Action 'test_form' ended with events '[BotUttered('Name:', {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, {}, 1593776879.341949), <rasa.core.events.Form object at 0x7fa47c0696a0>, <rasa.core.events.SlotSet object at 0x7fa4ca280e48>]'.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Current slot values: 
        address: None
        name: None
        requested_slot: name
        slot_to_change: None
2020-07-03 13:47:59 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, None, None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}]
2020-07-03 13:47:59 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'test_form'
2020-07-03 13:47:59 DEBUG    rasa.core.policies.mapping_policy  - There is no mapped action for the predicted intent, 'greet'.
2020-07-03 13:47:59 DEBUG    rasa.core.policies.form_policy  - There is an active form 'test_form'
2020-07-03 13:47:59 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_3_FormPolicy
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Predicted next action 'action_listen' with confidence 1.00.
2020-07-03 13:47:59 DEBUG    rasa.core.processor  - Action 'action_listen' ended with events '[]'.
2020-07-03 13:47:59 DEBUG    rasa.core.lock_store  - Deleted lock for conversation '079efbf3a8624af9b95b7dbfea5d6f5f'.
Name:
Your input ->  john                                                              
2020-07-03 13:48:01 DEBUG    rasa.core.tracker_store  - Recreating tracker for id '079efbf3a8624af9b95b7dbfea5d6f5f'
2020-07-03 13:48:01 DEBUG    rasa.nlu.classifiers.diet_classifier  - There is no trained model for 'ResponseSelector': The component is either not trained or didn't receive enough training data.
2020-07-03 13:48:01 DEBUG    rasa.nlu.selectors.response_selector  - Adding following selector key to message property: default
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Received user message 'john' with intent '{'name': 'inform', 'confidence': 0.9999873638153076}' and entities '[{'entity': 'name', 'start': 0, 'end': 4, 'value': 'john', 'extractor': 'DIETClassifier'}]'
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Current slot values: 
        address: None
        name: john
        requested_slot: name
        slot_to_change: None
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Logged UserUtterance - tracker now has 11 events.
2020-07-03 13:48:01 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}, {'intent_greet': 1.0, 'active_form_test_form': 1.0, 'prev_test_form': 1.0}, {'intent_inform': 1.0, 'prev_action_listen': 1.0, 'entity_name': 1.0, 'active_form_test_form': 1.0}]
2020-07-03 13:48:01 DEBUG    rasa.core.policies.memoization  - There is no memorised next action
2020-07-03 13:48:01 DEBUG    rasa.core.policies.form_policy  - There is an active form 'test_form'
2020-07-03 13:48:01 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_3_FormPolicy
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Predicted next action 'test_form' with confidence 1.00.
2020-07-03 13:48:01 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'test_form'.
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Action 'test_form' ended with events '[BotUttered('Address:', {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, {"name": "john", "requested_slot": "name"}, 1593776881.538067), <rasa.core.events.SlotSet object at 0x7fa45c705ef0>, <rasa.core.events.SlotSet object at 0x7fa45c705160>]'.
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Current slot values: 
        address: None
        name: john
        requested_slot: address
        slot_to_change: None
2020-07-03 13:48:01 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, None, None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}]
2020-07-03 13:48:01 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'test_form'
2020-07-03 13:48:01 DEBUG    rasa.core.policies.mapping_policy  - There is no mapped action for the predicted intent, 'inform'.
2020-07-03 13:48:01 DEBUG    rasa.core.policies.form_policy  - There is an active form 'test_form'
2020-07-03 13:48:01 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_3_FormPolicy
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Predicted next action 'action_listen' with confidence 1.00.
2020-07-03 13:48:01 DEBUG    rasa.core.processor  - Action 'action_listen' ended with events '[]'.
2020-07-03 13:48:01 DEBUG    rasa.core.lock_store  - Deleted lock for conversation '079efbf3a8624af9b95b7dbfea5d6f5f'.
Address:
Your input ->  stuttgart                                                         
2020-07-03 13:48:04 DEBUG    rasa.core.tracker_store  - Recreating tracker for id '079efbf3a8624af9b95b7dbfea5d6f5f'
2020-07-03 13:48:04 DEBUG    rasa.nlu.classifiers.diet_classifier  - There is no trained model for 'ResponseSelector': The component is either not trained or didn't receive enough training data.
2020-07-03 13:48:04 DEBUG    rasa.nlu.selectors.response_selector  - Adding following selector key to message property: default
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Received user message 'stuttgart' with intent '{'name': 'inform', 'confidence': 0.9999904036521912}' and entities '[{'entity': 'address', 'start': 0, 'end': 9, 'value': 'stuttgart', 'extractor': 'DIETClassifier'}]'
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Current slot values: 
        address: stuttgart
        name: john
        requested_slot: address
        slot_to_change: None
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Logged UserUtterance - tracker now has 18 events.
2020-07-03 13:48:04 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}, {'intent_greet': 1.0, 'active_form_test_form': 1.0, 'prev_test_form': 1.0}, {'intent_inform': 1.0, 'prev_action_listen': 1.0, 'active_form_test_form': 1.0, 'entity_address': 1.0}]
2020-07-03 13:48:04 DEBUG    rasa.core.policies.memoization  - There is no memorised next action
2020-07-03 13:48:04 DEBUG    rasa.core.policies.form_policy  - There is an active form 'test_form'
2020-07-03 13:48:04 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_3_FormPolicy
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Predicted next action 'test_form' with confidence 1.00.
2020-07-03 13:48:04 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'test_form'.
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Action 'test_form' ended with events '[BotUttered('Name: john; address: stuttgart; OK?', {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, {}, 1593776884.167718), <rasa.core.events.SlotSet object at 0x7fa45c64a0b8>, <rasa.core.events.Form object at 0x7fa45c64ae10>, <rasa.core.events.SlotSet object at 0x7fa45c64af98>]'.
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Current slot values: 
        address: stuttgart
        name: john
        requested_slot: None
        slot_to_change: None
2020-07-03 13:48:04 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}, {'intent_greet': 1.0, 'prev_test_form': 1.0}]
2020-07-03 13:48:04 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'action_listen'
2020-07-03 13:48:04 DEBUG    rasa.core.policies.mapping_policy  - There is no mapped action for the predicted intent, 'inform'.
2020-07-03 13:48:04 DEBUG    rasa.core.policies.form_policy  - There is no active form
2020-07-03 13:48:04 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_MemoizationPolicy
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Predicted next action 'action_listen' with confidence 1.00.
2020-07-03 13:48:04 DEBUG    rasa.core.processor  - Action 'action_listen' ended with events '[]'.
2020-07-03 13:48:04 DEBUG    rasa.core.lock_store  - Deleted lock for conversation '079efbf3a8624af9b95b7dbfea5d6f5f'.
Name: john; address: stuttgart; OK?
Your input ->  change address                                                    
2020-07-03 13:48:07 DEBUG    rasa.core.tracker_store  - Recreating tracker for id '079efbf3a8624af9b95b7dbfea5d6f5f'
2020-07-03 13:48:07 DEBUG    rasa.nlu.classifiers.diet_classifier  - There is no trained model for 'ResponseSelector': The component is either not trained or didn't receive enough training data.
2020-07-03 13:48:07 DEBUG    rasa.nlu.selectors.response_selector  - Adding following selector key to message property: default
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Received user message 'change address' with intent '{'name': 'change', 'confidence': 0.9999966621398926}' and entities '[{'entity': 'slot_to_change', 'start': 7, 'end': 14, 'value': 'address', 'extractor': 'DIETClassifier'}]'
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Current slot values: 
        address: stuttgart
        name: john
        requested_slot: None
        slot_to_change: address
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Logged UserUtterance - tracker now has 26 events.
2020-07-03 13:48:07 DEBUG    rasa.core.policies.memoization  - Current tracker state [None, {}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}, {'intent_greet': 1.0, 'prev_test_form': 1.0}, {'prev_action_listen': 1.0, 'slot_slot_to_change_0': 1.0, 'entity_slot_to_change': 1.0, 'intent_change': 1.0}]
2020-07-03 13:48:07 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'action_unset_slot'
2020-07-03 13:48:07 DEBUG    rasa.core.policies.form_policy  - There is no active form
2020-07-03 13:48:07 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_MemoizationPolicy
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Predicted next action 'action_unset_slot' with confidence 1.00.
2020-07-03 13:48:07 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'action_unset_slot'.
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Action 'action_unset_slot' ended with events '[<rasa.core.events.SlotSet object at 0x7fa45c5315f8>]'.
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Current slot values: 
        address: None
        name: john
        requested_slot: None
        slot_to_change: address
2020-07-03 13:48:07 DEBUG    rasa.core.policies.memoization  - Current tracker state [{}, {'prev_action_listen': 1.0, 'intent_greet': 1.0}, {'intent_greet': 1.0, 'prev_test_form': 1.0}, {'prev_action_listen': 1.0, 'slot_slot_to_change_0': 1.0, 'entity_slot_to_change': 1.0, 'intent_change': 1.0}, {'prev_action_unset_slot': 1.0, 'slot_slot_to_change_0': 1.0, 'entity_slot_to_change': 1.0, 'intent_change': 1.0}]
2020-07-03 13:48:07 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'action_listen'
2020-07-03 13:48:07 DEBUG    rasa.core.policies.mapping_policy  - There is no mapped action for the predicted intent, 'change'.
2020-07-03 13:48:07 DEBUG    rasa.core.policies.form_policy  - There is no active form
2020-07-03 13:48:07 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_MemoizationPolicy
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Predicted next action 'action_listen' with confidence 1.00.
2020-07-03 13:48:07 DEBUG    rasa.core.processor  - Action 'action_listen' ended with events '[]'.
2020-07-03 13:48:07 DEBUG    rasa.core.lock_store  - Deleted lock for conversation '079efbf3a8624af9b95b7dbfea5d6f5f'.
Your input ->

and the corresponding actions log:

2020-07-03 13:47:55 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
2020-07-03 13:47:55 INFO     rasa_sdk.executor  - Registered function for 'action_unset_slot'.
2020-07-03 13:47:55 INFO     rasa_sdk.executor  - Registered function for 'test_form'.
2020-07-03 13:47:59 INFO     root  - required_slots
2020-07-03 13:47:59 INFO     root  - required_slots
2020-07-03 13:47:59 INFO     root  - required_slots
2020-07-03 13:48:01 INFO     root  - required_slots
2020-07-03 13:48:01 INFO     root  - required_slots
2020-07-03 13:48:04 INFO     root  - required_slots
2020-07-03 13:48:04 INFO     root  - required_slots
2020-07-03 13:48:04 INFO     root  - required_slots
2020-07-03 13:48:04 INFO     root  - submit
2020-07-03 13:48:07 INFO     root  - unset
2020-07-03 13:48:20 INFO     root  - unset

Unfortunately I could not recreate the situation that the required_slots method is called again after unsetting, but still this should work in my understanding. I dont understand why action_listen is predicted with Memoization although thats not what the story looks like.

I think what’s causing this is that you are missing the form action event in your story (see our docs on form events in Stories).

I modified the story like this:

## address change
* greet
  - test_form
  - form{"name": "test_form"}
  - form{"name": null}
* change{"slot_to_change": "address"}
  - action_unset_slot
  - test_form
  - form{"name": "test_form"}
  - form{"name": null}
* affirm
  - utter_goodbye

and it seemed to work for the minimal test example. (Thanks for providing the example, that made it really easy to try things out).

Let me know if this solves your issue!

And one more thing: It would probably be good to also unset the slot "slot_to_change" at the end of the UnsetSlotAction. There is no reason why this should stay set after the slot to change has been unset.

Ok, that was simple :smiley: Thanks for the help!

I would be interested how you would implement this. I guess giving the user a chance to validate and change its entered data is a pretty common usecase. Is what I did there like a workaround or is that actually how you’re supposed to do it?

This seems like a pretty straightforward implementation to me. One alternative is to include the “change” intent in the stories that trigger the form, and have a validation function for slot_to_change that unsets the slot, but don’t include slot_to_change in the list of required slots. This would basically port what you’re doing inside the form. I’m not sure it’s better, but it’s an alternative you could try.

The form action would look like:

class TicketFormAction(forms.FormAction):
    def name(self) -> Text: 
        return "test_form"
    def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, 
                domain: Dict[Text, Any]) -> List[Dict]:
        logging.info("submit")
        dispatcher.utter_message(template="utter_sum_info")
        return []
    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        logging.info("required_slots")
        return ["name", "address"]
    def validate_slot_to_change(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:

        slot_to_change = tracker.get_slot("slot_to_change")
        return {slot_to_change:None}

And the story could look like:

## address change
* greet OR change
  - test_form
  - form{"name": "test_form"}
  - form{"name": null}
* affirm
  - utter_goodbye

this way, the slot could be changed before or after the form is submitted.

Thanks for the feedback and the alternative implementation. It might be beneficial to be able to change something before the form starts. Anyway it has the disadvantage that the mechanism can only be used for this one form since you directly trigger the form action from the change intent.

If you wanted to do it that way, you could create a custom form action that you base all your forms on that includes this logic. You’d need to think about how to write your stories though e.g. using entities in the “change” intent to differentiate which form gets started