Пример #1
0
def main(in_dataset_folder, in_model_folder, in_no_ood_evaluation):
    rev_vocab, kb, action_templates, config = load_model(in_model_folder)
    test_dialogs, test_indices = read_dialogs(os.path.join(
        in_dataset_folder, 'dialog-babi-task6-dstc2-tst.txt'),
                                              with_indices=True)

    et = EntityTracker(kb)
    at = ActionTracker(None, et)
    at.set_action_templates(action_templates)

    vocab = {word: idx for idx, word in enumerate(rev_vocab)}
    X, action_masks, sequence_masks, y = make_dataset(
        test_dialogs, test_indices, vocab, et, at, config['max_input_length'])

    net = LSTM_net(config, X.shape[-1], action_masks.shape[-1])
    net.restore(in_model_folder)
    eval_stats_full_dataset = evaluate_advanced(
        net, (X, action_masks, sequence_masks, y), test_indices,
        at.action_templates)
    print(
        'Full dataset: {} turns overall, {} turns after the first OOD'.format(
            eval_stats_full_dataset['total_turns'],
            eval_stats_full_dataset['total_turns_after_ood']))
    print('Accuracy:')
    accuracy = eval_stats_full_dataset[
        'correct_turns'] / eval_stats_full_dataset['total_turns']
    accuracy_after_ood = eval_stats_full_dataset['correct_turns_after_ood'] / eval_stats_full_dataset['total_turns_after_ood'] \
        if eval_stats_full_dataset['total_turns_after_ood'] != 0 \
        else 0
    print('overall: {:.3f}; after first OOD: {:.3f}'.format(
        accuracy, accuracy_after_ood))
    print('Loss : {:.3f}'.format(eval_stats_full_dataset['avg_loss']))

    if in_no_ood_evaluation:
        eval_stats_no_ood = evaluate_advanced(
            net, (X, action_masks, sequence_masks, y),
            test_indices,
            at.action_templates,
            ignore_ood_accuracy=True)
        print('Accuracy (OOD turns ignored):')
        accuracy = eval_stats_no_ood['correct_turns'] / eval_stats_no_ood[
            'total_turns']
        accuracy_after_ood = eval_stats_no_ood['correct_turns_after_ood'] / eval_stats_no_ood['total_turns_after_ood'] \
            if eval_stats_no_ood['total_turns_after_ood'] != 0 \
            else 0
        print('overall: {:.3f}; after first OOD: {:.3f}'.format(
            accuracy, accuracy_after_ood))
        print('Loss : {:.3f}'.format(eval_stats_no_ood['avg_loss']))
Пример #2
0
class InteractiveSession:

    def __init__(self):

        et = EntityTracker()
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        at = ActionTracker(et)

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size, action_size=action_size, nb_hidden=nb_hidden)

        # restore checkpoint
        self.net.restore()

    def interact(self):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        # begin interaction loop
        while True:

            # get input from user
            u = input('User: '******'clear' or u == 'reset' or u == 'restart':
                self.net.reset_state()
                et = EntityTracker()
                at = ActionTracker(et)
                print('Bot: Reset successfully')

            # check for entrance and exit command
            elif u == 'exit' or u == 'stop' or u == 'quit' or u == 'q':
                print("Bot: Thank you for using")
                break

            elif u == 'hello' or u == 'hi':
                print("Bot: Hello, what can i do for you")

            elif u == 'thank you' or u == 'thanks' or u == 'thank you very much':
                print('Bot: You are welcome')
                break

            else:
                if not u:
                    continue

                u = u.lower()

                # encode
                u_ent = et.extract_entities(u)
                u_ent_features = et.context_features()  # 5

                # print(et.entities)
                # print(et.ctxt_features)

                u_emb = self.emb.encode(u)              # 300
                u_bow = self.bow_enc.encode(u)          # 60
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
                # print(features.shape)
                # get action mask
                action_mask = at.action_mask()
                # action_mask = np.ones(self.net.action_size)

                # print("action_mask: ", action_mask)

                # forward
                prediction = self.net.forward(features, action_mask)
                response = self.action_templates[prediction]
                if prediction == 0:
                    slot_values = copy.deepcopy(et.entities)
                    slot_values.pop('<location>')
                    memory = []
                    count = 0
                    for k, v in slot_values.items():
                        memory.append('='.join([k, v]))
                        count += 1
                        if count == 2:
                            memory.append('\n')

                    response = response.replace("memory", ', '.join(memory))

                    # memory = ', '.join(slot_values.values())
                    # response = response.replace("memory", memory)
                    self.net.reset_state()
                    et = EntityTracker()
                    at = ActionTracker(et)
                    # print('Execute successfully and begin new session')
                if prediction == 1:
                    response = response.replace("location", '<location>=' + et.entities['<location>'])
                print('Bot: ', response)
Пример #3
0
class InteractiveSession():
    def __init__(self):

        et = EntityTracker()
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        at = ActionTracker(et)

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)

        # restore checkpoint
        self.net.restore()

    def interact(self):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        # begin interaction loop
        while True:

            # get input from user
            u = input(':: ')

            # check if user wants to begin new session
            if u == 'clear' or u == 'reset' or u == 'restart':
                self.net.reset_state()
                et = EntityTracker()
                at = ActionTracker(et)
                print('')

            # check for exit command
            elif u == 'exit' or u == 'stop' or u == 'quit' or u == 'q':
                break

            else:
                # ENTER press : silence
                if not u:
                    u = '<SILENCE>'

                # encode
                u_ent, u_entities = et.extract_entities(u, is_test=True)
                u_ent_features = et.context_features()

                u_emb = self.emb.encode(u)
                u_bow = self.bow_enc.encode(u)
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow),
                                          axis=0)
                # get action mask
                action_mask = at.action_mask()

                # forward
                prediction = self.net.forward(features, action_mask)
                print('prediction : ', prediction)
                print(u_entities)
                print('\n')
                if self.post_process(prediction, u_ent_features):
                    print(
                        '>>', 'api_call ' + u_entities['<cuisine>'] + ' ' +
                        u_entities['<location>'] + ' ' +
                        u_entities['<party_size>'] + ' ' +
                        u_entities['<rest_type>'])

                else:
                    prediction = self.action_post_process(
                        prediction, u_entities)
                    print('>>', self.action_templates[prediction])

                    # if all entities is satisfied and the user agree to make a reservation.
                    if all(u_ent_featur == 1
                           for u_ent_featur in u_ent_features) and (prediction
                                                                    == 10):
                        break

    def post_process(self, prediction, u_ent_features):
        if prediction == 0:
            return True
        attr_list = [9, 12, 6, 1]
        if all(u_ent_featur == 1
               for u_ent_featur in u_ent_features) and prediction in attr_list:
            return True
        else:
            return False

    def action_post_process(self, prediction, u_entities):
        attr_mapping_dict = {
            9: '<cuisine>',
            12: '<location>',
            6: '<party_size>',
            1: '<rest_type>'
        }

        # find exist and non-exist entity
        exist_ent_index = [
            key for key, value in u_entities.items() if value != None
        ]
        non_exist_ent_index = [
            key for key, value in u_entities.items() if value == None
        ]

        # if predicted key is already in exist entity index then find non exist entity index
        # and leads the user to input non exist entity.

        if prediction in attr_mapping_dict:
            pred_key = attr_mapping_dict[prediction]
            if pred_key in exist_ent_index:
                for key, value in attr_mapping_dict.items():
                    if value == non_exist_ent_index[0]:
                        return key
            else:
                return prediction
        else:
            return prediction
Пример #4
0
class InteractiveSession():
    def __init__(self):

        et = EntityTracker()
        self.bow_enc = BoW_encoder(et)
        self.emb = UtteranceEmbed()
        at = ActionTracker(et)

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)

        # restore checkpoint
        self.net.restore()

    def interact(self, input):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        # begin interaction loop
        #while True:

        # get input from user
        #u = input(':: ')
        u = input
        # check if user wants to begin new session
        if u == 'clear' or u == 'reset' or u == 'restart':
            self.net.reset_state()
            et = EntityTracker()
            at = ActionTracker(et)
            print('')

        # check for exit command
        #elif u == 'exit' or u == 'stop' or u == 'quit' or u == 'q':
        #break

        else:
            # ENTER press : silence
            if not u:
                u = '<SILENCE>'

                # encode
            u_ent = et.extract_entities(u)
            u_ent_features = et.context_features()
            u_emb = self.emb.encode(u)
            u_bow = self.bow_enc.encode(u)
            # concat features
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
            # get action mask
            action_mask = at.action_mask()

            # forward
            prediction = self.net.forward(features, action_mask)
            #print('>>', self.action_templates[prediction])
        return self.action_templates[prediction]
Пример #5
0
class InteractiveSession:
    def __init__(self):

        self.et = EntityTracker()
        self.at = ActionTracker(self.et)

        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()

        obs_size = self.emb.dim + self.bow_enc.vocab_size + self.et.num_features
        self.action_templates = self.at.get_action_templates()
        action_size = self.at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)

        # restore checkpoint
        self.net.restore()
        self.net.reset_state()

    def reset(self):
        self.net.reset_state()
        self.et = EntityTracker()
        self.at = ActionTracker(self.et)

    def interact(self, utterance, intent, slot_values):
        # get input from user
        u = utterance.lower()

        # check if user wants to begin new session
        if u == 'clear' or u == 'reset' or u == 'restart':
            self.reset()
            return "reset successfully"

        # check for entrance and exit command
        elif u == 'exit' or u == 'stop' or u == 'quit' or u == 'q':
            self.reset()
            return "Thank you for using"

        elif u == 'hello' or u == 'hi':
            self.reset()
            return "what can i do for you"

        elif u == 'thank you' or u == 'thanks' or u == 'thank you very much':
            self.reset()
            return 'you are welcome'

        else:

            # encode
            u_ent = self.et.extract_entities(u, intent, slot_values)
            u_ent_features = self.et.context_features()  # 5
            u_emb = self.emb.encode(u)  # 300
            u_bow = self.bow_enc.encode(u)  # 60
            # concat features
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)

            # get action mask
            action_mask = self.at.action_mask()
            # action_mask = np.ones(self.net.action_size)

            # forward
            prediction = self.net.forward(features, action_mask)
            response = self.action_templates[prediction]
            if prediction == 0:
                slot_values = copy.deepcopy(self.et.entities)
                slot_values.pop('location')
                memory = ', '.join(slot_values.values())
                response = response.replace("memory", memory)
                self.reset()
                print('API CALL execute successfully and begin new session')
            if prediction == 1:
                response = response.replace("location",
                                            self.et.entities['location'])
            return response
Пример #6
0
class InteractiveSession():
    def __init__(self):
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        self.at = ActionTracker(interact=True)
        print(self.at.dialog_acts)
        _, _, self.other_da, self.other_da_id = self.at.get_data()
        self.action_templates = self.at.action_templates
        self.action_size = self.at.action_size
        #self.responses = [r[0] for r in self.at.responses]
        #print(self.emb.dim , self.bow_enc.vocab_size , self.action_size)
        self.obs_size = self.emb.dim + self.bow_enc.vocab_size + self.action_size
        nb_hidden = 128
        self.exercises = list(self.at.action_templates.keys())
        self.net = LSTM_net(obs_size=self.obs_size,
                            action_size=self.action_size,
                            nb_hidden=nb_hidden)
        # restore checkpoint
        self.net.restore()

        # setup remote interaction via zeromq
        context = zmq.Context.instance()
        # PUB socket for sending system-output
        self.pubSocket: zmq.Socket = context.socket(zmq.PUB)
        self.pubSocket.bind(Config.SYSTEM_OUTPUT_ADDR)
        # SUB socket for receiving user-input
        self.subSocket: zmq.Socket = context.socket(zmq.SUB)
        self.subSocket.connect(Config.USER_INPUT_ADDR)
        self.subSocket.setsockopt_string(zmq.SUBSCRIBE,
                                         Config.USER_INPUT_SUBJECT)
        self.lastOutputMessage: str = None
        self.requestHandler: threading.Thread = None
        self.requestInterrupted: threading.Lock = None

    def has_exercise(self, exercise_name: str) -> bool:
        return exercise_name in self.at.action_templates

    def get_current_exercise(self) -> str:
        return self.at.exercise

    def send(self, message, utteranceType, state, dialogAct):
        print(">>", message)
        data = SystemOutputData(text=message,
                                utterance_type=utteranceType,
                                state=state,
                                dialogue_act=dialogAct)
        msg = SystemOutputMessage(type=MessageType.OUTPUT,
                                  timestamp=int(time.time() * 1000),
                                  data=data)
        jsonMsg = json.dumps(msg.to_dict())
        self.lastOutputMessage = jsonMsg
        rawMsg = "%s %s" % (to_enum(MessageType, msg.type), jsonMsg)
        # print("  ", rawMsg)#DEBUG
        self.pubSocket.send_string(rawMsg)

    def receive(self) -> 'UserInputMessage':
        rawMsg = self.subSocket.recv_string()
        # print("  ", rawMsg)#DEBUG
        # FIXME detect & handle when message has other type than "input"
        # TODO handle message types other than "input"
        msgTypeStr = to_enum(MessageType, MessageType.INPUT)
        # extract JSON message by removing subject/subscription string from beginning of message:
        msgStr = rawMsg.replace(msgTypeStr, "", 1).strip()
        return user_input_message_from_dict(json.loads(msgStr))

    def start_processing_requests(self, verbose: bool = False):
        self.stop_processing_requests()
        self.requestInterrupted = threading.Lock()
        self.requestInterrupted.acquire()
        self.requestHandler = threading.Thread(
            target=request_worker,
            args=(Config.QUERY_SYSTEM_OUTPUT_ADDR, self,
                  self.requestInterrupted, verbose))
        self.requestHandler.start()

    def stop_processing_requests(self):
        if self.requestInterrupted is not None and self.requestHandler is not None and self.requestHandler.isAlive(
        ):
            self.requestInterrupted.release()
            # print("should stop request_worker thread now!")
            self.requestHandler.join()
            print("stopped request_worker thread.")

    def interact_anew(self,
                      verbose,
                      update,
                      out_file,
                      new_state_name: str = None):
        prev_prediction = -1
        self.net.reset_state()
        if new_state_name is None:
            new_state_name = random.choice(self.exercises)
        self.at.set_exercise_string(new_state_name)
        self.at.memory.reset_memory(self.at.exercise)
        self.at.initialize_am()

        u = "start"
        if verbose == True:
            print("\n*******************\nÄUßERUNGSTYP: ",
                  self.at.automaton.get_utterance_type(u))

        action_mask = self.at.am
        u_emb = self.emb.encode(u)  # HIER
        u_bow = self.bow_enc.encode(u)  # HIER
        features = np.concatenate((u_emb, u_bow, action_mask), axis=0)
        # forward
        prediction = self.net.forward(features,
                                      action_mask,
                                      self.other_da,
                                      print_top=True)
        self.at.automaton.current_state, response = self.at.walk(u, prediction)
        prev_prediction = prediction

        if verbose == True:
            print("AKTUELLER ZUSTAND: ", self.at.automaton.current_state.name,
                  "\nDIALOGAKT: ", self.other_da[prediction],
                  "\n*******************\n"
                  )  # print("CURRENT Exercise: ", self.at.exercise)

        # self.net.train_step(features, prediction, action_mask)
        # response = self.at.get_text(prediction)
        self.send(response, self.at.automaton.get_utterance_type(u),
                  self.at.automaton.current_state.name,
                  self.at.dialog_acts[prediction])  # print('>>', response)
        if out_file:
            out_file.write(u + '\t' + response + '\t' +
                           self.other_da[prediction] + '\n')
        return prev_prediction

    def interact(self, verbose, update, write_to_file):
        print(
            "How do you do? I'm glad you're here. Let's do some exercises together."
        )
        # open file to write around here
        # only if write_to_file !
        with open('data/dialogs_from_interaction', 'a') as out:
            with open("data/utterances_from_interaction", "a") as uttout:
                self.start_processing_requests(verbose)
                out_file = None
                if write_to_file:
                    out_file = out
                prev_prediction = self.interact_anew(verbose, update, out_file)
                # begin interaction loop
                while True:
                    if verbose == True:
                        print([
                            self.other_da[i] for i in range(len(self.at.am))
                            if self.at.am[i] == 1
                        ])
                    #print("prediction: ",self.at.dialog_acts[prediction])
                    #print("response: ",response)

                    # get input from user; utterance isn't saved!
                    message = self.receive()  # u = input(':: ')
                    u = message.data.strip()
                    print(":: %s" % (u))

                    # check if user wants to begin new session
                    if u == 'clear' or u == 'reset' or u == 'restart' or u == 'von vorne' or u == 'neustart':
                        if write_to_file:
                            out.write("WARNING: Interaction was reset.\n\n")
                        prev_prediction = self.interact_anew(
                            verbose, update, out_file)
                        if write_to_file:
                            uttout.write(
                                u + "\t" +
                                self.at.automaton.get_utterance_type(u) + "\n")

                    elif self.other_da[prev_prediction] in [
                            "closing", "finish"
                    ]:
                        if write_to_file:
                            out.write('\n')
                        prev_prediction = self.interact_anew(
                            verbose, update, out_file)

                    # check for exit command
                    elif u == 'exit' or u == 'quit':

                        if update == True:
                            self.net.save()
                        self.send(
                            'Ok, wir brechen ab. Bis zum nächsten Mal!',
                            'EXIT COMMAND',
                            self.at.automaton.current_state.name, "UNKNOWN"
                        )  # print('>> Ok, wir brechen ab. Bis zum nächsten Mal!')
                        if write_to_file:
                            out.write("WARNING: Dialog may not be finished.\n")
                        break

                    else:
                        if u == "\n" or u == "":
                            u = '<SILENCE>'
                        #self.at.reset_action_mask()

                        if self.at.automaton.current_state.name == "all_one":
                            if verbose == True:
                                print("\n*******************\nÄUßERUNGSTYP: ",
                                      self.at.automaton.get_utterance_type(u))
                            ##print(self.at.automaton.current_state.name, self.at.dialog_acts[prev_prediction])
                        else:
                            if verbose == True:
                                print("\n*******************\nÄUßERUNGSTYP: ",
                                      self.at.automaton.get_utterance_type(u))
                        action_mask = self.at.am
                        u_emb = self.emb.encode(u)  #HIER
                        u_bow = self.bow_enc.encode(u)  #HIER
                        features = np.concatenate((u_emb, u_bow, action_mask),
                                                  axis=0)
                        # forward

                        prediction = self.net.forward(features,
                                                      action_mask,
                                                      self.other_da,
                                                      print_top=True)
                        self.at.automaton.current_state, response = self.at.walk(
                            u, prediction)
                        if prediction != "all_one":
                            prev_prediction = prediction

                        #self.at.memory.update(prediction)
                        if verbose == True:
                            print(
                                "AKTUELLER ZUSTAND: ",
                                self.at.automaton.current_state.name,
                                "\nDIALOGAKT: ", self.other_da[prediction],
                                "\n*******************\n"
                            )  #print("CURRENT Exercise: ", self.at.exercise)

                        self.net.train_step(features, prediction, action_mask)
                        self.send(response,
                                  self.at.automaton.get_utterance_type(u),
                                  self.at.automaton.current_state.name,
                                  self.at.dialog_acts[prediction]
                                  )  # print('>>', response)
                        if write_to_file:
                            out.write(u + '\t' + response + '\t' +
                                      self.other_da[prediction] + '\n')
                            uttout.write(
                                u + "\t" +
                                self.at.automaton.get_utterance_type(u) + "\n")
                if write_to_file:
                    out.write('\n')
                self.stop_processing_requests()