How to stop a form loop

Hello ! After trying for days I can’t stop a form loop. I have a registration form and a story to activate it. If the user trigger intent to “stop” the registration process I have a story that ask the user if he wants to continue with a response “utter_ask_to_continue”. I only have three policies in my congif.yml : MemoizationPolicy TEDPolicy and RulePolicy. When the intent “stop” is triggered by the user , the TEDPolicy predicts the right next action (utter_ask_to_continue) but then using policy_3_RulePolicy predicts to keep running the form. Why ? I tried : 1 MappingPolicy : to trigger utter_ask_to_continue after the intent “stop” 2 I give different priorities to the policies 3 I develop stories to stop the registration 4 I wrote rules to stop registartion But the policy_3_RulePolicy always predicts to keep running the form. Can somebody suggest a solution to stop the loop of the registration form ? Thanks, Stefano

Maybe this tutorial can help you if this is your question

Hello, take a look at these examples:

Rules:

- rule: Activate form_log_in
  steps:
  - intent: log_in
  - action: form_log_in
  - active_loop: form_log_in

- rule: Submit form_log_in
  condition: # Condition that form is active
  - active_loop: form_log_in
  steps:
  - action: form_log_in
  - active_loop: null # Stop the form
  - slot_was_set:
    - requested_slot: null
  - action: action_submit_form_log_in

Stories

- story: User fills form_log_in
  steps:
  - intent: log_in
  - action: form_log_in
  - active_loop: form_log_in
  - active_loop: null
  - action: action_submit_form_log_in

- story: User fills form_log_in and stops
  steps:
  - intent: log_in
  - action: form_log_in
  - active_loop: form_log_in
  - intent: stop
  - action: action_deactivate_loop
  - active_loop: null
  - action: utter_okay

More examples here.

Thanks but even using these examples I still can’t stop the form loop. There must be something else in my model that prevents the TEDPolicy to predict the right action

@drindrin Hello, can you share? rasa --version, config.yml , and action.py file for our reference, please.

the problem is rasa.core.policies.rule_policy overwrire the memorized and TED prediction : -rasa.core.policies.memoization - There is a memorised next action ‘utter_ask_continue_reg’ -rasa.core.policies.ted_policy - TED predicted ‘utter_ask_continue_reg’ based on user intent. -rasa.core.policies.rule_policy - Current tracker state: -[state 1] user intent: regi | previous action name: action_listen -[state 2] user intent: regi | previous action name: reg_form | active loop: {‘name’: ‘reg_form’} -[state 3] user text: stop | previous action name: action_listen | active loop: {‘name’: ‘reg_form’} -rasa.core.policies.rule_policy - There is no applicable rule. -rasa.core.policies.rule_policy - Predicted loop ‘reg_form’. -rasa.core.processor - Predicted next action ‘reg_form’ with confidence 1.00.

C:\Users\stefa>rasa --version Rasa Version : 2.8.0 Minimum Compatible Version: 2.8.0 Rasa SDK Version : 2.8.2 Rasa X Version : None Python Version : 3.8.7 Operating System : Windows-10-10.0.19041-SP0 Python Path : c:\program files\python38\python.exe

language: it

pipeline:

  • name: SpacyNLP

    model: “it_core_news_sm”

  • name: SpacyTokenizer

  • name: SpacyFeaturizer

  • name: LexicalSyntacticFeaturizer

  • name: CountVectorsFeaturizer

  • name: CountVectorsFeaturizer

    analyzer: “char_wb”

    min_ngram: 2

    max_ngram: 4

  • name: DIETClassifier

    epochs: 100

    constrain_similarities: true

policies:

  • name: MemoizationPolicy

    max_history: 4

    priority: 4

  • name: TEDPolicy

    max_history: 10

    epochs: 10

    priority: 5

    constrain_similarities: true

  • name: RulePolicy

    priority: 3

from typing import Any, Text, Dict, List, Union

from rasa_sdk import Action, Tracker

from rasa_sdk.executor import CollectingDispatcher

from rasa_sdk.events import SlotSet,Restarted

from rasa_sdk.knowledge_base.storage import InMemoryKnowledgeBase

from rasa_sdk.forms import FormAction

from typing import Dict, Text, Any, List, Union

from rasa_sdk import Tracker,FormValidationAction, Action

from rasa_sdk.events import AllSlotsReset

from twilio.rest import Client

import phonenumbers

from phonenumbers import carrier, timezone, geocoder

import os

import csv

import pandas as pd

import array as arr

import requests, json

import numpy as np

import datetime as dt

from datetime import date, datetime

class ValidateRegForm(FormValidationAction):

  def name(self)-> Text:

      return "validate_reg_form"

  def validate_cell(

      self,

      slot_value: Any,

      dispatcher: CollectingDispatcher,

      tracker: Tracker,

      domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

      print(slot_value)

      # z = phonenumbers.AsYouTypeFormatter("IT")

      # for character in slot_value:

        #if character.isdigit():

      #      z.input_digit(character)

      z = phonenumbers.parse(slot_value, "IT")

      print(z)

      if not phonenumbers.is_valid_number(z):

        dispatcher.utter_message(text=f" scusi ho capito ".format(tracker.get_slot("cell"))+" che non mi sembra un numero valido . puo ripetere ?")

        return {"cell": None}

      dispatcher.utter_message(text=f" grazie ho capito ".format(tracker.get_slot("cell")))

      return {"cell": slot_value}

class SendSMS(Action):

def name(self)-> Text:

return "action_SMS"

def run(self, dispatcher: CollectingDispatcher,

         tracker: Tracker,

         domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

   

    account_sid='AC38b4f0f4af2bf3e17386d5e58f283d8a'

    auth_token ='6619a793c96f143db3dfaad183dcd240'

    client=Client(account_sid,auth_token)

   

    snome=tracker.get_slot("nome")

    scell=tracker.get_slot("cell")

    print(snome)

    print(scell)

    client.api.account.messages.create(

         to="+39"+scell,

         from_="+16183767536",#+393339765500",

         body="GRAZIE PER ESSERSI REGISTRATO "+snome

    )

    #tracker.get_slot("message"))

    #print(message.sid)

    dispatcher.utter_message(text="Le ho mandato un SMS al {}".format(tracker.get_slot("cell")))

    return []

class ActionSoloReset(Action):

 def name(self) -> Text:

        return "action_solo_reset"

 def run(self, dispatcher: CollectingDispatcher,

         tracker: Tracker,

         domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

     now = datetime.now()

     print(now.strftime("%m/%d/%Y, %H:%M:%S")+", risettato tutto")

     return [AllSlotsReset()]

class ActionResetRecord(Action):

 def name(self) -> Text:

        return "action_reset"

 def run(self, dispatcher: CollectingDispatcher,

         tracker: Tracker,

         domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

     snome=tracker.get_slot("nome")

     scitta=tracker.get_slot("citta")

     scell=tracker.get_slot("cell")

     sruolo=tracker.get_slot("ruolo")

     dispatcher.utter_message('Grazie per essersi registrato '+snome+' che vive a '+scitta +' con cellulare '+scell+' nel ruolo di '+sruolo)

     txt = open(r'./data/txt/registrati.txt', 'a')

     now = datetime.now()

     s =now.strftime("%m/%d/%Y, %H:%M:%S")+','+snome+','+scitta+','+scell+','+sruolo

     txt.write('\n')

     txt.write(s+"\n")

     txt.close()

     print(s)

     return [AllSlotsReset()]

class ActionAskReg(Action): #action_promo

 def name(self) -> Text:

     return "ask_reg"

 def run(self, dispatcher: CollectingDispatcher,

         tracker: Tracker,

         domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

     now = datetime.now()

     s =now.strftime("%m/%d/%Y, %H:%M:%S")+' chiesta reg'

     print(s)

     risposta="Vuole registrarsi tra i nostri visitatori?"

     dispatcher.utter_message(text=risposta)

     return []

@drindrin stories and rule files please?

version: “2.0” stories:

  • story: User fills reg_form steps:

    • intent: regi
    • action: reg_form
    • active_loop: reg_form
    • active_loop: null
    • action: action_reset
  • story: User fills reg_form and stops steps:

    • intent: regi
    • action: reg_form
    • active_loop: reg_form
    • or:
      • intent: stop
      • intent: deny
    • action: action_deactivate_loop
    • active_loop: null
    • action: utter_goodbye
  • story: interactive_story_1 steps:

    • intent: regi
    • action: reg_form
    • active_loop: reg_form
    • slot_was_set:
      • requested_slot: nome
    • slot_was_set:
      • nome: pippo
    • slot_was_set:
      • requested_slot: citta
    • intent: stop
    • action: utter_ask_continue_reg
    • intent: deny
    • action: action_deactivate_loop
    • active_loop: null
    • slot_was_set:
      • requested_slot: null
    • action: utter_goodbye

version: “2.0”

rules:

  • rule: Activate form_reg_in

    steps:

    • intent: regi

    • action: reg_form

    • active_loop: reg_form

  • rule: Submit Reg Form

    condition:

    • active_loop: reg_form

    steps:

    • action: reg_form

    • active_loop: null

    • slot_was_set:

      • requested_slot: null
    • action: action_reset

I’m not the only one to have this problem Can't get form to deactivate. Rasa 2.0 - Stack Overflow

@drindrin Can I ask you at the end of form, why there is no utterance ?

such as

action: action_reset
action: utter_submit etc

Just checking!

this is the all form examples please have a look and if you already seen then please check the rule or stories files from this repo: https://github.com/RasaHQ/rasa-2.x-form-examples

I do have at the end of stories

  • active_loop: null
  • action_reset and a rule
  • rule: Submit Reg Form condition:
    • active_loop: reg_form steps:
    • action: reg_form
    • active_loop: null
    • slot_was_set:
      • requested_slot: null
    • action: action_reset

Weird, it should work. You can use a FormValidationAction to return an empty list in the required_slot() method if the intent is ‘cancel’`:

def required_slots(self, dom_slots, dispatcher, tracker, domain):
    if tracker.latest_message['intent'] == 'cancel':
        return []
    else:
        return dom_slots # Or whatever your original required_slot() did

See this for more and alternatives: How can i have a rule to cancel a form?

Thanks everybody , I have fixed it by adding at each requested slot “not_intent: stop” es:

  • forms:
  • reg_form:
  • required_slots:
    
  •   name:
    
  •   - entity: name
    
  •     type: from_text
    
  •     not_intent: stop
    
  •   city:
    
  •   - entity: city
    
  •     type: from_text
    
  •     not_intent: stop
    
  • ect…
1 Like

Ah yes, of course :slight_smile:

please can you explain more, or even better if you can share the code, becuase i have the same issue

Dear Sir, Please help me, I made it

  • I have created a variable in the status_end_exam file domain.yml to assign the value true or false (true will end the test and vice versa)
  • In the stories.yml file, I have created a dialogue that, if I execute the action_speak_question_answer function and return status_end_exam = false, then render each question in the exam and if status_end_exam = false then execute uter_announce_EndExam.
  • In the action.py file, I wrote the action_speak_question_answer function that renders a question and the answers of that question (for example, there are 10 questions, each time will return to render 1 question based on utter_speak_QuestionAnswer) However, current_question did not increase to render the next question but only stopped at sentence 1 nlu.yml (2.3 KB) domain.yml (3.4 KB) stories.yml (4.6 KB) actions.py (5.8 KB)