All extract_<slot> functions get called in each loop iteration

Hi,

I am trying to implement a Form with Slots that use custom mappings so that I can extract all the entities by myself. I got that working but there is something weird about having multiple extraction functions in a class that derives from FormValidationAction.

When the form loop starts and I get promoted to enter the first sentence/word or whatever I correctly detect that the first required slot has to be filled but after that, on every loop iteration all extract_ functions get called.

What I did to circumvent this problem is to implement the conditional statement

if tracker.slots["requested_slot"] == "one"

for every slot extraction function.

I don’t think that this behavior of calling every extract function on every loop is normal and I probably misconfigured something.

Please take look at my files and help me to find the error.

Domain:

actions:
  - validate_test_form

intents:
  - request_form

responses:
  utter_ask_one:
    - text: "give one"
  utter_ask_two:
    - text: "give two"
  utter_ask_three:
    - text: "give three"

slots:
  one:
    type: text
    mappings:
      - type: custom
        conditions:
          - active_loop: test_form
            requested_slot: one

  two:
    type: text
    mappings:
      - type: custom
        conditions:
          - active_loop: test_form
            requested_slot: two 

  three:
    type: text
    mappings:
      - type: custom
        conditions:
          - active_loop: test_form
            requested_slot: three 

forms:
  test_form:
    required_slots:
      - one
      - two
      - three
      

session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true

rules:

rules:
  - rule: Activate form
    steps:
      - intent: request_form
      - action: test_form
      - active_loop: test_form
      - slot_was_set:
          - requested_slot: one
          - requested_slot: two
          - requested_slot: three

actions:

from typing import Any, Text, Dict, List
from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet, SessionStarted, ActionExecuted, EventType
from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher


class ValidateCustomSlotMappings(FormValidationAction):
    def name(self) -> Text:
        return "validate_test_form"

    async def extract_one(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict) -> Dict[Text, Any]:
        print("extract one")

        if tracker.slots["requested_slot"] == "one":

            text_of_last_user_message = tracker.latest_message.get("text")
        
            return {"one": text_of_last_user_message}

    async def extract_two(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict) -> Dict[Text, Any]:
        print("extract two")

        if tracker.slots["requested_slot"] == "two":

            text_of_last_user_message = tracker.latest_message.get("text")
            return {"two": text_of_last_user_message}

    async def extract_three(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict) -> Dict[Text, Any]:
        print("extract three")

        if tracker.slots["requested_slot"] == "three":

            text_of_last_user_message = tracker.latest_message.get("text")
            return {"three": text_of_last_user_message}

Thank you very much!

  • Your slots all need to set influence_conversation: false. The default is true which is unfortunate because you typically don’t want slots to be featurized.
  • Remove this block from your rule:
      - slot_was_set:
          - requested_slot: one
          - requested_slot: two
          - requested_slot: three
  • Delete your three extract methods. Based on your example, they aren’t needed. You should use the from_text slot mapping as described here.

Thanks for the tip with influence_conversation! Unfortunately, this does not really help me.

I already got my scenario to work without the extract_ functions, but now I want to explicitly implement this form with the extract_ functions even though in this scenario implementing a custom extract function makes no sense.

I want to do this and make it work to work through all possible functions piece by piece and get a better understanding of rasa.

However, the extract function doesn’t make sense to me right now, because all implemented extract functions are called at the same time during a form iteration which doesn’t make sense in my eyes. Why else does it say in the documentation that these functions should be named with extract_ + slotname if then all are called anyway in a single iteration?

I duplicated your issue with formbot. You should file an issue in GitHub.

Hi @Thermal_String , I am facing the same issue. I don’t want extract_ functions to run for every slot in a form. Were you able to resolve this issue?