so I successfully used the sexy rasa core FormAction’s and I love em!
There is just this small problem I have which I was not able to figure out myself yet:
Given I have two required_slots, lets call them forename and surname, I utter_ask the user for his forename.
He names it, it get’s extracted successfully and now I want to use it in my utter_ask_surname like so:
- text: Thanks {forename}. What about your surname?
where forename gets substituted with None… does anyone have an idea why this is the case and how I can access the slot right away?
class TestFormAction(FormAction):
"""Example of a custom form action"""
RANDOMIZE = True
def name(self):
# type: () -> Text
"""Unique identifier of the form"""
return "action_test_form"
def slot_mapping(self):
# type: () -> Dict[Text: Union[Text, Dict, List[Text, Dict]]]
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message
or a list of them, where the first match will be picked"""
return {
'forename': [
self.from_entity(entity='forename'),
self.from_text(intent='get_forename'),
],
'surname': [
self.from_entity(entity='surname'),
self.from_text(intent='get_surname'),
],
}
@staticmethod
def required_slots(tracker):
# type: (Tracker) -> List[Text]
"""A list of required slots that the form has to fill"""
return ['forename', 'surname']
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_data_full_name', tracker)
return []
I am also on it to find out why this is the case. Hopefully I can come up with a PR, so far I’ll issue my findings
Thanks for your answer, I was quite unsure if it was me or the SDK.
Alright, I found the issue and well, it was my fault! I’m super sorry but want to share my findings with you:
The actual problem did stem from MYdomain.yml which made this particular piece of code not set the slots in the instant they were extracted… simply had to change from:
Nevertheless, I think it might be good to take from the “original” Tracker from the rasa-core repo for consistency reasons, right?
Also disambiguates the understanding of the class / object as they are supposed to be the same (while their implementation as of now is not identical).
Hey, is this solved? I experience the same issue - got a FormAction, the slot returns None upon calling it in utterance. Actually it just gets set to the correct value one utterance too late, in online training I can see it is set to the actual slot value one step later:
Should be setting slot here, but as you can see userid: None
Please enter the new userid! (Only the characters of the userid.)
action_listen 1.00
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
DFG44lksd@kfk5
intent: newuserid 0.63
Current slots:
email: ppdls@mail.com, isconfirmed: None, userid: None, requested_slot: userid
And here it is all fine, but too late for my asking back:
userdetails_form 1.00
slot{"userid": "DFG44lksd@kfk5"}
slot{"requested_slot": "isconfirmed"}
Do you confirm changing the userid to None for user ppdls@mail.com?
1: yes
(/choose{"isconfirmed": True})
2: no (/choose{"isconfirmed": False})
Current slots:
email: ppdls@mail.com, isconfirmed: None, userid: DFG44lksd@kfk5, requested_slot: isconfirmed
Now the userid is set, but as you can see, the utterance says “None”.
@lauraperge there is the branch tracker-updated-utterance with this fix, we’re looking into it, whether we want to merge this solution, or try something else
I agree with @lauraperge : The current problem is in the definition of the dispatcher :
def utter_template(self,
template, # type: Text
tracker, # type: Tracker
silent_fail=False, # type: bool
**kwargs # type: Any
):
# type: (...) -> None
""""Send a message to the client based on a template."""
message = {"template": template}
message.update(kwargs)
self.messages.append(message)
So you can pass the slots via the **kwargs and they will get updated in the message, but the utter_template function doesn’t read off the tracker directly. Right now, what the Dispatcher in rasa_core does is a bit involved to paste code here, but essentially there’s an NLG module sitting inside rasa_core, and the dispatcher’s utter_template function asks the NLG module to generate the message. Then the NLG takes the tracker and fills in the slots in the utterance.
If Rasa is going to move the Dispatcher to the rasa_core_sdk, there are three options that I see :
Move everything there and keep two copies of the NLG, which is a bit over-kill in my opinion
Find a way to communicate what the custom action tracked in the action server back to the bot, so that it keeps track of events and slots (so that in some sense, the action_server would compute and generate events, but not spit them itself to the bot
Only care about this particular issue and not the rest, and replace the dispatcher’s utter_template function by this one :
def utter_template(self,
template, # type: Text
tracker, # type: Tracker
silent_fail=False, # type: bool
**kwargs # type: Any
):
# type: (...) -> None
""""Send a message to the client based on a template."""
message = {"template": template}
message.update(**tracker.slots)
message.update(kwargs)
self.messages.append(message)
where we just add the slots manually to the message in that function.