2

My goal:

I'm trying to implement a simple report rule using Forms for my RASA Assistant, which should work as following:

User: "I want to report something."
Assistant: "Please describe your problem in the following message."
User: <short description of problem>
Assistant: "Thank you for report."

I expect, that whole report message from user will be saved as a text (string) in report_message slot and that's also my main goal. I followed an official RASA documentation and probably missed something important or made a bug somewhere and I can't find out, what I did wrong.

Current State:

Current implementation works like this:

User: "I want to report something."
Assistant: "Thank you for report."

Assistant completely ignores utter_ask_report_message and report_message slot is filled with text content of my report intent - I want to report something..

My RASA project files:

nlu.yml

version: "2.0"

nlu:
  - intent: report
    examples: |
      - I want to report something.
      - I want to report a problem.
      - I want to report a bug.
      - #report

rules.yml

version: "2.0"

rules:
  - rule: Activate report_message_form
    steps:
      - intent: report
      - action: report_message_form
      - active_loop: report_message_form

  - rule: Submit report_message_form
    condition:
      - active_loop: report_message_form
    steps:
      - action: report_message_form
      - active_loop: null
      - slot_was_set:
          - requested_slot: null
      - action: utter_success_report_message_form

domain.yml

version: "2.0"

actions:
  - validate_report_message_form

intents:
  - report

entities:
  - report_message

slots:
  report_message:
    type: text

forms:
  report_message_form:
    report_message:
      - type: from_text
        intent: report

responses:
  utter_ask_report_message:
    - text: "Please describe your problem in the following message."

  utter_success_report_message_form:
    - text: "Thank you for report."

actions.py

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

from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
from rasa_sdk.types import DomainDict


class ValidateReportMessageForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_report_message_form"

    async def required_slots(
        self,
        slots_mapped_in_domain: List[Text],
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict
    ) -> Optional[List[Text]]:
        return slots_mapped_in_domain + ["report_message"]

    async def extract_report_message(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict
    ) -> Dict[Text, Any]:
        text_of_last_user_message = tracker.latest_message.get("text")
        return {"report_message": text_of_last_user_message}

Thanks for every help and suggestion.

Adam
  • 49
  • 1
  • 1
  • 7

1 Answers1

1

Thie issue is your implementation of validate_report_message_form. This action is also called during the activation of your form which means that extract_report_message will fill it with the text of the message which activates the form. You can fix that by adding a check of if tracker.slots["requested_slot"] == "report_message" to ensure to only set this slot when Rasa Open Source requested the user to fill the slot.

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

from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
from rasa_sdk.types import DomainDict


class ValidateReportMessageForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_report_message_form"

    async def required_slots(
        self,
        slots_mapped_in_domain: List[Text],
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict
    ) -> Optional[List[Text]]:
        return slots_mapped_in_domain + ["report_message"]

    async def extract_report_message(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict
    ) -> Dict[Text, Any]:
        if not tracker.slots["requested_slot"] == "report_message":
          return {}

        text_of_last_user_message = tracker.latest_message.get("text")
        return {"report_message": text_of_last_user_message}
Tobias
  • 1,880
  • 11
  • 17