MemoizationPolicy does not predict any action

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

@stephens could you help me please? I´m pulling my hair out trying to find a solution, changing memoizationPolicy parameters and stories but still doesn´t work properly.

This is a common problem when you write more and more stories and they get longer.

Instead, don’t use stories or the memoization policy. Use short rules which can be linked together. One “trick” for tying rules together is to use wait_for_user_input: false as described here.

Also, look at the use of rules & forms together in the rasa-demo bot.