Create rule to avoid repetition of response

My bot has an automatic response that is always sent at beginning of an interaction:

  • action: utter_automatic_response

  • story: typical_story_start steps:

    • intent: greet
    • action: utter_automatic_response
    • action: utter_greet

The problem is that sometimes the bot uses the utter_automatic_response again after the initial interaction. Something like this:

  • intent: greet
  • action: utter_automatic_response
  • action: utter_greet
  • intent: ask_delivery_time
  • action: utter_automatic_response
  • action: utter_greet
  • action: action_get_delivery_time

I could add stories to avoid that behaviour but I was wondering if there was a way to set a rule to avoid repeating the utter_automatic_response.

I’m creating a custom policy:

from rasa.core.policies.policy import Policy
from rasa.shared.nlu.interpreter import NaturalLanguageInterpreter
from rasa.shared.core.trackers import DialogueStateTracker
from rasa.shared.core.domain import Domain
from rasa.shared.core.events import ActionExecuted
from typing import Any


# Define a custom policy that avoids repeating a specific response
class NoRepeatCustomPolicy(Policy):
    def __init__(self, priority: int = 1, *args, **kwargs):
        super().__init__(priority=priority, *args, **kwargs)
    
    @classmethod
    def _metadata_filename(cls) -> Optional[Text]:
        return "no_repetition_policy"

    def train(self, training_trackers, domain, **kwargs) -> None:
        pass

    def predict_action_probabilities(self, tracker: DialogueStateTracker,
                                     domain: Domain,
                                     interpreter: NaturalLanguageInterpreter,
                                     **kwargs: Any):
        # Get the desired response that we don't want to repeat
        desired_response = "utter_automatic_response"

        # Check if the desired response has already been used
        previous_responses = [e.action_name for e in tracker.events if isinstance(e, ActionExecuted)]
        action_index = domain.index_for_action("utter_automatic_response")

        if desired_response in previous_responses:
            # If the response has already been used, choose a different response
            return [0.0 if i == action_index else 1.0 for i in range(domain.num_actions)]
        else:
            # If the response has not been used all probabilities should remain constant
            return [1.0] * domain.num_actions

my config.yml look like this:

policies:
# # No configuration for policies was provided. The following default policies were used to train your model.
# # If you'd like to customize them, uncomment and adjust the policies.
# # See https://rasa.com/docs/rasa/policies for more information.
   - name: MemoizationPolicy
   - name: RulePolicy
   - name: "custom_policy.no_repetition_policy.NoRepeatCustomPolicy"
   - name: UnexpecTEDIntentPolicy
     max_history: 5
     epochs: 100
   - name: TEDPolicy
     max_history: 5
     epochs: 100
     constrain_similarities: true

The custom policy is inside a custom_policy dir inside a file called no_repetition_policy

Take a look at Rules for the Conversation Start.

That works to make sure the utter_automatic_response is used at the beginning. I’ll test it. However, I need a rule that:

conversation_start: False Dont use utter_automatic_response

So, there must be other rules/stories that issue utter_automatic_response.

There are no stories that specify using utter_automatic_response outside of the initial response but the bot predict it in certain situations