TL;DR: Two entities are very similar (5 digits vs 6 digits) and it mistakes one for the other.
Hey, I’m relatively new to RASA (started just on Monday) and it’s awesome.
I’m currently trying to create a Chat Bot that can give a customer general information but also information on their order at our online shop. To get that status, the user has to give the bot the order_id and the postcode of the shipping address.
Now each of them work fine independently of each other, but now I chained them together (i.e. first order_id, then postcode, then check if it’s correct and reply with information).
If the bot asks for the order ID, if the user inputs “Order 123456” everything works. But if the user just inputs “123456” it mistakes that number for the postcode (which is just 5 digits in length).
Here’s my custom_slots.py: class OrdernumberSlot(Slot): def feature_dimensionality(self): return 2
def as_feature(self):
r = [0.0] * self.feature_dimensionality()
if self.value:
match = re.match("\d{6}", self.value)
if match:
r[0] = 1.0
else:
r[1] = 1.0
return r
class PostcodeSlot(Slot):
def feature_dimensionality(self):
return 2
def as_feature(self):
r = [0.0] * self.feature_dimensionality()
if self.value:
match = re.match("\d{5}", self.value)
if match:
r[0] = 1.0
else:
r[1] = 1.0
return r
I assumed that using the regex there would tell the system what kind of input it is (on top of the intent).
The relevant part of my nlu.md:
## intent:inform_order
- Meine Bestellnr ist [323321](ordernumber)
- Die Bestellnummer lautet [378879](ordernumber)
- Meine Bstnr is [377876](ordernumber)
- Bestellnummer [355898](ordernumber)
- Bestellnummer ist [355652](ordernumber)
- [398752](ordernumber)
- [364651](ordernumber)
- Das ist die [336336](ordernumber)
- Das wäre die [369878](ordernumber)
- Bestesllung [254325](ordernumber)
- Bestellung [345621](ordernumber)
- Bst [445544](ordernumber)
- Bstnr [123123](ordernumber)
- [324654](ordernumber)
- Meine Bestellnummer ist [321344](ordernumber)
- [345123](ordernumber)
- Bstnr ist die [345678](ordernumber)
- DAs wäre die [314312](ordernumber)
- Bestellnr [278899](ordernumber)
- [387122](ordernumber)
- Bstnr. [345561](ordernumber)
- [337831](ordernumber)
- [389009](ordernumber)
- Bestellung [311178](ordernumber)
- [340909](ordernumber)
- Bestellnummer ist [320222](ordernumber)
- Best. [301010](ordernumber)
- Nr [304449](ordernumber)
- Nr. [309919](ordernumber)
- Nr[321188](ordernumber)
- No. [326969](ordernumber)
- Bestellung ist [343411](ordernumber)
- Bestellung [324632](ordernumber)
- Meine Bestellnummer ist [321000](ordernumber)
- [321322333](ordernumber)
- [334411](ordernumber)
- Bestellnr ist [112211](ordernumber)
- Bestellung [388309](ordernumber) .
- [10283701237](ordernumber)
- [366666](ordernumber)
- [32132](ordernumber)
- [388812](ordernumber)
- Bestllnr [345110](ordernumber)
- [21215](ordernumber)
- Bstnr [311344](ordernumber)
- [402873](postcode)
- Bestellnummer [402873](ordernumber)
- Bst [402873](ordernumber)
- bst [402873](ordernumber)
- [402879](postcode)
and
## intent:inform_postcode
- Meine PLZ ist [24963](postcode)
- Die Postleitzahl lautet [547896](postcode)
- Meine PLZ is [54778](postcode)
- Postleitzahl [25447](postcode)
- Postleitzahl ist [56658](postcode)
- [11245](postcode)
- [54482](postcode)
- Das ist die [25548](postcode)
- Das wäre die [33598](postcode)
- PLZ [65789](postcode)
- Postleitzahl [05478](postcode)
- Meine Postleitzahl ist [09785](postcode)
- [12558](postcode)
- PLZ ist die [23585](postcode)
- DAs wäre die [349465](postcode)
- PLZ [87448](postcode)
- [658235](postcode)
- PLZ: [63558](postcode)
- [04588](postcode)
- [99255](postcode)
- Postleitzahl: [05547](postcode)
- [06858](postcode)
- Postleitzahl ist [11547](postcode)
- PLZ: [22485](postcode)
- PLZ [855374](postcode)
- PLZ: [95587](postcode)
- PLZ[65442](postcode)
- PLZ: [23344](postcode)
- Postleitzahl ist [25548](postcode)
- Postleitzahl [233145](postcode)
- Meine Postleitzahl ist [36587](postcode)
- [78542](postcode)
- [85475](postcode)
- Postleitzahl ist [25478](postcode)
- Postleitzahl [32558](postcode).
- [15478](postcode)
- [87452](postcode)
- [24598](postcode)
- [54725](postcode)
- PLZ [95147](postcode)
- [75369](postcode)
- PLZ [74523](postcode)
- PLZ [53340](postcode)
- plz [53340](postcode)
- [53340](postcode)
- [53341](postcode)
The reason why I added some ordernumbers and postcodes with the wrong amount of digits is so that it would trigger a utter_incorrect_ordernumber or utter_incorrect_postcode. Is this the right way to do it? I have 16 stories, all set up right, but when it comes to testing it after training, it still thinks I want to send a postcode to the intent inform_order.
Is there a way to bind an entity to an intent or a slot to a form? So it listens specifically for one entity?
Thank you guys so much in advance! It’s a ton of fun working with Rasa / Rasa X!
EDIT: More information that might be relevant
domain.yml intents, entities, slots and forms:
intents:
- greet
- deny
- cancel
- affirm
- orderstatus
- inform_order
- inform_postcode
- bye
- thanks
entities:
- ordernumber
- postcode
slots:
ordernumber:
type: unfeaturized
postcode:
type: unfeaturized
requested_slot:
type: unfeaturized
config.yml
%YAML 1.1
---
language: de_core_news_sm
pipeline: pretrained_embeddings_spacy
policies:
- name: KerasPolicy
epochs: 175
max_history: 5
- name: FallbackPolicy
fallback_action_name: 'action_default_fallback'
- name: MemoizationPolicy
max_history: 5
- name: FormPolicy
actions.py OrdernumberForm class:
class OrdernumberForm(FormAction):
def name(self):
""" Unique identifier of the form"""
return "ordernumber_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""List of required slots that the form has to fill"""
return ["ordernumber"]
def validate_ordernumber(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Optional[Text]:
match = re.match("([^0-9]|^)[0-9]{6}([^0-9]|$)", value)
if match:
ordernumber = match.group(0)
dispatcher.utter_template('utter_ask_postcode', tracker)
return {'ordernumber': ordernumber}
else:
dispatcher.utter_template('utter_wrong_ordernumber', tracker)
return None
def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> List[Dict]:
"""Define what the form does after all required slots are filled"""
# dispatcher.utter_template('utter_submit', tracker)
# dispatcher.utter_template('utter_ask_for_more_questions', tracker)
return []
actions.py PostcodeForm class:
class PostcodeForm(FormAction):
def name(self):
""" Unique identifier of the form"""
return "postcode_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""List of required slots that the form has to fill"""
return ["postcode"]
def validate_postcode(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Optional[Text]:
match = re.match("^([0]{1}[1-9]{1}|[1-9]{1}[0-9]{1})[0-9]{3}$", value)
ordernumber = tracker.get_slot("ordernumber")
#(and then some api calls)#