issues
search
RasaHQ
/
rasa
💬 Open source machine learning framework to automate text- and voice-based conversations: NLU, dialogue management, connect to Slack, Facebook, and more - Create chatbots and voice assistants
https://rasa.com/docs/rasa/
Apache License 2.0
18.95k
stars
4.64k
forks
source link
failing to populate a slot
#3191
Closed
tchax3742
closed
5 years ago
tchax3742
commented
5 years ago
**Rasa version**: 0.14.5 **Python version**: 3.6.4 **Operating system** (windows, osx, ...): Ubuntu 18.04 **Issue**: i am training my pizzabot model, when i fill in the pizza size slot, it is populated with no problem, however when i fill in the next slot, pizzatype, its not updating this slot and returns a null value so it keeps looping on that same slot. There is no error on my action server ![Screenshot from 2019-04-02 01-22-53](https://user-images.githubusercontent.com/46517278/55365723-e2c02d00-54e5-11e9-93d0-18294d033d78.png) **Content of actions file (actions.py)**: ``` # -*- coding: utf-8 -*- from typing import Dict, Text, Any, List, Union from rasa_core_sdk import ActionExecutionRejection from rasa_core_sdk import Tracker from rasa_core_sdk.events import SlotSet from rasa_core_sdk.executor import CollectingDispatcher from rasa_core_sdk.forms import FormAction, REQUESTED_SLOT class PizzaForm(FormAction): #Example of a custom form action def name(self): # type: () -> Text #Unique identifier of the form return "pizza_form" @staticmethod def required_slots(tracker: Tracker) -> List[Text]: #A list of required slots that the form has to fill return ["size", "pizzatype", "ask_toppings", "toppings","num_pizza"] 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 {"size": self.from_entity(entity="size", intent="informsize"), "pizzatype": self.from_entity(entity="pizzatype", intent="informtype"), "ask_toppings": [self.from_entity(entity="toppings"), self.from_intent(intent='affirm', value=True), self.from_intent(intent='deny', value=False)], "toppings": self.from_entity(entity="toppings", intent="informtoppings"), "num_pizza": self.from_entity(entity="number"), "feedback": [self.from_entity(entity="feedback"), self.from_text()]} @staticmethod def size_db(): # type: () -> List[Text] #Database of supported sizes return ["large", "extra large", "medium", "small"] @staticmethod def pizzatype_db(): # type: () -> List[Text] # Database of supported pizzatypes return ["BBQ", "Buffalo chicken", "Hawaiian", "cheese"] @staticmethod def toppings_db(): # type: () -> List[Text] #Database of supported toppings return ["onions", "mushrooms", "extra cheese", "sausage", "green peppers"] @staticmethod def is_int(string: Text) -> bool: # Check if a string is an integer try: int(string) return True except ValueError: return False 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 == 'size': if value.lower() not in self.size_db(): dispatcher.utter_template('utter_wrong_size', tracker) # validation failed, set slot to None slot_values[slot] = None elif slot == 'pizzatype': if value.lower() not in self.pizzatype_db(): dispatcher.utter_template('utter_wrong_pizzatype', tracker) # validation failed, set slot to None slot_values[slot] = None elif slot == 'ask_toppings': if isinstance(value, str): if 'yes' in value: # convert "out..." to True slot_values[slot] = True elif 'no' in value: # convert "in..." to False slot_values[slot] = False else: dispatcher.utter_template('utter_wrong_toppings1', tracker) # validation failed, set slot to None slot_values[slot] = None elif slot == 'toppings': if value.lower() not in self.toppings_db(): dispatcher.utter_template('utter_wrong_toppings2', tracker) # validation failed, set slot to None slot_values[slot] = None elif slot == 'num_pizza': if not self.is_int(value) or int(value) <= 0: dispatcher.utter_template('utter_wrong_num_pizza', 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()] def submit(self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: 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_affirm', tracker) return [] ``` **Content of stories file (stories.md)** : ``` ## first * greet - utter_greet * request_restaurant - restaurant_form - form{"name": "restaurant_form"} - form{"name": null} - utter_slots_values * thanks - utter_thank ## second path * greet - utter_greet * order_pizza - pizza_form - form{"name": "pizza_form"} - slot{"requested_slot": "size"} * form: informsize{"size": "large"} - slot{"size": "large"} - form: pizza_form - slot{"size": "large"} ## third path * greet - utter_greet * order_pizza - pizza_form - form{"name": "pizza_form"} - slot{"requested_slot": "size"} * form: informsize{"size": "large"} - slot{"size": "large"} - form: pizza_form - slot{"size": "large"} - slot{"requested_slot": "pizzatype"} * form: informtype{"pizzatype": "Hawaiian"} - slot{"pizzatype": "hawaiian"} - form: pizza_form - slot{"pizzatype": "hawaiian"} ## fourth * order_pizza - pizza_form - form{"name": "pizza_form"} - slot{"requested_slot": "size"} * form: informsize{"size": "large"} - slot{"size": "large"} - form: pizza_form - slot{"size": "large"} - slot{"requested_slot": "pizzatype"} * form: informtype{"pizzatype": "Hawaiian"} - slot{"pizzatype": "hawaiian"} - form: pizza_form - slot{"pizzatype": "hawaiian"} ## real path * greet - utter_greet * order_pizza - pizza_form - form{"name": "pizza_form"} - slot{"requested_slot": "size"} * form: informsize{"size": "large"} - slot{"size": "large"} - form: pizza_form - slot{"size": "large"} - slot{"requested_slot": "pizzatype"} * form: informtype{"pizzatype": "Hawaiian"} - slot{"pizzatype": "hawaiian"} - form: pizza_form - slot{"pizzatype": "hawaiian"} - slot{"requested_slot": "ask_toppings"} * form: affirm - form: pizza_form - slot{"ask_toppings": true} - slot{"requested_slot": "toppings"} * form: informtoppings{"toppings": "onions"} - slot{"toppings": "onions"} - form: pizza_form - slot{"toppings": "onions"} - slot{"requested_slot": "num_pizza"} * form: number{"number": "2"} - slot{"num_pizza": "2"} - form: pizza_form - slot{"num_pizza": "2"} - form{"name": null} - slot{"requested_slot": null} - utter_slots_values * thanks - utter_thank ```
akelad
commented
5 years ago
Please ask these kind of questions in our
forum