I´m working on a rasa example using Rasa 3.6.15. The example consists of a bot that asks for a pizza using a form and if the user wants to provide personal information (after “affirm” intent) then starts another form asking for it. In my stories.yml file I wrote the following story:
version: '3.1'
stories:
- story: interactive_story_1
steps:
- intent: greet
- action: utter_greet
- action: simple_pizza_form
- active_loop: simple_pizza_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: utter_submit
- action: utter_ask_next_form
- intent: affirm
- action: personal_info_form
- active_loop: personal_info_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: utter_goodbye
After I train the model I run rasa shell --debug following the same steps as in the story above but after it detects affirm intent MemoizationPolicy does not trigger personal_info_form. This is what prints when I reply with affirm intent, as you can see it predicts “personal_info_form” using TEDPolicy but there is no memorised next action even though stories.yml says so.
Why does not predict using MemoizationPolicy? Here is my config.yml file:
recipe: default.v1
assistant_id: 20240407-180409-lazy-cycle
language: en
pipeline:
- name: WhitespaceTokenizer
- name: RegexFeaturizer
- name: LexicalSyntacticFeaturizer
- name: CountVectorsFeaturizer
- name: CountVectorsFeaturizer
analyzer: char_wb
min_ngram: 1
max_ngram: 4
- name: DIETClassifier
epochs: 100
constrain_similarities: true
- name: EntitySynonymMapper
- name: ResponseSelector
epochs: 100
constrain_similarities: true
- name: FallbackClassifier
threshold: 0.3
ambiguity_threshold: 0.1
policies:
- name: MemoizationPolicy
max_history: 40
epochs: 300
- name: RulePolicy
- name: UnexpecTEDIntentPolicy
max_history: 5
epochs: 100
- name: TEDPolicy
max_history: 5
epochs: 100
constrain_similarities: true
domain.yml:
version: '3.1'
forms:
simple_pizza_form:
required_slots:
- pizza_size
- pizza_type
personal_info_form:
required_slots:
- name
- age
slots:
pizza_size:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: pizza_size
pizza_type:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: pizza_type
name:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: name
age:
type: float
influence_conversation: true
mappings:
- type: from_entity
entity: age
entities:
- pizza_type
- age
- name
- pizza_size
intents:
- deny
- restart
- affirm
- buy_pizza
- greet
- inform
- informy
- stop
responses:
utter_submit:
- text: I will now order a pizza for you!
utter_pizza_slots:
- text: I will order a {pizza_size} {pizza_type} pizza.
utter_ask_pizza_size:
- text: What size would you like your pizza to be?
utter_ask_pizza_type:
- text: What kind of pizza would you like to buy?
utter_ask_name:
- text: What is your name?
utter_ask_age:
- text: How old are you?
utter_ask_continue:
- text: Do you want to continue?
utter_greet:
- text: Hi! How can I help you today?
utter_goodbye:
- text: Goodbye!
utter_ask_next_form:
- text: Do you want to provide more information?
utter_ask_restart:
- text: Do you want to order another pizza?
utter_restart:
- text: We will start again.
actions:
- utter_restart
- utter_ask_restart
- utter_greet
- utter_pizza_slots
- utter_submit
- utter_ask_next_form
- utter_goodbye
- validate_simple_pizza_form
session_config:
session_expiration_time: 60
carry_over_slots_to_new_session: true
actions.py:
from typing import Text, List, Any, Dict
from rasa_sdk import Tracker, FormValidationAction, Action
from rasa_sdk.events import EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
ALLOWED_PIZZA_SIZES = [
"small", "large", "extra-large", "extra large",
"s", "m", "l", "xl"
]
ALLOWED_PIZZA_TYPES = [
"mozzarella", "fungi", "veggie", "pepperoni", "hawaii"
]
class ValidateSimplePizzaForm(FormValidationAction):
def name(self) -> Text:
return "validate_simple_pizza_form"
def validate_pizza_size(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate `pizza_size` value."""
if slot_value.lower() not in ALLOWED_PIZZA_SIZES:
dispatcher.utter_message(text=f"We only accept pizza sizes: s/m/l/xl.")
return {"pizza_size": None}
dispatcher.utter_message(text=f"OK! You want to have a {slot_value} pizza.")
return {"pizza_size": slot_value}
def validate_pizza_type(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate `pizza_type` value."""
if slot_value not in ALLOWED_PIZZA_TYPES:
msg = "I don't recognize that pizza."
msg += f"We only serve {'/'.join(ALLOWED_PIZZA_TYPES)}."
dispatcher.utter_message(msg)
return {"pizza_type": None}
dispatcher.utter_message(text=f"OK! You want to have a {slot_value} pizza.")
return {"pizza_type": slot_value}
rules.py:
version: '3.1'
rules:
- rule: Activate Pizza Form
steps:
- intent: buy_pizza
- action: simple_pizza_form
- active_loop: simple_pizza_form