Ejemplo n.º 1
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"]
Ejemplo n.º 2
0
 def base_slots(self) -> List[Slot]:
     return [
         ListSlot(name=find_objects_action.SLOT_FOUND_OBJECT_NAMES, ),
         TextSlot(name=find_objects_action.SLOT_OBJECT_NAME_OR_TYPE),
         TextSlot(name=get_object_info.SLOT_OBJECT_ATTRIBUTE),
         FloatSlot(name="number",
                   max_value=100,
                   influence_conversation=False),
     ]
Ejemplo n.º 3
0
def test_container_derive_messages_from_domain_and_add():
    action_names = ["a", "b"]
    # action texts, response keys, forms, and action_names must be unique or the
    # domain will complain about it ...
    action_texts = ["a2", "b2"]
    # ... but the response texts could overlap with e.g action texts
    responses = {"a3": {TEXT: "a2"}, "b3": {TEXT: "b2"}}
    forms = {"a4": "a4"}
    # however, intent names can be anything
    intents = ["a", "b"]
    domain = Domain(
        intents=intents,
        action_names=action_names,
        action_texts=action_texts,
        responses=responses,
        entities=["e_a", "e_b", "e_c"],
        slots=[TextSlot(name="s", mappings=[{}])],
        forms=forms,
        data={},
    )
    lookup_table = MessageContainerForCoreFeaturization()
    lookup_table.derive_messages_from_domain_and_add(domain)
    assert len(lookup_table) == (
        len(domain.intent_properties) + len(domain.action_names_or_texts)
    )
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def test_unfeaturized_slot_in_domain_warnings():
    # create empty domain
    domain = Domain.empty()

    # add one unfeaturized and one text slot
    unfeaturized_slot = TextSlot(
        "unfeaturized_slot", "value1", influence_conversation=False
    )
    text_slot = TextSlot("text_slot", "value2")
    domain.slots.extend([unfeaturized_slot, text_slot])

    # ensure both are in domain
    assert all(slot in domain.slots for slot in (unfeaturized_slot, text_slot))

    # text slot should appear in domain warnings, unfeaturized slot should not
    in_domain_slot_warnings = domain.domain_warnings()["slot_warnings"]["in_domain"]
    assert text_slot.name in in_domain_slot_warnings
    assert unfeaturized_slot.name not in in_domain_slot_warnings
Ejemplo n.º 6
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
    )
Ejemplo n.º 7
0
def test_check_domain_sanity_on_invalid_domain():
    with pytest.raises(InvalidDomain):
        Domain(
            intents={},
            entities=[],
            slots=[],
            templates={},
            action_names=["random_name", "random_name"],
            forms=[],
        )

    with pytest.raises(InvalidDomain):
        Domain(
            intents={},
            entities=[],
            slots=[TextSlot("random_name"),
                   TextSlot("random_name")],
            templates={},
            action_names=[],
            forms=[],
        )

    with pytest.raises(InvalidDomain):
        Domain(
            intents={},
            entities=[
                "random_name", "random_name", "other_name", "other_name"
            ],
            slots=[],
            templates={},
            action_names=[],
            forms=[],
        )

    with pytest.raises(InvalidDomain):
        Domain(
            intents={},
            entities=[],
            slots=[],
            templates={},
            action_names=[],
            forms=["random_name", "random_name"],
        )
Ejemplo n.º 8
0
    def add_requested_slot(self) -> None:
        """Add a slot called `requested_slot` to the list of slots.

        The value of this slot will hold the name of the slot which the user
        needs to fill in next (either explicitly or implicitly) as part of a form.
        """
        if self.form_names and rasa.shared.core.constants.REQUESTED_SLOT not in [
                s.name for s in self.slots
        ]:
            self.slots.append(
                TextSlot(
                    rasa.shared.core.constants.REQUESTED_SLOT,
                    influence_conversation=False,
                ))
Ejemplo n.º 9
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
Ejemplo n.º 10
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"
def test_prepare_for_training():
    domain = Domain(
        intents=["greet"],
        entities=["name"],
        slots=[TextSlot("name", mappings=[{}])],
        responses={},
        forms={},
        action_names=["utter_greet", "action_check_weather"],
        data={},
    )

    f = SingleStateFeaturizer()
    f.prepare_for_training(domain)

    assert len(f._default_feature_states[INTENT]) > 1
    assert "greet" in f._default_feature_states[INTENT]
    assert len(f._default_feature_states[ENTITIES]) == 1
    assert f._default_feature_states[ENTITIES]["name"] == 0
    assert len(f._default_feature_states[SLOTS]) == 1
    assert f._default_feature_states[SLOTS]["name_0"] == 0
    assert len(f._default_feature_states[ACTION_NAME]) > 2
    assert "utter_greet" in f._default_feature_states[ACTION_NAME]
    assert "action_check_weather" in f._default_feature_states[ACTION_NAME]
    assert len(f._default_feature_states[ACTIVE_LOOP]) == 0
Ejemplo n.º 12
0
    def add_knowledge_base_slots(self) -> None:
        """
        Add slots for the knowledge base action to the list of slots, if the
        default knowledge base action name is present.

        As soon as the knowledge base action is not experimental anymore, we should
        consider creating a new section in the domain file dedicated to knowledge
        base slots.
        """
        if (rasa.shared.core.constants.DEFAULT_KNOWLEDGE_BASE_ACTION
                in self.action_names):
            logger.warning(
                "You are using an experiential feature: Action '{}'!".format(
                    rasa.shared.core.constants.DEFAULT_KNOWLEDGE_BASE_ACTION))
            slot_names = [s.name for s in self.slots]
            knowledge_base_slots = [
                rasa.shared.core.constants.SLOT_LISTED_ITEMS,
                rasa.shared.core.constants.SLOT_LAST_OBJECT,
                rasa.shared.core.constants.SLOT_LAST_OBJECT_TYPE,
            ]
            for s in knowledge_base_slots:
                if s not in slot_names:
                    self.slots.append(TextSlot(s,
                                               influence_conversation=False))
Ejemplo n.º 13
0
def test_domain_validation_with_valid_marker(depth: int, max_branches: int,
                                             seed: int):
    # We do this a bit backwards, we construct the domain from the marker
    # and assert they must match
    rng = np.random.default_rng(seed=seed)
    marker, expected_size = generate_random_marker(
        depth=depth,
        max_branches=max_branches,
        rng=rng,
        possible_conditions=CONDITION_MARKERS,
        possible_operators=OPERATOR_MARKERS,
        constant_condition_text=None,
        constant_negated=None,
    )

    slots = [
        TextSlot(name, [])
        for name in _collect_parameters(marker, SlotSetMarker)
    ]
    actions = list(_collect_parameters(marker, ActionExecutedMarker))
    intents = _collect_parameters(marker, IntentDetectedMarker)
    domain = Domain(intents, [], slots, {}, actions, {}, {})

    assert marker.validate_against_domain(domain)
Ejemplo n.º 14
0
    ) for response in util.get_input_responses()
]

# stories = [
#     # set_question_id_story,
#     Story(
#         [
#             IntentWithExamples(
#                 examples=[
#                     "New York",
#                     "I live in New York",
#                     "New York City",
#                     "My house is in New York",
#                 ],
#                 name="new_york_living",
#             ),
#             Utterance(text="Correct! LIVING", name="utter_correct"),
#         ]
#     ),
# ]

chatbot = Chatbot(
    state_machine=None,
    stories=stories,
    objects=[],
    additional_intents=[],
    additional_slots=[
        TextSlot(name="question_id"),
    ],
)
Ejemplo n.º 15
0
 def create_slot(self, mappings: List[Dict[Text, Any]],
                 influence_conversation: bool) -> Slot:
     return TextSlot("test",
                     mappings=mappings,
                     influence_conversation=influence_conversation)
Ejemplo n.º 16
0
             - 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"


@pytest.mark.parametrize(
    "slots,channel,expected_response",
    [
        (
            [
                TextSlot("test", "B", influence_conversation=False),
            ],
            "app",
            "condition example B no channel",
        ),
        ([
            TextSlot("test", "C", influence_conversation=False),
        ], "", "default"),
        ([
            TextSlot("test", "D", influence_conversation=False),
        ], "app", "default"),
    ],
)
async def test_nlg_conditional_edgecases(slots, channel, expected_response):
    domain = Domain.from_yaml("""
        version: "2.0"
Ejemplo n.º 17
0
                    mappings=[{}],
                    initial_value="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"


@pytest.mark.parametrize(
    "slots,channel,expected_response",
    [
        (
            [
                TextSlot(
                    "test",
                    mappings=[{}],
                    initial_value="B",
                    influence_conversation=False,
                )
            ],
            "app",
            "condition example B no channel",
        ),
        (
            [
                TextSlot(
                    "test",
                    mappings=[{}],
                    initial_value="C",
                    influence_conversation=False,
                )
            ],
Ejemplo n.º 18
0
 def create_slot(self, influence_conversation: bool) -> Slot:
     return TextSlot("test", influence_conversation=influence_conversation)
Ejemplo n.º 19
0
             - 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"


@pytest.mark.parametrize(
    "slots,channel,expected_response",
    [
        (
            [TextSlot("test", "B", influence_conversation=False),],
            "app",
            "condition example B no channel",
        ),
        ([TextSlot("test", "C", influence_conversation=False),], "", "default"),
        ([TextSlot("test", "D", influence_conversation=False),], "app", "default"),
    ],
)
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:
Ejemplo n.º 20
0
 def create_slot(self):
     return TextSlot("test")