Example #1
0
def test_nlg_fill_response_custom(slot_name: Text, slot_value: Any):
    response = {
        "custom": {
            "field": f"{{{slot_name}}}",
            "properties": {
                "field_prefixed": f"prefix_{{{slot_name}}}"
            },
            "bool_field": True,
            "int_field:": 42,
            "empty_field": None,
        }
    }
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response=response,
                              filled_slots={slot_name: slot_value})

    assert result == {
        "custom": {
            "field": str(slot_value),
            "properties": {
                "field_prefixed": f"prefix_{slot_value}"
            },
            "bool_field": True,
            "int_field:": 42,
            "empty_field": None,
        }
    }
Example #2
0
def test_nlg_fill_response_text_and_custom(text_slot_name, text_slot_value,
                                           cust_slot_name, cust_slot_value):
    response = {
        "text": f"{{{text_slot_name}}}",
        "custom": {
            "field": f"{{{cust_slot_name}}}",
            "properties": {
                "field_prefixed": f"prefix_{{{cust_slot_name}}}"
            },
        },
    }
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(
        response=response,
        filled_slots={
            text_slot_name: text_slot_value,
            cust_slot_name: cust_slot_value
        },
    )
    assert result == {
        "text": str(text_slot_value),
        "custom": {
            "field": str(cust_slot_value),
            "properties": {
                "field_prefixed": f"prefix_{str(cust_slot_value)}"
            },
        },
    }
Example #3
0
def test_nlg_fill_response_quick_replies(quick_replies_slot_name,
                                         quick_replies_slot_value):
    response = {"quick_replies": f"{{{quick_replies_slot_name}}}"}
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(
        response=response,
        filled_slots={quick_replies_slot_name: quick_replies_slot_value},
    )
    assert result == {"quick_replies": str(quick_replies_slot_value)}
Example #4
0
def test_nlg_fill_response_text_with_json(response_text, expected):
    response = {"text": response_text}
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response=response,
                              filled_slots={
                                  "slot_1": "foo",
                                  "slot_2": "bar"
                              })
    assert result == {"text": expected}
Example #5
0
async def test_run_end_to_end_utterance_action():
    end_to_end_utterance = "Hi"

    domain = Domain.from_yaml(
        textwrap.dedent(f"""
    actions:
    - my_action
    {KEY_E2E_ACTIONS}:
    - {end_to_end_utterance}
    - Bye Bye
"""))

    e2e_action = action.action_for_name_or_text("Hi", domain, None)
    events = await e2e_action.run(
        CollectingOutputChannel(),
        TemplatedNaturalLanguageGenerator(domain.responses),
        DialogueStateTracker.from_events("sender", evts=[]),
        domain,
    )

    assert events == [
        BotUttered(
            end_to_end_utterance,
            {
                "elements": None,
                "quick_replies": None,
                "buttons": None,
                "attachment": None,
                "image": None,
                "custom": None,
            },
            {},
        )
    ]
Example #6
0
async def test_nlg_conditional_response_variations_with_yaml_and_channel():
    domain = Domain.from_file(
        path="data/test_domains/conditional_response_variations.yml"
    )
    t = TemplatedNaturalLanguageGenerator(responses=domain.responses)

    slot = CategoricalSlot(
        name="account_type",
        mappings=[{}],
        initial_value="primary",
        influence_conversation=False,
    )
    tracker = DialogueStateTracker(sender_id="conversation_id", slots=[slot])

    r = await t.generate(
        utter_action="utter_check_balance", tracker=tracker, output_channel="os"
    )
    assert (
        r.get("text") == "As a primary account holder, you can now set-up "
        "your access on mobile app too."
    )

    resp = await t.generate(
        utter_action="utter_check_balance", tracker=tracker, output_channel="app"
    )
    assert resp.get("text") == "Welcome to your app account overview."
Example #7
0
async def test_nlg_conditional_response_variations_with_no_slots():
    responses = {
        "utter_test": [
            {
                "text": "Conditional OS Response A",
                "condition": [{"type": "slot", "name": "slot test", "value": "A"}],
                "channel": "os",
            },
            {
                "text": "Conditional Response A",
                "condition": [{"type": "slot", "name": "slot test", "value": "A"}],
            },
            {
                "text": "Conditional Response B",
                "condition": [{"type": "slot", "name": "slot test", "value": "B"}],
            },
            {"text": "Default response"},
        ]
    }
    t = TemplatedNaturalLanguageGenerator(responses=responses)
    no_slots_tracker = DialogueStateTracker(sender_id="nlg_test_default", slots=None)
    default_response = await t.generate(
        utter_action="utter_test", tracker=no_slots_tracker, output_channel=""
    )

    assert default_response.get("text") == "Default response"
Example #8
0
async def test_nlg_when_multiple_conditions_satisfied():
    responses = {
        "utter_action": [
            {
                "text": "example A",
                "condition": [{"type": "slot", "name": "test", "value": "A"}],
            },
            {
                "text": "example B",
                "condition": [{"type": "slot", "name": "test_another", "value": "B"}],
            },
            {
                "text": "non matching example 1",
                "condition": [
                    {"type": "slot", "name": "test_third_slot", "value": "C"}
                ],
            },
            {
                "text": "non matching example 2",
                "condition": [{"type": "slot", "name": "test", "value": "D"}],
            },
        ]
    }

    t = TemplatedNaturalLanguageGenerator(responses=responses)
    slot_a = TextSlot(name="test", initial_value="A", influence_conversation=False)
    slot_b = TextSlot(
        name="test_another", initial_value="B", influence_conversation=False
    )
    tracker = DialogueStateTracker(sender_id="test_nlg", slots=[slot_a, slot_b])
    resp = await t.generate(
        utter_action="utter_action", tracker=tracker, output_channel=""
    )
    assert resp.get("text") in ["example A", "example B"]
Example #9
0
async def test_nlg_conditional_response_variations_with_diff_slot_types(
    slot_name: Text, slot_value: Any, message: Text
):
    responses = {
        "utter_action": [
            {
                "text": "example boolean",
                "condition": [{"type": "slot", "name": "test_bool", "value": True}],
            },
            {
                "text": "example integer",
                "condition": [{"type": "slot", "name": "test_int", "value": 12}],
            },
            {
                "text": "example list",
                "condition": [{"type": "slot", "name": "test_list", "value": []}],
            },
        ]
    }
    t = TemplatedNaturalLanguageGenerator(responses=responses)
    slot = AnySlot(
        name=slot_name, initial_value=slot_value, influence_conversation=False
    )
    tracker = DialogueStateTracker(sender_id="nlg_tracker", slots=[slot])

    r = await t.generate(
        utter_action="utter_action", tracker=tracker, output_channel=""
    )
    assert r.get("text") == message
Example #10
0
async def test_nlg_conditional_response_variations_with_interpolated_slots(
        slot_name: Text, slot_value: Any, response_variation: Text):
    responses = {
        "utter_action": [
            {
                "text": "example one {test}",
                "condition": [{
                    "type": "slot",
                    "name": "test",
                    "value": "A"
                }],
            },
            {
                "text": "example two {test}",
                "condition": [{
                    "type": "slot",
                    "name": "test",
                    "value": "B"
                }],
            },
        ]
    }
    t = TemplatedNaturalLanguageGenerator(responses=responses)
    slot = TextSlot(
        name=slot_name,
        mappings=[{}],
        initial_value=slot_value,
        influence_conversation=False,
    )
    tracker = DialogueStateTracker(sender_id="nlg_interpolated", slots=[slot])

    r = await t.generate(utter_action="utter_action",
                         tracker=tracker,
                         output_channel="")
    assert r.get("text") == response_variation
Example #11
0
def template_nlg() -> TemplatedNaturalLanguageGenerator:
    responses = {
        "utter_ask_rephrase": [{
            "text": "can you rephrase that?"
        }],
        "utter_restart": [{
            "text": "congrats, you've restarted me!"
        }],
        "utter_back": [{
            "text": "backing up..."
        }],
        "utter_invalid": [{
            "text":
            "a response referencing an invalid {variable}."
        }],
        "utter_buttons": [{
            "text":
            "button message",
            "buttons": [
                {
                    "payload": "button1",
                    "title": "button1"
                },
                {
                    "payload": "button2",
                    "title": "button2"
                },
            ],
        }],
    }
    return TemplatedNaturalLanguageGenerator(responses)
Example #12
0
async def test_nlg_conditional_response_variations_with_yaml_multi_constraints():
    domain = Domain.from_file(
        path="data/test_domains/conditional_response_variations.yml"
    )
    t = TemplatedNaturalLanguageGenerator(responses=domain.responses)

    first_slot = CategoricalSlot(
        name="account_type",
        mappings=[{}],
        initial_value="primary",
        influence_conversation=False,
    )
    second_slot = BooleanSlot(
        name="can_withdraw",
        mappings=[{}],
        initial_value=True,
        influence_conversation=False,
    )
    tracker = DialogueStateTracker(
        sender_id="conversation_id", slots=[first_slot, second_slot]
    )
    r = await t.generate(
        utter_action="utter_withdraw", tracker=tracker, output_channel=""
    )
    assert r.get("text") == "Withdrawal has been approved."
Example #13
0
def test_nlg_fill_response_button(button_slot_name, button_slot_value):
    response = {
        "buttons": [{
            "payload": f'/choose{{{{"some_slot": "{{{button_slot_name}}}"}}}}',
            "title": f"{{{button_slot_name}}}",
        }]
    }
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(
        response=response, filled_slots={button_slot_name: button_slot_value})
    assert result == {
        "buttons": [{
            "payload": f'/choose{{"some_slot": "{button_slot_value}"}}',
            "title": f"{button_slot_value}",
        }]
    }
Example #14
0
def test_nlg_fill_response_image_and_text(text_slot_name, text_slot_value,
                                          img_slot_name, img_slot_value):
    response = {
        "text": f"{{{text_slot_name}}}",
        "image": f"{{{img_slot_name}}}"
    }
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(
        response=response,
        filled_slots={
            text_slot_name: text_slot_value,
            img_slot_name: img_slot_value
        },
    )
    assert result == {
        "text": str(text_slot_value),
        "image": str(img_slot_value)
    }
Example #15
0
async def test_nlg_non_matching_channel():
    domain = Domain.from_yaml("""
    version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}"
    responses:
        utter_hi:
        - text: "Hello"
        - text: "Hello Slack"
          channel: "slack"
    """)
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    tracker = DialogueStateTracker(sender_id="test", slots=[])
    r = await t.generate("utter_hi", tracker, "signal")
    assert r.get("text") == "Hello"
Example #16
0
def test_nlg_fill_response_custom_with_list():
    response = {
        "custom": {
            "blocks": [{
                "fields": [{
                    "text": "*Departure date:*\n{test}"
                }]
            }],
            "other": ["{test}"],
        }
    }
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response=response, filled_slots={"test": 5})
    assert result == {
        "custom": {
            "blocks": [{
                "fields": [{
                    "text": "*Departure date:*\n5"
                }]
            }],
            "other": ["5"],
        }
    }
Example #17
0
async def test_remote_action_with_template_param(
    default_channel: OutputChannel,
    default_tracker: DialogueStateTracker,
    domain: Domain,
):
    endpoint = EndpointConfig("https://example.com/webhooks/actions")
    remote_action = action.RemoteAction("my_action", endpoint)

    response = {
        "events": [
            {
                "event": "form",
                "name": "restaurant_form",
                "timestamp": None
            },
            {
                "event": "slot",
                "timestamp": None,
                "name": "requested_slot",
                "value": "cuisine",
            },
        ],
        "responses": [{
            "text": None,
            "buttons": [],
            "elements": [],
            "custom": {},
            "template": "utter_ask_cuisine",
            "image": None,
            "attachment": None,
        }],
    }

    nlg = TemplatedNaturalLanguageGenerator(
        {"utter_ask_cuisine": [{
            "text": "what dou want to eat?"
        }]})
    with aioresponses() as mocked:
        mocked.post("https://example.com/webhooks/actions", payload=response)

        with pytest.warns(FutureWarning):
            events = await remote_action.run(default_channel, nlg,
                                             default_tracker, domain)

    assert events == [
        BotUttered("what dou want to eat?",
                   metadata={"utter_action": "utter_ask_cuisine"}),
        ActiveLoop("restaurant_form"),
        SlotSet("requested_slot", "cuisine"),
    ]
Example #18
0
async def test_nlg_conditional_response_variations_with_yaml_single_condition(
        slot_name: Text, slot_value: Any, bot_message: Text):
    domain = Domain.from_file(
        path="data/test_domains/conditional_response_variations.yml")
    t = TemplatedNaturalLanguageGenerator(responses=domain.responses)

    slot = AnySlot(name=slot_name,
                   initial_value=slot_value,
                   influence_conversation=False)
    tracker = DialogueStateTracker(sender_id="conversation_id", slots=[slot])

    r = await t.generate(utter_action="utter_withdraw",
                         tracker=tracker,
                         output_channel="")
    assert r.get("text") == bot_message
Example #19
0
async def test_nlg_conditional_response_variations_channel_no_condition_met():
    domain = Domain.from_yaml(f"""
        version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}"
        responses:
           utter_action:
             - text: "example with channel"
               condition:
                - type: slot
                  name: test
                  value: A
               channel: os
             - text: "default"
        """)
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    tracker = DialogueStateTracker(sender_id="test", slots=[])
    r = await t.generate("utter_action", tracker, "os")
    assert r.get("text") == "default"
Example #20
0
async def test_nlg_conditional_response_variations_with_slot_not_a_constraint():
    domain = Domain.from_yaml(
        """
            version: "2.0"
            responses:
                utter_action:
                - text: "text A"
                  condition:
                  - type: slot
                    name: account
                    value: "A"
            """
    )
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    slot = TextSlot(name="account", initial_value="B", influence_conversation=False)
    tracker = DialogueStateTracker(sender_id="test", slots=[slot])
    r = await t.generate("utter_action", tracker, "")
    assert r is None
Example #21
0
async def test_nlg_conditional_response_variations_with_none_slot():
    domain = Domain.from_yaml(f"""
        version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}"
        responses:
            utter_action:
            - text: "text A"
              condition:
              - type: slot
                name: account
                value: "A"
        """)
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    slot = AnySlot(name="account",
                   mappings=[{}],
                   initial_value=None,
                   influence_conversation=False)
    tracker = DialogueStateTracker(sender_id="test", slots=[slot])
    r = await t.generate("utter_action", tracker, "")
    assert r is None
Example #22
0
async def test_nlg_conditional_response_variations_condition_logging(
    caplog: LogCaptureFixture,
):
    domain = Domain.from_yaml(
        """
        version: "3.0"
        responses:
           utter_action:
             - text: "example"
               condition:
                - type: slot
                  name: test_A
                  value: A
                - type: slot
                  name: test_B
                  value: B
             - text: "default"
        """
    )
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    slot_A = TextSlot(
        name="test_A", mappings=[{}], initial_value="A", influence_conversation=False
    )
    slot_B = TextSlot(
        name="test_B", mappings=[{}], initial_value="B", influence_conversation=False
    )
    tracker = DialogueStateTracker(sender_id="test", slots=[slot_A, slot_B])

    with caplog.at_level(logging.DEBUG):
        await t.generate("utter_action", tracker=tracker, output_channel="")

    assert any(
        "Selecting response variation with conditions:" in message
        for message in caplog.messages
    )
    assert any(
        "[condition 1] type: slot | name: test_A | value: A" in message
        for message in caplog.messages
    )
    assert any(
        "[condition 2] type: slot | name: test_B | value: B" in message
        for message in caplog.messages
    )
Example #23
0
async def test_nlg_conditional_response_variation_condition_met_channel_mismatch(
):
    domain = Domain.from_yaml("""
        version: "2.0"
        responses:
           utter_action:
             - text: "example with channel"
               condition:
                - type: slot
                  name: test
                  value: A
               channel: os
             - text: "app default"
               channel: app
        """)
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    slot = TextSlot("test", "A", influence_conversation=False)
    tracker = DialogueStateTracker(sender_id="test", slots=[slot])
    r = await t.generate("utter_action", tracker, "app")
    assert r.get("text") == "app default"
Example #24
0
async def test_nlg_conditional_edgecases(slots, channel, expected_response):
    domain = Domain.from_yaml(
        """
        version: "2.0"
        responses:
           utter_action:
             - text: "condition example A with channel"
               condition:
                - type: slot
                  name: test
                  value: A
               channel: app

             - text: "condition example C with channel"
               condition:
                - type: slot
                  name: test
                  value: C
               channel: app

             - text: "condition example A no channel"
               condition:
                - type: slot
                  name: test
                  value: A

             - text: "condition example B no channel"
               condition:
                - type: slot
                  name: test
                  value: B

             - text: "default"
        """
    )
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    tracker = DialogueStateTracker(sender_id="test", slots=slots)
    r = await t.generate("utter_action", tracker, channel)
    assert r.get("text") == expected_response
Example #25
0
async def test_nlg_conditional_response_variations_with_null_slot():
    domain = Domain.from_yaml(
        """
                version: "2.0"
                responses:
                    utter_action:
                    - text: "text for null"
                      condition:
                      - type: slot
                        name: account
                        value: null
                """
    )
    t = TemplatedNaturalLanguageGenerator(domain.responses)
    slot = AnySlot(name="account", initial_value=None, influence_conversation=False)
    tracker = DialogueStateTracker(sender_id="test", slots=[slot])
    r = await t.generate("utter_action", tracker, "")
    assert r.get("text") == "text for null"

    tracker_no_slots = DialogueStateTracker(sender_id="new_test", slots=[])
    r = await t.generate("utter_action", tracker_no_slots, "")
    assert r.get("text") == "text for null"
Example #26
0
def test_nlg_fill_response_text(slot_name: Text, slot_value: Any):
    response = {"text": f"{{{slot_name}}}"}
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response=response,
                              filled_slots={slot_name: slot_value})
    assert result == {"text": str(slot_value)}
Example #27
0
def test_nlg_fill_response_image(img_slot_name: Text, img_slot_value: Text):
    response = {"image": f"{{{img_slot_name}}}"}
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response=response,
                              filled_slots={img_slot_name: img_slot_value})
    assert result == {"image": str(img_slot_value)}
Example #28
0
def test_nlg_fill_response_with_bad_slot_name(slot_name, slot_value):
    response_text = f"{{{slot_name}}}"
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(response={"text": response_text},
                              filled_slots={slot_name: slot_value})
    assert result["text"] == response_text
Example #29
0
def test_nlg_fill_response_attachment(attach_slot_name, attach_slot_value):
    response = {"attachment": "{" + attach_slot_name + "}"}
    t = TemplatedNaturalLanguageGenerator(responses=dict())
    result = t._fill_response(
        response=response, filled_slots={attach_slot_name: attach_slot_value})
    assert result == {"attachment": str(attach_slot_value)}