Пример #1
0
    def from_entity(
        self,
        entity: Text,
        intent: Optional[Union[Text, List[Text]]] = None,
        not_intent: Optional[Union[Text, List[Text]]] = None,
        role: Optional[Text] = None,
        group: Optional[Text] = None,
    ) -> Dict[Text, Any]:
        """A dictionary for slot mapping to extract slot value.

        From:
        - an extracted entity
        - conditioned on
            - intent if it is not None
            - not_intent if it is not None,
                meaning user intent should not be this intent
            - role if it is not None
            - group if it is not None
        """
        intent, not_intent = (
            SlotMapping.to_list(intent),
            SlotMapping.to_list(not_intent),
        )

        return {
            "type": str(SlotMappingType.FROM_ENTITY),
            "entity": entity,
            "intent": intent,
            "not_intent": not_intent,
            "role": role,
            "group": group,
        }
Пример #2
0
def test_slot_mapping_intent_is_desired(domain: Domain):
    domain = Domain.from_file("examples/formbot/domain.yml")
    tracker = DialogueStateTracker("sender_id_test", slots=domain.slots)
    event1 = UserUttered(
        text="I'd like to book a restaurant for 2 people.",
        intent={
            "name": "request_restaurant",
            "confidence": 0.9604260921478271
        },
        entities=[{
            "entity": "number",
            "value": 2
        }],
    )
    tracker.update(event1, domain)
    mappings_for_num_people = (
        domain.as_dict().get("slots").get("num_people").get("mappings"))
    assert SlotMapping.intent_is_desired(mappings_for_num_people[0], tracker,
                                         domain)

    event2 = UserUttered(
        text="Yes, 2 please",
        intent={
            "name": "affirm",
            "confidence": 0.9604260921478271
        },
        entities=[{
            "entity": "number",
            "value": 2
        }],
    )
    tracker.update(event2, domain)
    assert (SlotMapping.intent_is_desired(mappings_for_num_people[0], tracker,
                                          domain) is False)

    event3 = UserUttered(
        text="Yes, please",
        intent={
            "name": "affirm",
            "confidence": 0.9604260921478271
        },
        entities=[],
    )
    tracker.update(event3, domain)
    mappings_for_preferences = (
        domain.as_dict().get("slots").get("preferences").get("mappings"))
    assert (SlotMapping.intent_is_desired(mappings_for_preferences[0], tracker,
                                          domain) is False)
Пример #3
0
def test_slot_mappings_ignored_intents_during_active_loop():
    domain = Domain.from_yaml("""
    version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}"
    intents:
    - greet
    - chitchat
    slots:
      cuisine:
        type: text
        mappings:
        - type: from_text
          conditions:
          - active_loop: restaurant_form
    forms:
      restaurant_form:
        ignored_intents:
        - chitchat
        required_slots:
        - cuisine
    """)
    tracker = DialogueStateTracker("sender_id", slots=domain.slots)
    event1 = ActiveLoop("restaurant_form")
    event2 = UserUttered(
        text="The weather is sunny today",
        intent={
            "name": "chitchat",
            "confidence": 0.9604260921478271
        },
        entities=[],
    )
    tracker.update_with_events([event1, event2], domain)
    mappings_for_cuisine = domain.as_dict().get("slots").get("cuisine").get(
        "mappings")
    assert (SlotMapping.intent_is_desired(mappings_for_cuisine[0], tracker,
                                          domain) is False)
Пример #4
0
def test_slot_mapping_entity_is_desired(slot_name: Text, expected: bool):
    domain = Domain.from_file("data/test_domains/travel_form.yml")
    tracker = DialogueStateTracker("test_id", slots=domain.slots)
    event = UserUttered(
        text="I'm travelling to Vancouver.",
        intent={"name": "inform", "confidence": 0.9604260921478271},
        entities=[{"entity": "GPE", "value": "Vancouver", "role": "destination"}],
    )
    tracker.update(event, domain)
    slot_mappings = domain.as_dict().get("slots").get(slot_name).get("mappings")
    assert SlotMapping.entity_is_desired(slot_mappings[0], tracker) is expected
Пример #5
0
def extract_slot_value_from_predefined_mapping(
    mapping_type: SlotMappingType,
    mapping: Dict[Text, Any],
    tracker: "DialogueStateTracker",
) -> List[Any]:
    """Extracts slot value if slot has an applicable predefined mapping."""
    should_fill_entity_slot = (mapping_type == SlotMappingType.FROM_ENTITY
                               and SlotMapping.entity_is_desired(
                                   mapping, tracker))

    should_fill_intent_slot = mapping_type == SlotMappingType.FROM_INTENT

    should_fill_text_slot = mapping_type == SlotMappingType.FROM_TEXT

    active_loops_in_mapping_conditions = [
        active_loop.get(ACTIVE_LOOP)
        for active_loop in mapping.get(MAPPING_CONDITIONS, [])
    ]
    should_fill_trigger_slot = (
        mapping_type == SlotMappingType.FROM_TRIGGER_INTENT
        and tracker.active_loop_name not in active_loops_in_mapping_conditions)

    value: List[Any] = []
    if should_fill_entity_slot:
        value = list(
            tracker.get_latest_entity_values(
                mapping.get(ENTITY_ATTRIBUTE_TYPE),
                mapping.get(ENTITY_ATTRIBUTE_ROLE),
                mapping.get(ENTITY_ATTRIBUTE_GROUP),
            ))
    elif should_fill_intent_slot or should_fill_trigger_slot:
        value = [mapping.get("value")]
    elif should_fill_text_slot:
        value = [
            tracker.latest_message.text
            if tracker.latest_message is not None else None
        ]

    return value
Пример #6
0
    async def run(
        self,
        output_channel: "OutputChannel",
        nlg: "NaturalLanguageGenerator",
        tracker: "DialogueStateTracker",
        domain: "Domain",
    ) -> List[Event]:
        """Runs action. Please see parent class for the full docstring."""
        slot_events: List[Event] = []
        executed_custom_actions: Set[Text] = set()

        user_slots = [
            slot for slot in domain.slots
            if slot.name not in DEFAULT_SLOT_NAMES
        ]

        for slot in user_slots:
            for mapping in slot.mappings:
                mapping_type = SlotMappingType(mapping.get(MAPPING_TYPE))

                if not SlotMapping.check_mapping_validity(
                        slot_name=slot.name,
                        mapping_type=mapping_type,
                        mapping=mapping,
                        domain=domain,
                ):
                    continue

                intent_is_desired = SlotMapping.intent_is_desired(
                    mapping, tracker, domain)

                if not intent_is_desired:
                    continue

                if not ActionExtractSlots._verify_mapping_conditions(
                        mapping, tracker, slot.name):
                    continue

                if self._fails_unique_entity_mapping_check(
                        slot.name, mapping, tracker, domain):
                    continue

                if mapping_type.is_predefined_type():
                    value = extract_slot_value_from_predefined_mapping(
                        mapping_type, mapping, tracker)
                else:
                    value = None

                if value:
                    if not isinstance(slot, ListSlot):
                        value = value[-1]

                    if tracker.get_slot(slot.name) != value:
                        slot_events.append(SlotSet(slot.name, value))

                should_fill_custom_slot = mapping_type == SlotMappingType.CUSTOM

                if should_fill_custom_slot:
                    (
                        custom_evts,
                        executed_custom_actions,
                    ) = await self._execute_custom_action(
                        mapping,
                        executed_custom_actions,
                        output_channel,
                        nlg,
                        tracker,
                        domain,
                    )
                    slot_events.extend(custom_evts)

        validated_events = await self._execute_validation_action(
            slot_events, output_channel, nlg, tracker, domain)

        return validated_events