Пример #1
0
    def handle_match_found(self, agent_action: DialogAction):
        # If intent is match_found then fill the action informs with the matches informs (if there is a match)
        assert agent_action.inform_slots is None
        db_results = self.db_helper.get_db_results(self.current_informs)
        if db_results:
            item_idx, item = list(db_results.items())[0]
            agent_action.inform_slots = copy.deepcopy(item)
            agent_action.inform_slots[self.match_key] = str(item_idx)
        else:
            agent_action.inform_slots = {self.match_key: "no match available"}

        value = agent_action.inform_slots[self.match_key]
        self.current_informs[self.match_key] = value
Пример #2
0
    def _return_init_action(self):
        self.state.intent = "request"

        if self.goal.inform_slots:
            # Pick all the required init. informs, and add if they exist in goal inform slots
            for inform_key in self.init_informs:
                if inform_key in self.goal.inform_slots:
                    self.state.inform_slots[inform_key] = self.goal.inform_slots[
                        inform_key
                    ]
                    self.state.rest_slots.pop(inform_key)
                    self.state.history_slots[inform_key] = self.goal.inform_slots[
                        inform_key
                    ]
            # If nothing was added then pick a random one to add
            if not self.state.inform_slots:
                key, value = random.choice(list(self.goal.inform_slots.items()))
                self.state.inform_slots[key] = value
                self.state.rest_slots.pop(key)
                self.state.history_slots[key] = value

        req_key = self.get_request_key()
        self.state.request_slots[req_key] = "UNK"

        user_response = DialogAction(
            self.state.intent,
            self.state.inform_slots,
            self.state.request_slots,
            speaker=USER,
        )

        return user_response
Пример #3
0
    def infuse_error(self, action: DialogAction):
        """
        Takes a semantic frame/action as a dict and adds 'error'.

        Given a dict/frame it adds error based on specifications in constants. It can either replace slot values,
        replace slot and its values, delete a slot or do all three. It can also randomize the intent.

        Parameters:
            frame (dict): format dict('intent': '', 'inform_slots': {}, 'request_slots': {}, 'round': int,
                          'speaker': 'User')
        """

        informs_dict = action.inform_slots
        for key in list(action.inform_slots.keys()):
            assert key in self.slot2values
            if random.random() < self.slot_error_prob:
                if self.slot_error_mode == 0:  # replace the slot_value only
                    self._slot_value_noise(key, informs_dict)
                elif self.slot_error_mode == 1:  # replace slot and its values
                    self._slot_noise(key, informs_dict)
                elif self.slot_error_mode == 2:  # delete the slot
                    self._slot_remove(key, informs_dict)
                else:  # Combine all three
                    rand_choice = random.random()
                    if rand_choice <= 0.33:
                        self._slot_value_noise(key, informs_dict)
                    elif rand_choice > 0.33 and rand_choice <= 0.66:
                        self._slot_noise(key, informs_dict)
                    else:
                        self._slot_remove(key, informs_dict)
        if random.random() < self.intent_error_prob:  # add noise for intent level
            action.intent = random.choice(self.intents)
Пример #4
0
    def _rule_action(self) -> int:

        if self.rule_current_slot_index < len(RULE_REQUESTS):
            slot = RULE_REQUESTS[self.rule_current_slot_index]
            self.rule_current_slot_index += 1
            rule_response = DialogAction("request",
                                         request_slots={slot: "UNK"})
        elif self.rule_phase == "not done":
            rule_response = DialogAction("match_found")
            self.rule_phase = "done"
        elif self.rule_phase == "done":
            rule_response = DialogAction("done")
        else:
            raise Exception("Should not have reached this clause")

        index = map_action_to_index(rule_response)
        return index
Пример #5
0
    def update_state_user(self, user_action: DialogAction):

        for key, value in user_action.inform_slots.items():
            self.current_informs[key] = value

        user_action.turn = self.round_num
        self.history.append(user_action)
        self.round_num += 1
Пример #6
0
    def update_state_agent(self, agent_action: DialogAction):

        if agent_action.intent == "inform":
            self.handle_inform_with_db_query(agent_action)
        elif agent_action.intent == "match_found":
            self.handle_match_found(agent_action)

        agent_action.turn = self.round_num
        self.history.append(agent_action)
Пример #7
0
 def handle_inform_with_db_query(self, agent_action: DialogAction):
     assert agent_action.inform_slots
     slot_name = list(agent_action.inform_slots.keys())[0]
     value = self.db_helper.get_inform_value(slot_name,
                                             self.current_informs)
     agent_action.inform_slots = {slot_name: value}
     key, value = list(agent_action.inform_slots.items())[0]  # Only one
     assert key != "match_found"
     assert value != "PLACEHOLDER", "KEY: {}".format(key)
     self.current_informs[key] = value
Пример #8
0
    def step(self, agent_action: DialogAction):

        self.validate_action(agent_action)

        self.state.inform_slots.clear()
        self.state.intent = ""

        done = False
        success = NO_OUTCOME
        # First check round num, if equal to max then fail
        if agent_action.turn == self.max_round:
            done = True
            success = FAIL
            self.state.intent = "done"
            self.state.request_slots.clear()
        else:
            agent_intent = agent_action.intent
            if agent_intent == "request":
                self._response_to_request(agent_action)
            elif agent_intent == "inform":
                self._response_to_inform(agent_action)
            elif agent_intent == "match_found":
                self._response_to_match_found(agent_action.inform_slots)
            elif agent_intent == "done":
                success = self._response_to_done()
                self.state.intent = "done"
                self.state.request_slots.clear()
                done = True

        self.validate_state(self.state)

        user_response = DialogAction(
            self.state.intent,
            self.state.inform_slots,
            self.state.request_slots,
            speaker=USER,
        )

        reward = reward_function(
            success, self.max_round
        )  # TODO(tilo): reward-calculation must not be done by user!

        return user_response, reward, done, True if success is 1 else False