Beispiel #1
0
    def update(self, user_act=None):
        # print('------------------{}'.format(user_act))
        if type(user_act) is not dict:
            raise Exception('Expect user_act to be <class \'dict\'> type but get {}.'.format(type(user_act)))
        previous_state = self.state
        new_belief_state = copy.deepcopy(previous_state['belief_state'])
        new_request_state = copy.deepcopy(previous_state['request_state'])
        for domain_type in user_act.keys():
            domain, tpe = domain_type.lower().split('-')
            if domain in ['unk', 'general', 'booking']:
                continue
            if tpe == 'inform':
                for k, v in user_act[domain_type]:
                    k = REF_SYS_DA[domain.capitalize()].get(k, k)
                    if k is None:
                        continue
                    try:
                        assert domain in new_belief_state
                    except:
                        raise Exception('Error: domain <{}> not in new belief state'.format(domain))
                    domain_dic = new_belief_state[domain]
                    assert 'semi' in domain_dic
                    assert 'book' in domain_dic

                    if k in domain_dic['semi']:
                        nvalue = normalize_value(self.value_dict, domain, k, v)
                        # if nvalue != v:
                        #     _log('domain {} slot {} value {} -> {}'.format(domain, k, v, nvalue))
                        new_belief_state[domain]['semi'][k] = nvalue
                    elif k in domain_dic['book']:
                        new_belief_state[domain]['book'][k] = v
                    elif k.lower() in domain_dic['book']:
                        new_belief_state[domain]['book'][k.lower()] = v
                    elif k == 'trainID' and domain == 'train':
                        new_belief_state[domain]['book'][k] = normalize_value(self.value_dict, domain, k, v)
                    else:
                        # raise Exception('unknown slot name <{}> of domain <{}>'.format(k, domain))
                        with open('unknown_slot.log', 'a+') as f:
                            f.write('unknown slot name <{}> of domain <{}>\n'.format(k, domain))
            elif tpe == 'request':
                for k, v in user_act[domain_type]:
                    k = REF_SYS_DA[domain.capitalize()].get(k, k)
                    if domain not in new_request_state:
                        new_request_state[domain] = {}
                    if k not in new_request_state[domain]:
                        new_request_state[domain][k] = 0

        new_state = copy.deepcopy(previous_state)
        new_state['belief_state'] = new_belief_state
        new_state['request_state'] = new_request_state
        new_state['user_action'] = user_act

        self.state = new_state
        
        return self.state
Beispiel #2
0
    def update(self, user_act=None):
        """Update the dialogue state with the generated tokens from TRADE"""
        if not isinstance(user_act, str):
            raise Exception(
                f'Expected user_act is str but found {type(user_act)}')
        prev_state = self.state

        actual_history = copy.deepcopy(prev_state['history'])
        actual_history[-1].append(user_act)  # [sys, user], [sys,user]

        query = self.construct_query(actual_history)
        pred_states = self.predict(query)

        new_belief_state = copy.deepcopy(prev_state['belief_state'])
        for state in pred_states:
            domain, slot, value = state.split('-')
            if slot not in ['name', 'book']:
                if domain not in new_belief_state:
                    raise Exception(
                        'Error: domain <{}> not in belief state'.format(
                            domain))
            slot = REF_SYS_DA[domain.capitalize()].get(slot, slot)
            assert 'semi' in new_belief_state[domain]
            assert 'book' in new_belief_state[domain]
            if 'book' in slot:
                assert slot.startswith('book ')
                slot = slot.strip().split()[1]
            domain_dic = new_belief_state[domain]
            if slot in domain_dic['semi']:
                new_belief_state[domain]['semi'][slot] = normalize_value(
                    self.value_dict, domain, slot, value)
            elif slot in domain_dic['book']:
                new_belief_state[domain]['book'][slot] = value
            elif slot.lower() in domain_dic['book']:
                new_belief_state[domain]['book'][slot.lower()] = value
            else:
                with open('trade_tracker_unknown_slot.log', 'a+') as f:
                    f.write(
                        f'unknown slot name <{slot}> with value <{value}> of domain <{domain}>\nitem: {state}\n\n'
                    )

        new_request_state = copy.deepcopy(prev_state['request_state'])
        # update request_state
        user_request_slot = self.detect_requestable_slots(user_act)
        for domain in user_request_slot:
            for key in user_request_slot[domain]:
                if domain not in new_request_state:
                    new_request_state[domain] = {}
                if key not in new_request_state[domain]:
                    new_request_state[domain][key] = user_request_slot[domain][
                        key]

        new_state = copy.deepcopy(dict(prev_state))
        new_state['belief_state'] = new_belief_state
        new_state['request_state'] = new_request_state
        self.state = new_state
        # print((pred_states, query))
        return self.state
Beispiel #3
0
    def update(self, user_act=None):
        """Update the dialog state."""
        if type(user_act) is not str:
            raise Exception(
                'Expected user_act to be <class \'str\'> type, but get {}.'.
                format(type(user_act)))
        prev_state = self.state
        if not os.path.exists(os.path.join(self.data_dir, "results")):
            os.makedirs(os.path.join(self.data_dir, "results"))

        global train_batch_size

        model_variables = self.model_variables
        (user, sys_res, no_turns, user_uttr_len, sys_uttr_len, labels,
         domain_labels, domain_accuracy, slot_accuracy, value_accuracy,
         value_f1, train_step, keep_prob, predictions, true_predictions,
         [y, _]) = model_variables

        # generate fake dialogue based on history (this os to reuse the original MDBT code)
        # actual_history = prev_state['history']  # [[sys, user], [sys, user], ...]
        actual_history = copy.deepcopy(
            prev_state['history'])  # [[sys, user], [sys, user], ...]
        actual_history[-1].append(user_act)
        actual_history = self.normalize_history(actual_history)
        if len(actual_history) == 0:
            actual_history = [[
                '', user_act if len(user_act) > 0 else 'fake user act'
            ]]
        fake_dialogue = {}
        turn_no = 0
        for _sys, _user in actual_history:
            turn = {}
            turn['system'] = _sys
            fake_user = {}
            fake_user['text'] = _user
            fake_user['belief_state'] = init_belief_state
            turn['user'] = fake_user
            key = str(turn_no)
            fake_dialogue[key] = turn
            turn_no += 1
        context, actual_context = process_history([fake_dialogue],
                                                  self.word_vectors,
                                                  self.ontology)
        batch_user, batch_sys, batch_labels, batch_domain_labels, batch_user_uttr_len, batch_sys_uttr_len, \
                batch_no_turns = generate_batch(context, 0, 1, len(self.ontology))  # old feature

        # run model
        [pred, y_pred] = self.sess.run(
            [predictions, y],
            feed_dict={
                user: batch_user,
                sys_res: batch_sys,
                labels: batch_labels,
                domain_labels: batch_domain_labels,
                user_uttr_len: batch_user_uttr_len,
                sys_uttr_len: batch_sys_uttr_len,
                no_turns: batch_no_turns,
                keep_prob: 1.0
            })

        # convert to str output
        dialgs, _, _ = track_dialogue(actual_context, self.ontology, pred,
                                      y_pred)
        assert len(dialgs) >= 1
        last_turn = dialgs[0][-1]
        predictions = last_turn['prediction']
        new_belief_state = copy.deepcopy(prev_state['belief_state'])

        # updaet belief state
        for item in predictions:
            item = item.lower()
            domain, slot, value = item.strip().split('-')
            value = value[::-1].split(':', 1)[1][::-1]
            if slot == 'price range':
                slot = 'pricerange'
            if slot not in ['name', 'book']:
                if domain not in new_belief_state:
                    raise Exception(
                        'Error: domain <{}> not in belief state'.format(
                            domain))
                slot = REF_SYS_DA[domain.capitalize()].get(slot, slot)
                assert 'semi' in new_belief_state[domain]
                assert 'book' in new_belief_state[domain]
                if 'book' in slot:
                    assert slot.startswith('book ')
                    slot = slot.strip().split()[1]
                domain_dic = new_belief_state[domain]
                if slot in domain_dic['semi']:
                    new_belief_state[domain]['semi'][slot] = normalize_value(
                        self.value_dict, domain, slot, value)
                elif slot in domain_dic['book']:
                    new_belief_state[domain]['book'][slot] = value
                elif slot.lower() in domain_dic['book']:
                    new_belief_state[domain]['book'][slot.lower()] = value
                else:
                    with open('mdbt_unknown_slot.log', 'a+') as f:
                        f.write(
                            'unknown slot name <{}> with value <{}> of domain <{}>\nitem: {}\n\n'
                            .format(slot, value, domain, item))
        new_request_state = copy.deepcopy(prev_state['request_state'])
        # update request_state
        user_request_slot = self.detect_requestable_slots(user_act)
        for domain in user_request_slot:
            for key in user_request_slot[domain]:
                if domain not in new_request_state:
                    new_request_state[domain] = {}
                if key not in new_request_state[domain]:
                    new_request_state[domain][key] = user_request_slot[domain][
                        key]
        # update state
        new_state = copy.deepcopy(dict(prev_state))
        new_state['belief_state'] = new_belief_state
        new_state['request_state'] = new_request_state
        self.state = new_state
        return self.state