Пример #1
0
def test_get_actions_for_valid_num_actions(agenda, constraintA, constraintB):
    """
    Tests whether retrieving actions from the stack with a number of actions is smaller or equal
    to the stack size will return the last num_actions items from the stack in reversed order.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value']),
        UserAct(act_type=UserActionType.Request,
                slot=constraintA['slot'],
                value=constraintA['value'])
    ]
    agenda.stack = stack.copy()
    num_actions = 2
    res = agenda.get_actions(num_actions=num_actions)
    assert len(res) == num_actions
    assert res == stack[-1:(len(stack) - (num_actions + 1)):-1]
Пример #2
0
def test_reset_informs_resets_only_informs(bst):
    """
    Tests whether reset informs removes only inform slots.

    Args:
        bst: BST Object (given in conftest.py)
    """
    acts = [
        UserAct(act_type=UserActionType.Inform, slot='foo', value='bar'),
        UserAct(act_type=UserActionType.Request, slot='bar', value='foo')
    ]
    bst.bs['informs'] = {
        'foo': {
            'bar': 0.5
        },
        'bar': {
            'foo': 0.3
        },
        'baz': {
            'foo': 0.6
        }
    }
    bst._reset_informs(acts)
    assert all(act.slot not in bst.bs['informs'] for act in acts
               if act.type == UserActionType.Inform)
    assert 'bar' in bst.bs['informs']
Пример #3
0
def test_get_actions_for_invalid_num_actions(agenda, constraintA, constraintB,
                                             num_actions):
    """
    Tests whether retrieving actions from the stack with a number of actions that is less or
    greater than the stack size will return the complete stack in reversed order.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        num_actions (int): number of actions to be selected
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    res = agenda.get_actions(num_actions=num_actions)
    assert len(res) == len(stack)
    assert res == stack[::-1]
Пример #4
0
def test_remove_fulfilled_requests_on_clean(agenda, goal, constraintA,
                                            constraintB):
    """
    Tests whether cleaning the stack removes requests that are already fulfilled in the goal.

    Args:
        agenda: Agenda object (given in conftest.py)
        goal: Goal object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    fulfilled_request = UserAct(act_type=UserActionType.Request,
                                slot=constraintA['slot'],
                                value=constraintA['value'])
    stack = [
        fulfilled_request,
        UserAct(act_type=UserActionType.Inform,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    goal.requests = {fulfilled_request.slot: fulfilled_request.value}
    agenda.clean(goal)
    assert len(agenda.stack) < len(stack)
    assert fulfilled_request not in agenda.stack
Пример #5
0
def test_keep_order_in_stack_on_clean(agenda, goal, constraintA, constraintB):
    """
    Tests whether cleaning the stack keeps the items in the same order.

    Args:
        agenda: Agenda object (given in conftest.py)
        goal: Goal object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    goal.requests = {constraintA['slot']: None}
    agenda.clean(goal)
    assert len(agenda.stack) == len(stack)
    assert agenda.stack == stack
Пример #6
0
    def _receive_select(self, sys_act: SysAct):
        """Processes a select action from the system."""
        # handle as request
        value_in_goal = False
        for slot, values in sys_act.slot_values.items():
            for value in values:
                # do not consider 'dontcare' as any value
                if not self.goal.is_inconsistent_constraint_strict(
                        Constraint(slot, value)):
                    value_in_goal = True

        if value_in_goal:
            self._receive_request(sys_act)
        else:
            assert len(sys_act.slot_values.keys()) == 1,\
                "There shall be only one slot in a select action."
            slot = list(sys_act.slot_values.keys())[0]
            # inform about correct value with some probability
            if common.random.random(
            ) < self.parameters['usermodel']['InformOnSelect']:
                self.agenda.push(UserAct(act_type=UserActionType.Inform, slot=slot,\
                    value=self.goal.get_constraint(slot), score=1.0))

            for slot, values in sys_act.slot_values.items():
                for value in values:
                    self.agenda.push(UserAct(act_type=UserActionType.NegativeInform, slot=slot,\
                        value=value, score=1.0))
Пример #7
0
def test_remove_inconsistencies_on_clean(agenda, goal, constraintA,
                                         constraintB, constraintA_alt):
    """
    Tests whether cleaning the stack removes inconsistent inform constraints.

    Args:
        agenda: Agenda object (given in conftest.py)
        goal: Goal object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintA_alt (dict): as constraint A, but with an alternative value (given in
        conftest_<domain>.py)
    """
    inconsistent_item = UserAct(act_type=UserActionType.Inform,
                                slot=constraintA['slot'],
                                value=constraintA['value'])
    stack = [
        inconsistent_item,
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    goal.constraints = [
        Constraint(constraintA_alt['slot'], constraintA_alt['value'])
    ]
    agenda.clean(goal)
    assert len(agenda.stack) < len(stack)
    assert all(item.slot != inconsistent_item.slot
               and item.value != inconsistent_item.value
               for item in agenda.stack)
Пример #8
0
def test_get_actions_of_type_with_matching_action_without_considering_dontcare(
        agenda, constraintA, constraintB):
    """
    Tests whether asking to get an action of specific type returns no matching actions in the
    stack that have the value 'dontcare' if specified.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    act_type = UserActionType.Inform
    stack = [
        UserAct(act_type=act_type, slot=constraintA['slot'], value='dontcare'),
        UserAct(act_type=act_type,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    res = agenda.get_actions_of_type(act_type=act_type,
                                     consider_dontcare=False)
    res = list(res)
    assert len(res) < len(stack)
    assert res == [
        act for act in stack
        if act.type == act_type and act.value != 'dontcare'
    ]
Пример #9
0
def test_get_actions_of_type_without_matching_action(agenda, constraintA,
                                                     constraintB):
    """
    Tests whether asking to get an action of specific type returns nothing if there are no matching
    actions in  the stack.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    res = agenda.get_actions_of_type(act_type=UserActionType.Request,
                                     consider_dontcare=True)
    assert list(res) == []
Пример #10
0
def test_remove_actions_of_type_with_matching_action(agenda, constraintA,
                                                     constraintB):
    """
    Tests whether removing actions of a specific type will delete these actions if present in the stack.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    act_type = UserActionType.Inform
    stack = [
        UserAct(act_type=act_type,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    agenda.remove_actions_of_type(act_type=act_type)
    assert len(agenda.stack) < len(stack)
    assert all(item.type != act_type for item in agenda.stack)
Пример #11
0
def test_remove_actions_of_type_without_matching_action(
        agenda, constraintA, constraintB):
    """
    Tests whether removing actions of a specific type will not change the stack if no matching
    actions are in it.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    agenda.remove_actions_of_type(act_type=UserActionType.Request)
    assert len(agenda.stack) == len(stack)
    assert agenda.stack == stack
Пример #12
0
def test_remove_actions_with_value(agenda, constraintA, constraintB):
    """
    Tests whether removing specific actions with stating their type, slot and value removes all
    matching actions from the stack.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    act_type = UserActionType.Inform
    slot = constraintA['slot']
    value = constraintA['value']
    stack = [
        UserAct(act_type=act_type, slot=slot, value=value),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    agenda.remove_actions(act_type=act_type, slot=slot, value=value)
    assert len(agenda.stack) < len(stack)
    assert all(
        item.type != act_type and item.slot != slot and item.value != value
        for item in agenda.stack)
Пример #13
0
 def _receive_confirm(self, sys_act: SysAct):
     """
     Processes a confirm action from the system based on information in the user goal
     
     Args:
         sys_act (SysAct): the last system action        
     """
     for slot, _value in sys_act.slot_values.items():
         value = _value[0]  # there is always only one value
         if self.goal.is_inconsistent_constraint_strict(
                 Constraint(slot, value)):
             # inform about correct value with some probability, otherwise deny value
             if common.random.random(
             ) < self.parameters['usermodel']['InformOnConfirm']:
                 self.agenda.push(
                     UserAct(act_type=UserActionType.Inform,
                             slot=slot,
                             value=self.goal.get_constraint(slot),
                             score=1.0))
             else:
                 self.agenda.push(
                     UserAct(act_type=UserActionType.NegativeInform,
                             slot=slot,
                             value=value,
                             score=1.0))
         else:
             # NOTE using inform currently since NLU currently does not support Affirm here and
             # NLU would tinker it into an Inform action anyway
             # self.agenda.push(
             #     UserAct(act_type=UserActionType.Affirm, score=1.0))
             self.agenda.push(
                 UserAct(act_type=UserActionType.Inform,
                         slot=slot,
                         value=value,
                         score=1.0))
Пример #14
0
    def parse_user_utterance(self,
                             user_utterance: str = None
                             ) -> dict(user_acts=List[UserAct]):
        """Parses the user utterance.

        Responsible for detecting user acts with their respective slot-values from the user
        utterance by predicting relation, topic entities and the relation's direction.

        Args:
            user_utterance: the last user input as string

        Returns:
            A dictionary with the key "user_acts" and the value containing a list of user actions
        """
        result = {}
        self.user_acts = []

        user_utterance = user_utterance.strip()

        if not user_utterance:
            return {'user_acts': None}
        elif user_utterance.lower().replace(' ', '').endswith('bye'):
            return {'user_acts': [UserAct(user_utterance, UserActionType.Bye)]}

        if self.domain.get_keyword() in user_utterance.lower():
            self.user_acts.append(
                UserAct(user_utterance, UserActionType.SelectDomain))
            begin_idx = user_utterance.lower().find(self.domain.get_keyword())
            user_utterance = user_utterance.lower().replace(
                self.domain.get_keyword(), "")
            if len(user_utterance) == 0:
                return {'user_acts': self.user_acts}

        tokens, embeddings = self._preprocess_utterance(user_utterance)

        relation_out = self._predict_relation(embeddings)
        entities_out = self._predict_topic_entities(embeddings)
        direction_out = self._predict_direction(embeddings)

        relation_pred = self._lookup_relation(relation_out)
        entities_pred = extract_entities(tokens[1:], entities_out[:, 0])
        direction_pred = self._lookup_direction(direction_out)

        self.user_acts.extend([
            UserAct(user_utterance, UserActionType.Inform, 'relation',
                    relation_pred, 1.0),
            UserAct(user_utterance, UserActionType.Inform, 'direction',
                    direction_pred, 1.0)
        ])
        for t in entities_pred:
            self.user_acts.append(
                UserAct(user_utterance, UserActionType.Inform, 'topic',
                        ' '.join(t), 1.0))

        result['user_acts'] = self.user_acts
        self.debug_logger.dialog_turn("User Actions: %s" % str(self.user_acts))
        return result
Пример #15
0
    def extract_user_acts(self,
                          user_utterance: str = None
                          ) -> dict(user_acts=List[UserAct]):
        """Main function for detecting and publishing user acts.

        Args:
            user_utterance: the user input string

        Returns:
            dict with key 'user_acts' and list of user acts as value
        """
        user_acts = []
        if not user_utterance:
            return {'user_acts': None}
        user_utterance = ' '.join(user_utterance.lower().split())

        for bye in ('bye', 'goodbye', 'byebye', 'seeyou'):
            if user_utterance.replace(' ', '').endswith(bye):
                return {
                    'user_acts': [UserAct(user_utterance, UserActionType.Bye)]
                }

        # check weather today
        for regex in WEATHER_DATE_TODAY_REGEXES:
            match = regex.search(user_utterance)
            if match:
                user_acts.append(
                    UserAct(user_utterance, UserActionType.Inform, 'date',
                            datetime.now()))
                break
        if len(user_acts) == 0:
            for regex in WEATHER_DATE_TOMORROW_REGEXES:
                match = regex.search(user_utterance)
                if match:
                    tomorrow = datetime.now() + timedelta(days=1)
                    date = datetime(tomorrow.year,
                                    tomorrow.month,
                                    tomorrow.day,
                                    hour=15)
                    user_acts.append(
                        UserAct(user_utterance, UserActionType.Inform, 'date',
                                date))
                    break
        for regex in WEATHER_LOCATION_REGEXES:
            match = regex.search(user_utterance)
            if match:
                user_acts.append(
                    UserAct(user_utterance, UserActionType.Inform, 'location',
                            match.group(1)))

        self.debug_logger.dialog_turn("User Actions: %s" % str(user_acts))
        return {'user_acts': user_acts}
Пример #16
0
 def _finish_dialog(self, ungrateful=False):
     """
     Pushes a bye action ontop of the agenda in order to end a dialog. Depending on the user
     model, a thankyou action might be added too.
     """
     self.agenda.clear()  # empty agenda
     # thank with some probability
     # NOTE bye has to be the topmost action on the agenda since we check for it in the
     # respond() method
     if not ungrateful and common.random.random(
     ) < self.parameters['usermodel']['Thank']:
         self.agenda.push(UserAct(act_type=UserActionType.Thanks,
                                  score=1.0))
     self.agenda.push(UserAct(act_type=UserActionType.Bye, score=1.0))
Пример #17
0
def test_fill_agenda_on_initialization(agenda, goal, constraintA, constraintB):
    """
    Tests whether the agenda is emptied and filled with the constraints of the given goal on
    initialization.

    Args:
        agenda: Agenda object (given in conftest.py)
        goal: Goal object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stored_action = UserAct(act_type=UserActionType.Inform,
                            slot=constraintA['slot'],
                            value=constraintA['value'])
    goal_constraint = Constraint(slot=constraintB['slot'],
                                 value=constraintB['value'])
    agenda.stack = [stored_action]
    goal.constraints = [goal_constraint]
    agenda.init(goal)
    assert len(agenda.stack) == len(goal.constraints)
    assert stored_action not in agenda.stack
    assert any(item.slot == goal_constraint.slot and item.value ==
               goal_constraint.value and item.type == UserActionType.Inform
               for item in agenda.stack)
Пример #18
0
    def dialog_start(self):
        """Resets the user model at the beginning of a dialog, e.g. draws a new goal and populates
        the agenda according to the goal."""
        # self.goal = Goal(self.domain, self.parameters['goal'])

        self.goal.init()
        self.agenda.init(self.goal)
        if self.logger:
            self.logger.dialog_turn(
                "New goal has constraints {} and requests {}.".format(
                    self.goal.constraints, self.goal.requests))
            self.logger.dialog_turn("New agenda initialized: {}".format(
                self.agenda))

        # add hello action with some probability
        if common.random.random() < self.parameters['usermodel']['Greeting']:
            self.agenda.push(UserAct(act_type=UserActionType.Hello, score=1.0))

        # needed for possibility to reset patience
        if len(self.parameters['usermodel']['patience']) == 1:
            self.dialog_patience = self.parameters['usermodel']['patience'][0]
        else:
            self.dialog_patience = common.random.randint(
                *self.parameters['usermodel']['patience'])
        self.patience = self.dialog_patience
        self.last_user_actions = None
        self.last_system_action = None
        self.excluded_venues = []
        self.turn = 0
Пример #19
0
    def extract_user_acts(self, user_utterance: str = None) -> dict(user_acts=List[UserAct]):

        """
        Responsible for detecting user acts with their respective slot-values from the user
        utterance through regular expressions.

        Args:
            user_utterance (BeliefState) - a BeliefState obejct representing current system
                                           knowledge

        Returns:
            dict of str: UserAct - a dictionary with the key "user_acts" and the value
                                            containing a list of user actions
        """
        result = {}

        # Setting request everything to False at every turn
        self.req_everything = False

        self.user_acts = []

        # slots_requested & slots_informed store slots requested and informed in this turn
        # they are used later for later disambiguation
        self.slots_requested, self.slots_informed = set(), set()
        if user_utterance is not None:
            user_utterance = user_utterance.strip()
            self._match_general_act(user_utterance)
            self._match_domain_specific_act(user_utterance)

        self._solve_informable_values()

        # If nothing else has been matched, see if the user chose a domain; otherwise if it's
        # not the first turn, it's a bad act
        if len(self.user_acts) == 0:
            if self.domain.get_keyword() in user_utterance:
                self.user_acts.append(UserAct(text=user_utterance if user_utterance else "",
                                              act_type=UserActionType.SelectDomain))
            elif self.sys_act_info['last_act'] is not None:
                # start of dialogue or no regex matched
                self.user_acts.append(UserAct(text=user_utterance if user_utterance else "",
                                              act_type=UserActionType.Bad))
        self._assign_scores()
        self.logger.dialog_turn("User Actions: %s" % str(self.user_acts))
        result['user_acts'] = self.user_acts

        return result
Пример #20
0
    def extract_user_acts(self, user_utterance: str = None, sys_act: SysAct = None, beliefstate: BeliefState = None) \
            -> dict(user_acts=List[UserAct]):
        """Original code but adapted to automatically add a request(name) act"""
        result = {}

        # Setting request everything to False at every turn
        self.req_everything = False

        self.user_acts = []

        # slots_requested & slots_informed store slots requested and informed in this turn
        # they are used later for later disambiguation
        self.slots_requested, self.slots_informed = set(), set()
        if user_utterance is not None:
            user_utterance = user_utterance.strip()
            self._match_general_act(user_utterance)
            self._match_domain_specific_act(user_utterance)

        # Solving ambiguities from regexes, especially with requests and informs happening
        # simultaneously on the same slot and two slots taking the same value
        self._disambiguate_co_occurrence(beliefstate)
        self._solve_informable_values()

        # If nothing else has been matched, see if the user chose a domain; otherwise if it's
        # not the first turn, it's a bad act
        if len(self.user_acts) == 0:
            if self.domain.get_keyword() in user_utterance:
                self.user_acts.append(
                    UserAct(text=user_utterance if user_utterance else "",
                            act_type=UserActionType.SelectDomain))
            elif self.sys_act_info['last_act'] is not None:
                # start of dialogue or no regex matched
                self.user_acts.append(
                    UserAct(text=user_utterance if user_utterance else "",
                            act_type=UserActionType.Bad))

        # the name should always be mentioned by the system, so we mock a request for it
        if self.user_acts:
            self.user_acts.append(
                UserAct(user_utterance, UserActionType.Request, 'name'))
        self._assign_scores()
        result['user_acts'] = self.user_acts
        self.logger.dialog_turn("User Actions: %s" % str(self.user_acts))
        return result
Пример #21
0
 def _request_alt(self, offer=None):
     # add current offer to exclusion list, reset current offer and request alternative
     if offer is not None:
         self.excluded_venues.append(offer)
     if self.goal.requests[self.domain.get_primary_key()] is not None:
         self.excluded_venues.append(
             self.goal.requests[self.domain.get_primary_key()])
         self.goal.requests[self.domain.get_primary_key()] = None
     self.goal.reset()
     self.agenda.push(UserAct(act_type=UserActionType.RequestAlternatives))
Пример #22
0
 def _receive_request(self, sys_act: SysAct):
     """
     Processes a request action from the system by adding the corresponding answer based
     on the current simulator goal.
     
     Args:
         sys_act (SysAct): the last system action        
     """
     for slot, _ in sys_act.slot_values.items():
         self.agenda.push(UserAct(
             act_type=UserActionType.Inform,
             slot=slot, value=self.goal.get_constraint(slot),
             score=1.0))
Пример #23
0
def test_clear_stack(agenda, constraintA, constraintB):
    """
    Tests whether clearing the stack will remove all items from it.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    stack = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    agenda.stack = stack.copy()
    agenda.clear()
    assert len(agenda.stack) == 0
Пример #24
0
    def fill_with_requests(self, goal: Goal, exclude_name: bool = True):
        """Adds all request actions to the agenda necessary to fulfill the *goal*.

        Args:
            goal (Goal): The current goal of the (simulated) user for which actions will be pushed to the
                         agenda.
            exclude_name (bool): whehter or not to include an action to request an entities name.

        """
        # add requests and make sure to add the name at the end (i.e. ask first for name)
        for key, value in goal.requests.items():
            if ((key != 'name' and exclude_name) or not exclude_name) and value is None:
                self.stack.append(
                    UserAct(act_type=UserActionType.Request, slot=key, value=value, score=1.0))
Пример #25
0
def test_get_all_usr_action_types(bst):
    """
    Tests whether requesting user action types will return all of them.

    Args:
        bst: BST Object (given in conftest.py)
    """
    user_action_types = [
        UserActionType.Inform, UserActionType.Request, UserActionType.Hello,
        UserActionType.Thanks
    ]
    user_acts = [UserAct(act_type=act_type) for act_type in user_action_types]
    act_type_set = bst._get_all_usr_action_types(user_acts)
    assert act_type_set == set(user_action_types)
Пример #26
0
def test_handle_user_acts_for_user_request(bst):
    """
    Tests whether the requests are set correctly when handling a user request.

    Args:
        bst: BST Object (given in conftest.py)
    """
    slot = 'foo'
    score = 0.5
    user_acts = [
        UserAct(act_type=UserActionType.Request, slot=slot, score=score)
    ]
    bst._handle_user_acts(user_acts)
    assert slot in bst.bs['requests']
    assert bst.bs['requests'][slot] == score
Пример #27
0
def test_push_several_items(agenda, constraintA, constraintB):
    """
    Tests whether pushing several items on the stack increases the stack size by the number of
    items and inserts the items in the same order at the end of the stack.

    Args:
        agenda: Agenda object (given in conftest.py)
        constraintA (dict): an existing slot-value pair in the domain (given in
        conftest_<domain>.py)
        constraintB (dict): another existing slot-value pair in the domain (given in
        conftest_<domain>.py)
    """
    items = [
        UserAct(act_type=UserActionType.Inform,
                slot=constraintA['slot'],
                value=constraintA['value']),
        UserAct(act_type=UserActionType.Confirm,
                slot=constraintB['slot'],
                value=constraintB['value'])
    ]
    stack_size = len(agenda.stack)
    agenda.push(items)
    assert len(agenda.stack) == stack_size + len(items)
    assert agenda.stack[-len(items):] == items
Пример #28
0
    def _add_request(self, user_utterance: str, slot: str):
        """
        Creates the user request act and adds it to the user act list
        Args:
            user_utterance {str} --  text input from user
            slot {str} -- requested slot

        Returns:

        """
        # New user act -- Request(slot)
        user_act = UserAct(text=user_utterance, act_type=UserActionType.Request, slot=slot)
        self.user_acts.append(user_act)
        # Storing user requested slots during the whole dialog
        self.slots_requested.add(slot)
Пример #29
0
    def fill_with_constraints(self, goal):
        """
        Adds all inform actions to the agenda necessary to fulfill the *goal*. Generally there is
        no need to add all constraints from the goal to the agenda apart from the initialisation.

        Args:
            goal: The current goal of the (simulated) user for which actions will be pushed to the
            agenda.

        """

        # add informs from goal
        for constraint in goal.constraints:
            self.stack.append(UserAct(act_type=UserActionType.Inform, slot=constraint.slot,\
                value=constraint.value, score=1.0))
Пример #30
0
def test_handle_user_acts_for_user_negative_inform(bst):
    """
    Tests whether handling a negative inform by the user deletes the corresponding inform value.

    Args:
        bst: BST Object (given in conftest.py)
    """
    slot = 'foo'
    value = 'bar'
    bst.bs['informs'][slot] = {value: 0.5}
    user_acts = [
        UserAct(act_type=UserActionType.NegativeInform, slot=slot, value=value)
    ]
    bst._handle_user_acts(user_acts)
    assert value not in bst.bs['informs'][slot]