def _build_one_answer(self, da_metadata, answer, follow_order=False): '''Build a full answer to a system act. Args: da_metadata: a dict contains only description of system act such as slots-values. answer: a dic full description of answer act. follow_order: a boolean specifying the first return act need to be satisfied or cancel completely the answer. Returns: A list of DialogueActItem object. ''' #print answer da_items = [] new_items = [] first_act = True for act_out in answer['return_acts']:#for reply without ordered answer #New for repeat if act_out == 'repeat': da_items.extend(self.last_user_da)#add previous act, may add more if we use inform in return_acts continue answer_types = get_dict_value(answer, act_out + '_answer_types') answer_type = None if answer_types is not None: answer_type = sample_from_dict(answer_types) overridden_properties = get_dict_value(answer, act_out + '_overridden_properties') #da_items.extend(self._build_dialogue_act_items(da_metadata, act_out, answer_type, overridden_properties)) new_items = self._build_dialogue_act_items(da_metadata, act_out, answer_type, overridden_properties) da_items.extend(new_items) if follow_order and 'all_act_valid' in answer.keys() and answer['all_act_valid']==True:#this case of this answer requires all acts must appliabl if len(new_items)==0: da_items = []#cancel all other da item already build, that will move to next case of anser break if first_act and follow_order:#if the first action in a return actions which follows the order not successful, that case not satisfy, give up first_act=False if len(da_items)==0: break return da_items
def _get_random_goal(self): '''Sample a final goal of user. Returns: A dict represent slots and their values sampled. ''' self.goal_id = sample_from_dict(self._goal_dist) goal_des = self.metadata['goals'][self.goal_id] goal = {} self.goal = goal sampled_slots = [] for s, v in goal_des['fixed_slots']:#fixed slots goal[s] = v sampled_slots.append(s) for key in goal_des['same_table_slot_keys']:#same table slots NOTE same_table_slot was coded without testing since data hadn't faked yet slots_values = self._get_random_same_table_slots_values(key) for slot in slots_values.keys(): if slot in goal_des['changeable_slots']: sampled_slots.append(slot) goal[slot] = slots_values[slot] for one_set in goal_des['one_of_slot_set']:#get value for one slot set and ignore other slots slot_set = sample_from_dict(one_set) for slot in slot_set: goal[slot] = self._get_random_slot_value(slot) for key in one_set.keys(): sampled_slots.extend(key) sampled_slots.extend(goal_des['sys_unaskable_slots']) remain_slots = matlab.subtract(goal_des['changeable_slots'], sampled_slots) for slot in remain_slots:#changeable slots goal[slot] = self._get_random_slot_value(slot) '''Don't fill default slots, only return when system ask for slot, value in goal_des['default_slots_values']:#fill the default slot which was not being filled if slot not in goal.keys(): goal[slot] = value ''' fun = get_dict_value(goal_des,'goal_post_process_fun') if fun is not None: #goal = fun(self, goal) goal = fun(goal) #for debug: #self.goal_id = 0 #goal = {'to_city': u'Allerton', 'task': 'find_connection', 'from_city': u'North Massapequa',} return goal
def end_dialogue(self): '''end dialgoue and post-processing''' fun = get_dict_value(self.metadata['goals'][self.goal_id], 'end_dialogue_post_process_fun') if fun is not None: fun(self)
def _get_combined_slots(self, act_in, act_out_des, answer_type, used_slots): '''Find combineable slots for Args: act_in: A dict presenting the metadata of system act. act_out_des: A dict describing the setting of answer act. answer_type: A string showing the type of answer such as direct_answer, over_answer used_slots: A list of slots which the act already used in previous turns. Returns: A list of combineable slots. Raises: NotImplementedError: The source providing slots for the action was not implemented. Or the answer_type used was not implemented. ''' #print 'get_combined_slot, act_in=', act_in, ' act_out_des=', act_out_des lst = [] remain_slots = self.goal.keys() if 'combineable_slots' in act_out_des.keys():#figured out list of combineable slot in the config file, but still have to filter at status slot lst.extend(act_out_des['combineable_slots']) #return act_out_des['combineable_slots'] remain_slots = act_out_des['combineable_slots'] #print '--combined slots1', lst if 'accept_used_slots' in act_out_des.keys() and act_out_des['accept_used_slots']==False:#filter used slot remain_slots = matlab.subtract(remain_slots, used_slots) #print '--combined slots2', lst if 'slot_from' in act_out_des.keys():#take all slot in the type figured in slot_from if act_out_des['slot_from']=='sys_da': lst.extend(act_in['slots']) elif act_out_des['slot_from']=='none': pass#dont take slot from sys_da elif act_out_des['slot_from']=='goal': lst.extend(self.goal.keys()) else: raise NotImplementedError('slot_from=%s unhandled yet'%act_out_des['slot_from']) #print '--combined slots3', lst #process answer_type if answer_type=='direct_answer': pass#every slot in sys_da already included elif answer_type=='over_answer': #only over or complete answer for slot not mentioned remain_slots = matlab.subtract(remain_slots, lst) lst.extend(random_filter_list(remain_slots)) elif answer_type=='complete_answer': remain_slots = matlab.subtract(remain_slots, lst) lst.extend(remain_slots) elif answer_type is None: pass else: raise NotImplementedError('answer_type=%s unhandled yet'%answer_type) #print '--combined slots4', lst #process litmited slots if 'limited_slots' in act_out_des.keys(): limits = act_out_des['limited_slots'] limits = matlab.subtract(limits, act_in['slots'])#limited slots will be used when system ask #lst = matlab.subtract(lst, act_out_des['limited_slots']) lst = matlab.subtract(lst, limits) #process status included if 'status_included' in act_out_des.keys(): status_included = act_out_des['status_included'] lst = self._filter_slot_status(act_in, lst, status_included) #print '--combined slots5', lst # the act required all its slot need to be have the same status if 'status_in_all_slots' in act_out_des.keys() and act_out_des['status_in_all_slots']: if len(lst)!= len(act_in['slots']):#TODO this way of testing may give trouble in some cases in future, but currently it works. lst = []#this action require all of requested slot must satisfy the given status #add atlesat slots if 'atleast_slots' in act_out_des.keys(): for slot in act_out_des['atleast_slots']: if slot not in lst: lst.append(slot) #process slot_used_sequence goal_des = self.metadata['goals'][self.goal_id] if 'slot_used_sequence' in goal_des.keys(): use_sequence = get_dict_value(act_out_des, 'use_slot_sequence') if use_sequence is not None and use_sequence:#default dont using slot sequence lst = self._filter_slot_used_sequence(goal_des['slot_used_sequence'], lst) #print '--combined slots', lst return lst