Example #1
0
    def receive(self, sys_act):
        """
        This method is called to transmit the machine dialogue act to the user.
        It updates the goal and the agenda.
        :param sys_act: System action.
        :return:
        """
        # Update previous goal.
        self.prev_goal = copy.deepcopy(self.goal)
        # Update the user patience level.
        if self.lastUserAct is not None and self.lastUserAct.act == 'repeat' and \
                self.lastSysAct is not None and self.lastSysAct.act == 'repeat' and \
                sys_act.act == 'repeat':
            # Endless cycle of repeating repeats: reduce patience to zero.
            print "Endless cycle of repeating repeats. Setting patience to zero."
            self.goal.patience = 0
        elif sys_act.act == 'badact' or sys_act.act == 'null' or \
                (self.lastSysAct is not None and self.lastUserAct.act != 'repeat' and self.lastSysAct == sys_act):
            # Same action as last turn. Patience decreased.
            self.goal.patience -= 1
        elif self.patience_old_style:
            # not same action as last time so patience is restored
            self.goal.patience = self.max_patience

        if self.goal.patience < 1:
            self.hdcSim.agenda.clear()
            # Pushing bye act onto agenda.
            self.hdcSim.agenda.push(DiaAct('bye()'))
            return

        # Update last system action.
        self.lastSysAct = sys_act

        # Process the sys_act
        self.hdcSim.receive(sys_act, self.goal)
Example #2
0
    def start_call(self, simulated_user):
        self.restart()
        self.num_dialogs += 1

        last_sys_act = self.retrieve_last_sys_act()

        # SYSTEM ACT:
        # 1. Belief state tracking
        belief_state = self.bs_tracker.update_belief_state(
            last_act=last_sys_act, obs=[])

        # 2.Query Knowledge base
        constraints = {}
        slots = Ontology.global_ontology.get_system_requestable_slots()
        for slot in slots:
            constraints[slot] = max(belief_state[slot],
                                    key=belief_state[slot].get)
        entities = KnowledgeBase.global_kb.entity_by_features(constraints)

        # 3. Add recommended list into belief state
        belief_state['name'] = self.recommended_list

        belief_state['entity'] = len(entities)

        # 4. Policy -- Determine system act/response
        sys_act = self.policy_manager.act_on(belief_state, entities)

        # 5. Add system recommend restaurant to the recommended list
        if not isinstance(sys_act, DiaAct):
            sys_act = DiaAct(str(sys_act))

        if sys_act.act == 'inform':
            name = sys_act.get_value('name', negate=False)
            if name not in ['none', None]:
                try:
                    self.recommended_list.remove(name)
                except:
                    pass
                self.recommended_list.append(name)

        # 6. EVALUATION: - record the system action
        self._evaluate_agents_turn(simulated_user, sys_act, belief_state)

        return sys_act
Example #3
0
    def act_on(self, belief_state, entities):
        if self.last_system_action is None and self.start_with_hello:
            sys_act, next_action_idx = 'hello()', -1
        else:
            sys_act, next_action_idx = self.next_action(belief_state, entities)
        self.last_system_action = sys_act
        self.summary_act = next_action_idx
        self.prev_belief = belief_state

        sys_action = DiaAct(sys_act)
        return sys_action
Example #4
0
    def act_on(self, sys_act_string):
        """
        Through the UserModel member, receives the system action and then responds.
        :param sys_act_string: system action
        :type sys_act_string: unicode str
        :returns: (str) user action
        """
        sys_act = DiaAct(sys_act_string)
        self.um.receive(sys_act)
        user_act = self.um.respond()

        return user_act
Example #5
0
    def continue_call(self, user_act, simulated_user):

        if self._turn_increment_and_check():
            sys_act = DiaAct('bye()')
            return sys_act

        # Make sure there is some asr information:
        if user_act is None:
            sys_act = DiaAct('null()')
            return sys_act

        last_sys_act = self.retrieve_last_sys_act()

        # SYSTEM ACT:
        # 1. Belief state tracking
        belief_state = self.bs_tracker.update_belief_state(
            last_act=last_sys_act, obs=[(str(user_act), 1.0)])

        # 2.Query Knowledge base
        constraints = {}
        slots = Ontology.global_ontology.get_system_requestable_slots()
        for slot in slots:
            constraints[slot] = max(belief_state[slot],
                                    key=belief_state[slot].get)
        entities = KnowledgeBase.global_kb.entity_by_features(constraints)

        # 3. Add recommended list into belief state
        belief_state['name'] = self.recommended_list

        # 4. Policy -- Determine system act/response type: DiaAct
        sys_act = self.policy_manager.act_on(belief_state, entities)

        # 5. Add system recommend restaurant to the recommended list
        if not isinstance(sys_act, DiaAct):
            sys_act = DiaAct(str(sys_act))

        if sys_act.act == 'inform':
            name = sys_act.get_value('name', negate=False)
            if name not in ['none', None]:
                try:
                    self.recommended_list.remove(name)
                except:
                    pass
                self.recommended_list.append(name)

        # 6. EVALUATION: - record the system action
        self._evaluate_agents_turn(simulated_user, sys_act, belief_state)

        return sys_act
Example #6
0
    def act_on(self, belief_state, entities):
        """
        Main policy method: mapping of belief state to system action.

        This method is automatically invoked by the agent at each turn after tracking the belief state.

        May initially return 'hello()' as hardcoded action. Keeps track of last system action and last belief state.

        :param belief_state: the belief state to act on
        :type belief_state: dict
        :param entities: search results from knowledge base (match to the constraints, if no constraints: random 10)
        :type entities: list
        :returns: the next system action of type :class:`~utils.dact.DiaAct`
        """
        if self.last_system_action is None and self.start_with_hello:
            sys_act = 'hello()'
        else:
            sys_act = self.next_action(belief_state, entities)
        self.last_system_action = sys_act
        self.prev_belief = belief_state
        sys_action = DiaAct(sys_act)
        return sys_action
Example #7
0
    def _get_turn_reward(self, turn_info):
        """
        Computes the turn reward regarding turn_info. The default turn reward is -1 unless otherwise computed.

        :param turn_info: parameters necessary for computing the turn reward, eg., system act, prev system act and state
        :type turn_info: dict
        :return: int -- the turn reward.
        """
        # Immediate reward for each turn.
        reward = -self.penalise_all_turns

        if turn_info is not None and isinstance(turn_info, dict):
            if 'usermodel' in turn_info and 'sys_act' in turn_info:
                um = turn_info['usermodel']
                self.user_goal = um.goal.constraints

                # unpack input user model um.
                prev_consts = copy.deepcopy(um.goal.constraints)
                for item in prev_consts:
                    if item.slot == 'name' and item.op == '=':
                        item.val = 'dontcare'
                requests = um.goal.requests
                sys_act = DiaAct(turn_info['sys_act'])
                user_act = um.lastUserAct

                # Check if the most recent venue satisfies constraints.
                name = sys_act.get_value('name', negate=False)
                if name not in ['none', None]:
                    # Venue is recommended.
                    is_valid_venue = self._is_valid_venue(name, prev_consts)
                    if is_valid_venue:
                        # Success except if the next user action is reqalts.
                        if user_act.act != 'reqalts':
                            self.venue_recommended = True  # Correct venue is recommended.
                        else:
                            if 'state' in turn_info:
                                belief_state = turn_info['state']
                                recommended_list = belief_state['name']
                                if name not in recommended_list:
                                    reward += self.reward_venue_alternatives
                                else:
                                    reward -= self.penalty_venue_alternatives
                    else:
                        # Previous venue did not match.
                        self.venue_recommended = False
                        reward -= self.wrong_venue_penalty

                # If system inform(name=none) but it was not right decision based on wrong values.
                if name == 'none' and sys_act.has_conflicting_value(
                        prev_consts):
                    reward -= self.wrong_venue_penalty

                # Check if the system used slot values previously not mentioned for 'select' and 'confirm'.
                not_mentioned = False
                if sys_act.act in ['select', 'confirm']:
                    for slot in Ontology.global_ontology.get_system_requestable_slots(
                    ):
                        values = set(sys_act.get_values(slot))
                        if len(values - self.mentioned_values[slot]) > 0:
                            # System used values which are not previously mentioned.
                            not_mentioned = True
                            break

                if not_mentioned:
                    reward -= self.not_mentioned_value_penalty

                # If the correct venue has been recommended and all requested slots are filled,
                # check if this dialogue is successful.
                if self.venue_recommended and None not in requests.values():
                    reward += self.reward_venue_recommended

                # Update mentioned values.
                self._update_mentioned_value(sys_act)
                self._update_mentioned_value(user_act)

        return reward