Rasa forms do not extract slots

Hi there, I have to trigger a form action so I call this inside another python function:

async def redirect_form(user_id, context=None):
                await agent.handle_message("customer survey", sender_id = user_id)
            loop.run_until_complete(redirect_form(user_id=user_id))

This triggers the form, however, form just passes and does not extract any slots.

my form action: class SurveyAction(FormAction):

	def name(self) -> Text:
		return "action_survey"
	
	def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
		return {
			"slot_1": self.from_text(),
			"slot_2": self.from_text()
		}
	@staticmethod
	def required_slots(tracker: Tracker) -> List[Text]:
		return ["slot_1", "slot_2"]

	def request_next_slot(self,dispatcher: "CollectingDispatcher",tracker: "Tracker",
	domain):		
		for slot in self.required_slots(tracker):
			if self._should_request_slot(tracker, slot):
				if slot == 'slot_1':
					dispatcher.utter_template("utter_ask_slot_1")
					
				elif slot == 'slot_2':
					dispatcher.utter_template("utter_ask_slot_2")
					
				return [SlotSet("requested_slot", slot)]
		return None


	def submit(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    	) -> List[Dict]:
        
		userId = tracker.current_state()["sender_id"]

		s1 = tracker.get_slot("slot_1")
		s2 = tracker.get_slot("slot_2")
		if s1 is not "":
			## some requests to post
		if s2 is not "":
			## some requests to post
		if s1 is not "" and s2 is not "":
			dispatcher.utter_template("utter_submit_survey", tracker})
		return []

My slots are from text so whatever user will type (feedback) will be sent to backend. Initial values of slots are None and auto-fill is false so that the agent will actually ask for it (but doesn’t)

Action server:

2021-06-02 15:04:07 DEBUG    rasa_sdk.forms  - Validating extracted slots: {}
2021-06-02 15:04:07 DEBUG    rasa_sdk.forms  - No slots left to request, all required slots are filled:
	slot_1: None
	slot_2: None
(sends request)
    2021-06-02 15:04:07 DEBUG    rasa_sdk.forms  - Submitting the form 'action_survey'
2021-06-02 15:04:07 DEBUG    rasa_sdk.forms  - Deactivating the form 'action_survey'
2021-06-02 15:04:07 DEBUG    rasa_sdk.executor  - Finished running 'action_survey'
2021-06-02 15:04:08 DEBUG    rasa_sdk.executor  - Received request to run 'action_survey'
2021-06-02 15:04:08 DEBUG    rasa_sdk.forms  - There is no active form
2021-06-02 15:04:08 DEBUG    rasa_sdk.forms  - Activated the form 'action_survey
2021-06-02 15:04:08 DEBUG    rasa_sdk.forms  - Validating pre-filled required slots: {'slot_1': 'None', 'slot_2': 'None'}

The stories:

## path_survey
* customer_survey
  - action_survey
  - form{"name": "action_survey"}
  - form{"name": null}
The slots in domain.yml:
slot_1:
    auto_fill: false
    initial_value: None
    type: rasa.core.slots.TextSlot
  slot_2:
    auto_fill: false
    initial_value: None
    type: rasa.core.slots.TextSlot

What I have also tried:

## path_survey
* customer_survey
  - action_survey
  - form{"name": "action_survey"}
  -  slot{“requested_slot”: “slot_1”}
  - slot{“requested_slot”: “slot_2”}
  - form{"name": null}

I’ve also used the default request_next_slot from the documentation, when I put a debugger I realized it didn’t even go there. That’s why I hard the slots in that method.

What I’m currently trying at the moment:

I also see here that there’s a default function that will raise a value error when slots aren’t working, I didn’t get that error

My problem also could be because I’m triggering an async function and looping over it manually to trigger the intent and the form which might be a problem. (?) but this is a must as I can’t expect the user to simply ask for a survey.

Note that I’m using 1.10.24.

Hi @merveenoyan ,

before we go into detail:

Have you checked if the methods required_slots and slot_mappings get properly called during the processing of the form, e.g. by setting the mentioned debugger / logger?

Kind regards
Julian

Hello Julian,

Are you talking about logger.debug() points? I used the default one that’s in the default request_next_slot function, but I realized it doesn’t prompt anything. Do you think that specifying what slots would be filled with in the stories would work? i.e. I’ll put it down like this

  • slot{“requested_slot”: “slot_1”}
  • slot{“slot_1”: “ease of use”} since this is free text slot.

I also think that it might’ve been because I’m using agent.handle_message(), would it bug the process? I’ll be adding logger.debug points shortly.

I’ve put few debug points and it seems that it knows what it should be extracting.

2021-06-02 21:20:44 DEBUG    rasa_sdk.executor  - Received request to run 'action_survey'
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - There is no active form
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - Activated the form 'action_survey'
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - Validating pre-filled required slots: {'slot_1': 'None', 'slot_2: 'None'}
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - Validating user input '{'intent': {'name': 'customer_survey', 'confidence': 0.935171425342559}, 'entities': []}' #removed rest of the logs for this post
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - Validating extracted slots: {}
2021-06-02 21:20:44 DEBUG    actions  - Required slot is 'slot_1' 
2021-06-02 21:20:44 DEBUG    actions  - Required slot is 'slot_2'
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - No slots left to request, all required slots are filled:
	slot_1: None
	slot_2: None
2021-06-02 21:20:44 DEBUG    rasa_sdk.forms  - Submitting the form 'action_survey'
2021-06-02 21:20:44 DEBUG    actions  - answer_1 'None' 
2021-06-02 21:20:44 DEBUG    actions  - answer_2'None'

These are

2021-06-02 21:20:44 DEBUG actions - Required slot is ‘slot_1’ 2021-06-02 21:20:44 DEBUG actions - Required slot is ‘slot_2’ coming from this:

for slot in self.required_slots(tracker): logger.debug(“Required slot is ‘{}’”.format(slot)) if self._should_request_slot(tracker, slot): logger.debug(“Request slot ‘{}’”.format(slot))

These are

2021-06-02 21:20:44 DEBUG    actions  - answer_1 'None' 
2021-06-02 21:20:44 DEBUG    actions  - answer_2'None'

coming from these lines in action_submit:

a1 = tracker.get_slot(“slot_1”) logger.debug(“answer_1 ‘{}’”.format(a1)) a2 = tracker.get_slot(“slot_2”) logger.debug(“answer_2’{}'”.format(a2))

also, writing request_next_slot like this:

def request_next_slot(self,dispatcher: “CollectingDispatcher”,tracker: “Tracker”, domain): for slot in self.required_slots(tracker): logger.debug(“Required slot is ‘{}’”.format(slot)) if self._should_request_slot(tracker, slot): logger.debug(“Request slot ‘{}’”.format(slot)) if slot == ‘slot_1’: dispatcher.utter_template(“utter_ask_slot_1”)

  		elif slot == 'slot_2':
  			dispatcher.utter_template("utter_ask_slot_2")
  			
  			
  		return [SlotSet(REQUESTED_SLOT, slot)]

Do you think is this valid? I looked for something like FormValidationAction for 1.x but couldn’t find.

What I’ve done so far (sorry if I used this post as a diary) Removed “return None” in the request_next_slot from the slots as this is done once per user lifetime, this form is prompted if a flag coming from the backend allows it to.

changed stories like this:

path_survey

  • customer_survey
    • slot{“requested_slot”: “slot_1”}
    • slot{“requested_slot”: “slot_2”}
    • action_survey
    • form{“name”: “customer_survey”}
    • slot{“slot_1”:“bot is talking gibberish”}
    • slot{“slot_2”:“improve the bot”}
    • form{“name”: null}

Because I want slots to be set, I’m particularly making the initial slot values as None and auto_fill as false, yet slots are set to “None”

2021-06-03 13:28:08 DEBUG    rasa_sdk.forms  - Validating extracted slots: {}
2021-06-03 13:28:08 DEBUG    actions  - Required slot is 'slot_1'
2021-06-03 13:28:08 DEBUG    actions  - Required slot is 'slot_2'
2021-06-03 13:28:08 DEBUG    rasa_sdk.forms  - No slots left to request, all required slots are filled:
	slot_1: None
	slot_2: None

I also changed request_next_slot like this, hard-coding SlotSet event and removing return None:

def request_next_slot(self,dispatcher: "CollectingDispatcher",tracker: "Tracker",
domain):		
	for slot in self.required_slots(tracker):
		logger.debug("Required slot is '{}'".format(slot))
		if self._should_request_slot(tracker, slot):
			logger.debug("Request slot '{}'".format(slot))
			if slot == 'slot_1':
				dispatcher.utter_template("utter_ask_slot_1")
				return [SlotSet("slot_1", slot_1)]
				
			elif slot == 'slot_2':
				dispatcher.utter_template("utter_ask_slot_2")
				return [SlotSet("slot_2", slot_2)]

This is full trace from action server:

2021-06-03 13:25:21 DEBUG    rasa_sdk.utils  - Using the default number of Sanic workers (1).
2021-06-03 13:28:06 DEBUG    rasa_sdk.executor  - Received request to run 'action_survey'
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - There is no active form
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - Activated the form 'action_survey'
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - Validating pre-filled required slots: {'slot_2': 'None', 'slot_2': 'None'}
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - Validating user input '{'intent': {'name': 'customer_survey', 'confidence': 0.935171425342559}, 'entities': [], 'intent_ranking': [{'name': 'customer_survey', 'confidence': 0.935171425342559}, -other intents-, 'text': 'Customer survey'}'
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - Validating extracted slots: {}
2021-06-03 13:28:06 DEBUG    actions  - Required slot is 'slot_1'
2021-06-03 13:28:06 DEBUG    actions  - Required slot is 'slot_2'
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - No slots left to request, all required slots are filled:
	slot_1: None
	slot_2: None
2021-06-03 13:28:06 DEBUG    rasa_sdk.forms  - Submitting the form 'action_survey'
2021-06-03 13:28:06 DEBUG    actions  - answer_1 'None'
2021-06-03 13:28:06 DEBUG    actions  - answer_2'None'

It’s important to note that this log is shown for three times in the action server, the reason why I think might be that I’m calling form outside by triggering the intent agent.handle_message(“customer survey”) and it works async like it’s supposed to.

What do you think the problem might be? @JulianGerhard Also I’d be happy if you could point out anything you see wrong.

I think my main problem here is something like this: Bot not asking for slots in Form as bot directly returns the utter_submit instead of asking for slots. It might be because of the agent.handle_message().