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)
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
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
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
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
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
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