How to export slot values into json file

Hi

I have a working FormAction in which I fill multiple slots.

Goal:

After all slots are filled, I want to sent / export all slot values into a json file. Or is there a better way to store slot values, then please let me know!

My approach:

I think in order to solve my problem I have to change the function def submit in my FormAction. According to the documentation this function is about “what to do at the end of the form, when all the slots have been filled”.

This might be useful but I didn’t know how to apply it to my case: sent slot values in JSON

Maybe you can help me with this?

Here is my FormAction (which works properly):

actions.py


class AuthenticateFormShort(FormAction):
    """Example of a custom form action"""

    def name(self):
        # type: () -> Text
        """Unique identifier of the form"""

        return "authenticate_form_short"

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

        return ["name"]  # Every time the form action gets called, it will ask the user for the next slot in required_slots which is not already set. Note the order!!!

    def submit(self, dispatcher, tracker, domain):
        # type: (CollectingDispatcher, Tracker, Dict[Text, Any]) -> List[Dict]
        """Define what the form has to do
           after all required slots are filled"""

        # utter submit template
        dispatcher.utter_template('utter_form_bye', tracker)
        return []

    def slot_mappings(self):
        # type: () -> 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 {
            "name": [self.from_entity(entity="name", not_intent=["chitchat"])],
        }

    def validate(self,
                 dispatcher: CollectingDispatcher,
                 tracker: Tracker,
                 domain: Dict[Text, Any]) -> List[Dict]:
        """Validate extracted requested slot
            else reject the execution of the form action
        """
        # extract other slots that were not requested
        # but set by corresponding entity
        slot_values = self.extract_other_slots(dispatcher, tracker, domain)

        # extract requested slot
        slot_to_fill = tracker.get_slot(REQUESTED_SLOT)
        if slot_to_fill:
            slot_values.update(self.extract_requested_slot(dispatcher,
                                                           tracker, domain))
            if not slot_values:
                # reject form action execution
                # if some slot was requested but nothing was extracted
                # it will allow other policies to predict another action
                raise ActionExecutionRejection(self.name(),
                                               "Failed to validate slot {0} "
                                               "with action {1}"
                                               "".format(slot_to_fill,
                                                         self.name()))
        # we'll check when validation failed in order
        # to add appropriate utterances

        for slot, value in slot_values.items():
    

        if slot == 'name':
            if (bool(re.search(r'\d', value)) == False) and (
                    bool(re.search("[^a-zA-Z.\-\s\Ü\ü\ß\ä\Ä\ö\Ö]", value)) == False):  # if hasNumber == False
                slot_values[slot] = value
            else:
                dispatcher.utter_template('utter_spezial_characters', tracker)
                # validation failed, set slot to None
                slot_values[slot] = None


                # validation succeed, set the slots values to the extracted values
        return [SlotSet(slot, value) for slot, value in slot_values.items()]

As you can see, the slos that I want to export is

  • name

Hope you can help me!

Hi @Chatbot_Ra,

We have a function for this in our utils, so you can place the following code in your form’s submit function and I’m sure it provides the functionality you’re looking for :slight_smile:

from rasa.nlu.utils import write_json_to_file
write_json_to_file(filename, tracker.slots)

Hey

Thnak you very much for your reply. For some reason I had to load the package this way:

from rasa_nlu.utils import write_json_to_file

(Note the small difference to your response!)

Before I run the code, I have created an empty file named “filename.json” in the same folder then my action.py file. In the action.py file I have changed the submit function the way you just said. The submit function in my form was changed to this:

    def submit(self, dispatcher, tracker, domain):
    # type: (CollectingDispatcher, Tracker, Dict[Text, Any]) -> List[Dict]
    """Define what the form has to do
       after all required slots are filled"""

    write_json_to_file(filename, tracker.slots)

    # utter submit template
    dispatcher.utter_template('utter_form_bye', tracker)
    return []

After completing the form (filling all slots) I get the following error message:

2019-07-17 13:54:55 ERROR rasa_core.actions.action - Failed to run custom action ‘authenticate_form’. Action server responded with a non 200 status code of 500. Make sure your action server properly runs actions and returns a 200 o nce the action is executed. Error: 500 Server Error: INTERNAL SERVER ERROR for url: http://localhost:5055/webhook 2019-07-17 13:54:55 ERROR rasa_core.processor - Encountered an exception while running action ‘authenticate_form’. Bot will continue, but the actions events are lost. Make sure to fix the exception in your custom code.

Hi @Chatbot_Ra,

Please check the logs on your action server for something more insightful :slight_smile:

Unfortunately the log-file is not much more insightful:

Rasa process starting
Added 'nlp_spacy' to component cache. Key 'nlp_spacy-de_core_news_sm'.

Rasa Core server is up and running on http://localhost:5005

Failed to run custom action 'authenticate_form'. Action server responded 
with a non 200 
status code of 500. Make sure your action server properly runs actions 
and returns a 200 
once the action is executed. Error: 500 Server Error: 
INTERNAL SERVER ERROR for url: http://localhost:5055/webhook
Encountered an exception while running action 'authenticate_form'. 
Bot will continue,
 but the actions events are lost. Make sure to fix the exception 
in your custom code.

Ok, I just found the mistake that I have done.

    def submit(self, dispatcher, tracker, domain):
    # type: (CollectingDispatcher, Tracker, Dict[Text, Any]) -> List[Dict]
    """Define what the form has to do
       after all required slots are filled"""

    write_json_to_file("filename.json", tracker.slots)

    # utter submit template
    dispatcher.utter_template('utter_form_bye', tracker)
    return []

See the small diference in calling the file “filename.json” to what I did before!

Now it works fine. Thank you very much for your help Thomas!