Beispiel #1
0
def _create_from_endpoint_config(
    endpoint_config: Optional[EndpointConfig] = None, domain: Optional[Domain] = None
) -> "NaturalLanguageGenerator":
    """Given an endpoint configuration, create a proper NLG object."""

    domain = domain or Domain.empty()

    if endpoint_config is None:
        from rasa.core.nlg import TemplatedNaturalLanguageGenerator

        # this is the default type if no endpoint config is set
        nlg = TemplatedNaturalLanguageGenerator(domain.responses)
    elif endpoint_config.type is None or endpoint_config.type.lower() == "callback":
        from rasa.core.nlg import CallbackNaturalLanguageGenerator

        # this is the default type if no nlg type is set
        nlg = CallbackNaturalLanguageGenerator(endpoint_config=endpoint_config)
    elif endpoint_config.type.lower() == "response":
        from rasa.core.nlg import TemplatedNaturalLanguageGenerator

        nlg = TemplatedNaturalLanguageGenerator(domain.responses)
    elif endpoint_config.type.lower() == "template":
        rasa.shared.utils.io.raise_deprecation_warning(
            "Please change the NLG endpoint config type from `template` to `response`.",
            docs=f"{DOCS_URL_MIGRATION_GUIDE}#rasa-23-to-rasa-24",
        )
        from rasa.core.nlg import TemplatedNaturalLanguageGenerator

        nlg = TemplatedNaturalLanguageGenerator(domain.responses)
    else:
        nlg = _load_from_module_name_in_endpoint_config(endpoint_config, domain)

    logger.debug(f"Instantiated NLG to '{nlg.__class__.__name__}'.")
    return nlg
Beispiel #2
0
def _create_from_endpoint_config(
        endpoint_config: Optional[EndpointConfig] = None,
        domain: Optional[Domain] = None) -> "NaturalLanguageGenerator":
    """Given an endpoint configuration, create a proper NLG object."""

    domain = domain or Domain.empty()

    if endpoint_config is None:
        from rasa.core.nlg import (  # pytype: disable=pyi-error
            TemplatedNaturalLanguageGenerator, )

        # this is the default type if no endpoint config is set
        nlg = TemplatedNaturalLanguageGenerator(domain.templates)
    elif endpoint_config.type is None or endpoint_config.type.lower(
    ) == "callback":
        from rasa.core.nlg import (  # pytype: disable=pyi-error
            CallbackNaturalLanguageGenerator, )

        # this is the default type if no nlg type is set
        nlg = CallbackNaturalLanguageGenerator(endpoint_config=endpoint_config)
    elif endpoint_config.type.lower() == "template":
        from rasa.core.nlg import (  # pytype: disable=pyi-error
            TemplatedNaturalLanguageGenerator, )

        nlg = TemplatedNaturalLanguageGenerator(domain.templates)
    else:
        nlg = _load_from_module_name_in_endpoint_config(
            endpoint_config, domain)

    logger.debug(f"Instantiated NLG to '{nlg.__class__.__name__}'.")
    return nlg
    def create(
        obj: Union["NaturalLanguageGenerator", EndpointConfig, None],
        domain: Optional[Domain],
    ) -> "NaturalLanguageGenerator":
        """Factory to create a generator."""

        custom_nlg = None
        if isinstance(obj, EndpointConfig) and obj.type:
            custom_nlg = NaturalLanguageGenerator.load_nlg_from_module_string(
                obj)

        if isinstance(obj, NaturalLanguageGenerator):
            return obj
        elif custom_nlg:
            return custom_nlg(domain=domain, endpoint_config=obj)
        elif isinstance(obj, EndpointConfig) and obj.url:
            from rasa.core.nlg import (  # pytype: disable=pyi-error
                CallbackNaturalLanguageGenerator, )

            return CallbackNaturalLanguageGenerator(obj)
        elif obj is None:
            from rasa.core.nlg import (  # pytype: disable=pyi-error
                TemplatedNaturalLanguageGenerator, )

            templates = domain.templates if domain else []
            return TemplatedNaturalLanguageGenerator(templates)
        else:
            raise Exception("Cannot create a NaturalLanguageGenerator "
                            "based on the passed object. Type: `{}`"
                            "".format(type(obj)))
Beispiel #4
0
def test_predict_next_action_raises_limit_reached_exception(domain: Domain):
    interpreter = RegexInterpreter()
    ensemble = SimplePolicyEnsemble(
        policies=[RulePolicy(), MemoizationPolicy()])
    tracker_store = InMemoryTrackerStore(domain)
    lock_store = InMemoryLockStore()

    processor = MessageProcessor(
        interpreter,
        ensemble,
        domain,
        tracker_store,
        lock_store,
        TemplatedNaturalLanguageGenerator(domain.responses),
        max_number_of_predictions=1,
    )

    tracker = DialogueStateTracker.from_events(
        "test",
        evts=[
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered("Hi!"),
            ActionExecuted("test_action"),
        ],
    )
    tracker.set_latest_action({"action_name": "test_action"})

    with pytest.raises(ActionLimitReached):
        processor.predict_next_action(tracker)
Beispiel #5
0
async def test_1st_affirmation_is_successful():
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User affirms
            UserUttered("hi", {"name": "greet", "confidence": 1.0}),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )

    for events in events:
        tracker.update(events, domain)

    applied_events = tracker.applied_events()
    assert applied_events == [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("hi", {"name": "greet", "confidence": 1.0}),
    ]
Beispiel #6
0
async def test_activate_with_prefilled_slot():
    slot_name = "num_people"
    slot_value = 5

    tracker = DialogueStateTracker.from_events(
        sender_id="bla", evts=[SlotSet(slot_name, slot_value)])
    form_name = "my form"
    action = FormAction(form_name, None)

    next_slot_to_request = "next slot to request"
    domain = f"""
    forms:
      {form_name}:
        {slot_name}:
        - type: from_entity
          entity: {slot_name}
        {next_slot_to_request}:
        - type: from_text
    slots:
      {slot_name}:
        type: unfeaturized
    """
    domain = Domain.from_yaml(domain)
    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )
    assert events == [
        ActiveLoop(form_name),
        SlotSet(slot_name, slot_value),
        SlotSet(REQUESTED_SLOT, next_slot_to_request),
    ]
Beispiel #7
0
async def test_ask_affirm_after_rephrasing():
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents
            UserUttered("hi", {"name": USER_INTENT_OUT_OF_SCOPE}),
            # Action asks user to rephrase
            ActionExecuted(ACTION_TWO_STAGE_FALLBACK_NAME),
            BotUttered("please rephrase"),
            # User rephrased with low confidence
            *_message_requiring_fallback(),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        tracker,
        domain,
    )

    assert len(events) == 1
    assert isinstance(events[0], BotUttered)
Beispiel #8
0
    def create(
        obj: Union["NaturalLanguageGenerator", EndpointConfig, None],
        domain: Optional[Domain],
    ) -> "NaturalLanguageGenerator":
        """Factory to create a generator."""

        if isinstance(obj, NaturalLanguageGenerator):
            return obj
        elif isinstance(obj, EndpointConfig):
            from rasa.core.nlg import (  # pytype: disable=pyi-error
                CallbackNaturalLanguageGenerator,
            )

            return CallbackNaturalLanguageGenerator(obj)
        elif obj is None:
            from rasa.core.nlg import (  # pytype: disable=pyi-error
                TemplatedNaturalLanguageGenerator,
            )

            templates = domain.templates if domain else []
            return TemplatedNaturalLanguageGenerator(templates)
        else:
            raise Exception(
                "Cannot create a NaturalLanguageGenerator "
                "based on the passed object. Type: `{}`"
                "".format(type(obj))
            )
Beispiel #9
0
async def test_action_rejection():
    form_name = "my form"
    slot_to_fill = "some slot"
    tracker = DialogueStateTracker.from_events(
        sender_id="bla",
        evts=[
            ActiveLoop(form_name),
            SlotSet(REQUESTED_SLOT, slot_to_fill),
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered("haha", {"name": "greet"}),
        ],
    )
    form_name = "my form"
    action = FormAction(form_name, None)
    domain = f"""
    forms:
      {form_name}:
        {slot_to_fill}:
        - type: from_entity
          entity: some_entity
    slots:
      {slot_to_fill}:
        type: unfeaturized
    """
    domain = Domain.from_yaml(domain)

    with pytest.raises(ActionExecutionRejection):
        await action.run(
            CollectingOutputChannel(),
            TemplatedNaturalLanguageGenerator(domain.templates),
            tracker,
            domain,
        )
Beispiel #10
0
async def test_activate():
    tracker = DialogueStateTracker.from_events(sender_id="bla", evts=[])
    form_name = "my form"
    action = FormAction(form_name, None)
    slot_name = "num_people"
    domain = f"""
forms:
  {form_name}:
    {slot_name}:
    - type: from_entity
      entity: number
responses:
    utter_ask_num_people:
    - text: "How many people?"
"""
    domain = Domain.from_yaml(domain)

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )
    assert events[:-1] == [
        ActiveLoop(form_name),
        SlotSet(REQUESTED_SLOT, slot_name)
    ]
    assert isinstance(events[-1], BotUttered)
Beispiel #11
0
async def test_set_slot_and_deactivate():
    form_name = "my form"
    slot_name = "num_people"
    slot_value = "dasdasdfasdf"
    events = [
        Form(form_name),
        SlotSet(REQUESTED_SLOT, slot_name),
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered(slot_value),
    ]
    tracker = DialogueStateTracker.from_events(sender_id="bla", evts=events)

    domain = f"""
    forms:
    - {form_name}:
        {slot_name}:
        - type: from_text
    slots:
      {slot_name}:
        type: unfeaturized
    """
    domain = Domain.from_yaml(domain)

    action = FormAction(form_name, None)
    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )
    assert events == [
        SlotSet(slot_name, slot_value),
        SlotSet(REQUESTED_SLOT, None),
        Form(None),
    ]
Beispiel #12
0
async def test_2nd_affirmation_failed(intent_which_lets_action_give_up: Text):
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents
            UserUttered("hi", {"name": USER_INTENT_OUT_OF_SCOPE}),
            # Action asks user to rephrase
            *_two_stage_clarification_request(),
            # User rephrased with low confidence
            *_message_requiring_fallback(),
            # Actions asks user to affirm for the last time
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents for the second time
            UserUttered("hi", {"name": intent_which_lets_action_give_up}),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        tracker,
        domain,
    )

    assert events == [ActiveLoop(None), UserUtteranceReverted()]
Beispiel #13
0
async def test_action_unlikely_intent_metadata(
        default_processor: MessageProcessor):
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            ActionExecuted(ACTION_LISTEN_NAME),
        ],
    )
    domain = Domain.empty()
    metadata = {"key1": 1, "key2": "2"}

    await default_processor._run_action(
        ActionUnlikelyIntent(),
        tracker,
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        PolicyPrediction([], "some policy", action_metadata=metadata),
    )

    applied_events = tracker.applied_events()
    assert applied_events == [
        ActionExecuted(ACTION_LISTEN_NAME),
        ActionExecuted(ACTION_UNLIKELY_INTENT_NAME, metadata=metadata),
    ]
    assert applied_events[1].metadata == metadata
Beispiel #14
0
async def test_loop_without_activate_and_without_deactivate():
    expected_do_events = [ActionExecuted("do")]
    form_name = "my form"

    class MyLoop(LoopAction):
        def name(self) -> Text:
            return form_name

        async def activate(self, *args: Any) -> List[Event]:
            raise ValueError("this shouldn't be called")

        async def do(self, *args: Any) -> List[Event]:
            return expected_do_events

        async def deactivate(self, *args) -> List[Event]:
            return [SlotSet("deactivated")]

        async def is_activated(self, *args: Any) -> bool:
            return True

        async def is_done(self, *args) -> bool:
            return False

    tracker = DialogueStateTracker.from_events("some sender", [])
    domain = Domain.empty()

    action = MyLoop()
    actual = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        tracker,
        domain,
    )

    assert actual == [*expected_do_events]
Beispiel #15
0
async def test_validate_slots_on_activation_with_other_action_after_user_utterance(
):
    form_name = "my form"
    slot_name = "num_people"
    slot_value = "hi"
    events = [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered(slot_value,
                    entities=[{
                        "entity": "num_tables",
                        "value": 5
                    }]),
        ActionExecuted("action_in_between"),
    ]
    tracker = DialogueStateTracker.from_events(sender_id="bla", evts=events)

    domain = f"""
    slots:
      {slot_name}:
        type: unfeaturized
    forms:
      {form_name}:
        {slot_name}:
        - type: from_text
    actions:
    - validate_{form_name}
    """
    domain = Domain.from_yaml(domain)
    action_server_url = "http:/my-action-server:5055/webhook"

    expected_slot_value = "✅"
    with aioresponses() as mocked:
        mocked.post(
            action_server_url,
            payload={
                "events": [{
                    "event": "slot",
                    "name": slot_name,
                    "value": expected_slot_value
                }]
            },
        )

        action_server = EndpointConfig(action_server_url)
        action = FormAction(form_name, action_server)

        events = await action.run(
            CollectingOutputChannel(),
            TemplatedNaturalLanguageGenerator(domain.templates),
            tracker,
            domain,
        )

    assert events == [
        ActiveLoop(form_name),
        SlotSet(slot_name, expected_slot_value),
        SlotSet(REQUESTED_SLOT, None),
        ActiveLoop(None),
    ]
Beispiel #16
0
async def default_processor(default_agent: Agent) -> MessageProcessor:
    tracker_store = InMemoryTrackerStore(default_agent.domain)
    return MessageProcessor(
        default_agent.interpreter,
        default_agent.policy_ensemble,
        default_agent.domain,
        tracker_store,
        TemplatedNaturalLanguageGenerator(default_agent.domain.templates),
    )
Beispiel #17
0
async def test_2nd_affirm_successful(default_processor: MessageProcessor):
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered("my name is John", {
                "name": "say_name",
                "confidence": 1.0
            }),
            SlotSet("some_slot", "example_value"),
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents
            UserUttered("hi", {"name": USER_INTENT_OUT_OF_SCOPE}),
            # Action asks user to rephrase
            *_two_stage_clarification_request(),
            # User rephrased with low confidence
            *_message_requiring_fallback(),
            *_two_stage_clarification_request(),
            # Actions asks user to affirm for the last time
            ActionExecuted(ACTION_LISTEN_NAME),
            # User affirms successfully
            UserUttered("hi", {"name": "greet"}),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    await default_processor._run_action(
        action,
        tracker,
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        PolicyPrediction([], "some policy"),
    )

    applied_events = tracker.applied_events()

    assert applied_events == [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("my name is John", {
            "name": "say_name",
            "confidence": 1.0
        }),
        SlotSet("some_slot", "example_value"),
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("hi", {"name": "greet"}),
    ]
Beispiel #18
0
async def test_dispatcher_template_invalid_vars():
    templates = {
        "my_made_up_template": [
            {"text": "a template referencing an invalid {variable}."}
        ]
    }
    bot = CollectingOutputChannel()
    nlg = TemplatedNaturalLanguageGenerator(templates)
    dispatcher = Dispatcher("my-sender", bot, nlg)
    tracker = DialogueStateTracker("my-sender", slots=[])
    await dispatcher.utter_template("my_made_up_template", tracker)
    collected = dispatcher.output_channel.latest_output()
    assert collected["text"].startswith("a template referencing an invalid {variable}.")
Beispiel #19
0
async def test_dispatcher_utter_buttons_from_domain_templ(default_tracker):
    domain_file = "examples/moodbot/domain.yml"
    domain = Domain.load(domain_file)
    bot = CollectingOutputChannel()
    nlg = TemplatedNaturalLanguageGenerator(domain.templates)
    dispatcher = Dispatcher("my-sender", bot, nlg)
    await dispatcher.utter_template("utter_greet", default_tracker)
    assert len(bot.messages) == 1
    assert bot.messages[0]["text"] == "Hey! How are you?"
    assert bot.messages[0]["buttons"] == [
        {"payload": "great", "title": "great"},
        {"payload": "super sad", "title": "super sad"},
    ]
Beispiel #20
0
async def test_validate_slots(validate_return_events: List[Dict],
                              expected_events: List[Event]):
    form_name = "my form"
    slot_name = "num_people"
    slot_value = "hi"
    events = [
        ActiveLoop(form_name),
        SlotSet(REQUESTED_SLOT, slot_name),
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered(slot_value,
                    entities=[{
                        "entity": "num_tables",
                        "value": 5
                    }]),
    ]
    tracker = DialogueStateTracker.from_events(sender_id="bla", evts=events)

    domain = f"""
    slots:
      {slot_name}:
        type: any
      num_tables:
        type: any
    forms:
      {form_name}:
        {slot_name}:
        - type: from_text
        num_tables:
        - type: from_entity
          entity: num_tables
    actions:
    - validate_{form_name}
    """
    domain = Domain.from_yaml(domain)
    action_server_url = "http:/my-action-server:5055/webhook"

    with aioresponses() as mocked:
        mocked.post(action_server_url,
                    payload={"events": validate_return_events})

        action_server = EndpointConfig(action_server_url)
        action = FormAction(form_name, action_server)

        events = await action.run(
            CollectingOutputChannel(),
            TemplatedNaturalLanguageGenerator(domain.templates),
            tracker,
            domain,
        )
        assert events == expected_events
Beispiel #21
0
async def test_ask_affirmation(events: List[Event]):
    tracker = DialogueStateTracker.from_events("some-sender", evts=events)
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        tracker,
        domain,
    )

    assert len(events) == 2
    assert events[0] == ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME)
    assert isinstance(events[1], BotUttered)
Beispiel #22
0
async def test_activate_and_immediate_deactivate():
    slot_name = "num_people"
    slot_value = 5

    tracker = DialogueStateTracker.from_events(
        sender_id="bla",
        evts=[
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered(
                "haha",
                {"name": "greet"},
                entities=[{
                    "entity": slot_name,
                    "value": slot_value
                }],
            ),
        ],
    )
    form_name = "my form"
    action = FormAction(form_name, None)
    domain = f"""
    forms:
      {form_name}:
        {slot_name}:
        - type: from_entity
          entity: {slot_name}
    slots:
      {slot_name}:
        type: unfeaturized
    """
    domain = Domain.from_yaml(domain)
    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )
    assert events == [
        ActiveLoop(form_name),
        SlotSet(slot_name, slot_value),
        SlotSet(REQUESTED_SLOT, None),
        ActiveLoop(None),
    ]
Beispiel #23
0
async def test_2nd_affirm_successful():
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents
            UserUttered("hi", {"name": USER_INTENT_OUT_OF_SCOPE}),
            # Action asks user to rephrase
            *_two_stage_clarification_request(),
            # User rephrased with low confidence
            *_message_requiring_fallback(),
            *_two_stage_clarification_request(),
            # Actions asks user to affirm for the last time
            ActionExecuted(ACTION_LISTEN_NAME),
            # User affirms successfully
            UserUttered("hi", {"name": "greet"}),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )

    for event in events:
        tracker.update(event)

    applied_events = tracker.applied_events()

    assert applied_events == [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("hi", {"name": "greet"}),
    ]
Beispiel #24
0
async def test_no_slots_extracted_with_custom_slot_mappings(
        custom_events: List[Event]):
    form_name = "my form"
    events = [
        ActiveLoop(form_name),
        SlotSet(REQUESTED_SLOT, "num_tables"),
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("off topic"),
    ]
    tracker = DialogueStateTracker.from_events(sender_id="bla", evts=events)

    domain = f"""
    slots:
      num_tables:
        type: any
    forms:
      {form_name}:
        num_tables:
        - type: from_entity
          entity: num_tables
    actions:
    - validate_{form_name}
    """
    domain = Domain.from_yaml(domain)
    action_server_url = "http:/my-action-server:5055/webhook"

    with aioresponses() as mocked:
        mocked.post(action_server_url, payload={"events": custom_events})

        action_server = EndpointConfig(action_server_url)
        action = FormAction(form_name, action_server)

        with pytest.raises(ActionExecutionRejection):
            await action.run(
                CollectingOutputChannel(),
                TemplatedNaturalLanguageGenerator(domain.templates),
                tracker,
                domain,
            )
Beispiel #25
0
async def test_processor_logs_text_tokens_in_tracker(mood_agent: Agent):
    text = "Hello there"
    tokenizer = WhitespaceTokenizer()
    tokens = tokenizer.tokenize(Message(data={"text": text}), "text")
    indices = [(t.start, t.end) for t in tokens]

    message = UserMessage(text)
    tracker_store = InMemoryTrackerStore(mood_agent.domain)
    lock_store = InMemoryLockStore()
    processor = MessageProcessor(
        mood_agent.interpreter,
        mood_agent.policy_ensemble,
        mood_agent.domain,
        tracker_store,
        lock_store,
        TemplatedNaturalLanguageGenerator(mood_agent.domain.responses),
    )
    tracker = await processor.log_message(message)
    event = tracker.get_last_event_for(event_type=UserUttered)
    event_tokens = event.as_dict().get("parse_data").get("text_tokens")

    assert event_tokens == indices
Beispiel #26
0
async def test_ask_rephrase_after_failed_affirmation():
    rephrase_text = "please rephrase"
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            Form(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            ActionExecuted(ACTION_LISTEN_NAME),
            # User denies suggested intents
            UserUttered("hi", {"name": USER_INTENT_OUT_OF_SCOPE}),
        ],
    )

    domain = Domain.from_yaml(
        f"""
        responses:
            utter_ask_rephrase:
            - {rephrase_text}
        """
    )
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )

    assert len(events) == 1
    assert isinstance(events[0], BotUttered)

    bot_utterance = events[0]
    assert isinstance(bot_utterance, BotUttered)
    assert bot_utterance.text == rephrase_text
Beispiel #27
0
async def test_give_it_up_after_low_confidence_after_affirm_request():
    tracker = DialogueStateTracker.from_events(
        "some-sender",
        evts=[
            # User sends message with low NLU confidence
            *_message_requiring_fallback(),
            ActiveLoop(ACTION_TWO_STAGE_FALLBACK_NAME),
            # Action asks user to affirm
            *_two_stage_clarification_request(),
            # User's affirms with low NLU confidence again
            *_message_requiring_fallback(),
        ],
    )
    domain = Domain.empty()
    action = TwoStageFallbackAction()

    events = await action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        tracker,
        domain,
    )

    assert events == [ActiveLoop(None), UserUtteranceReverted()]
Beispiel #28
0
async def test_one_stage_fallback_rule():
    domain = Domain.from_yaml(f"""
        intents:
        - {GREET_INTENT_NAME}
        - {DEFAULT_NLU_FALLBACK_INTENT_NAME}
        actions:
        - {UTTER_GREET_ACTION}
    """)

    fallback_recover_rule = TrackerWithCachedStates.from_events(
        "bla",
        domain=domain,
        slots=domain.slots,
        evts=[
            ActionExecuted(RULE_SNIPPET_ACTION_NAME),
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered(intent={"name": DEFAULT_NLU_FALLBACK_INTENT_NAME}),
            ActionExecuted(ACTION_DEFAULT_FALLBACK_NAME),
            ActionExecuted(ACTION_LISTEN_NAME),
        ],
        is_rule_tracker=True,
    )

    greet_rule_which_only_applies_at_start = TrackerWithCachedStates.from_events(
        "bla",
        domain=domain,
        evts=[
            ActionExecuted(ACTION_LISTEN_NAME),
            UserUttered(intent={"name": GREET_INTENT_NAME}),
            ActionExecuted(UTTER_GREET_ACTION),
            ActionExecuted(ACTION_LISTEN_NAME),
        ],
        is_rule_tracker=True,
    )
    policy = RulePolicy()
    policy.train(
        [greet_rule_which_only_applies_at_start, fallback_recover_rule],
        domain,
        RegexInterpreter(),
    )

    # RulePolicy predicts fallback action
    conversation_events = [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("dasdakl;fkasd",
                    {"name": DEFAULT_NLU_FALLBACK_INTENT_NAME}),
    ]
    tracker = DialogueStateTracker.from_events("casd",
                                               evts=conversation_events,
                                               slots=domain.slots)
    action_probabilities = policy.predict_action_probabilities(
        tracker, domain, RegexInterpreter())
    assert_predicted_action(action_probabilities, domain,
                            ACTION_DEFAULT_FALLBACK_NAME)

    # Fallback action reverts fallback events, next action is `ACTION_LISTEN`
    conversation_events += await ActionDefaultFallback().run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.templates),
        tracker,
        domain,
    )

    # Rasa is back on track when user rephrased intent
    conversation_events += [
        ActionExecuted(ACTION_LISTEN_NAME),
        UserUttered("haha", {"name": GREET_INTENT_NAME}),
    ]
    tracker = DialogueStateTracker.from_events("casd",
                                               evts=conversation_events,
                                               slots=domain.slots)

    action_probabilities = policy.predict_action_probabilities(
        tracker, domain, RegexInterpreter())
    assert_predicted_action(action_probabilities, domain, UTTER_GREET_ACTION)
Beispiel #29
0
def default_nlg(default_domain):
    return TemplatedNaturalLanguageGenerator(default_domain.templates)
Beispiel #30
0
def default_nlg(domain: Domain) -> NaturalLanguageGenerator:
    return TemplatedNaturalLanguageGenerator(domain.responses)