def get_active_loop_name(state: State) -> Optional[Text]: """Get the name of current active loop. Args: state: The state from which the name of active loop should be extracted Return: the name of active loop or None """ if ( not state.get(ACTIVE_LOOP) or state[ACTIVE_LOOP].get(LOOP_NAME) == SHOULD_NOT_BE_SET ): return return state[ACTIVE_LOOP].get(LOOP_NAME)
def _is_rule_applicable(self, rule_key: Text, turn_index: int, conversation_state: State) -> bool: """Check if rule is satisfied with current state at turn. Args: rule_key: the textual representation of learned rule turn_index: index of a current dialogue turn conversation_state: the state that corresponds to turn_index Returns: a boolean that says whether the rule is applicable to current state """ # turn_index goes back in time reversed_rule_states = list(reversed( self._rule_key_to_state(rule_key))) # the rule must be applicable because we got (without any applicability issues) # further in the conversation history than the rule's length if turn_index >= len(reversed_rule_states): return True # a state has previous action if and only if it is not a conversation start # state current_previous_action = conversation_state.get(PREVIOUS_ACTION) rule_previous_action = reversed_rule_states[turn_index].get( PREVIOUS_ACTION) # current conversation state and rule state are conversation starters. # any slots with initial_value set will necessarily be in both states and don't # need to be checked. if not rule_previous_action and not current_previous_action: return True # current rule state is a conversation starter (due to conversation_start: true) # but current conversation state is not. # or # current conversation state is a starter # but current rule state is not. if not rule_previous_action or not current_previous_action: return False # check: current rule state features are present in current conversation state return self._does_rule_match_state(reversed_rule_states[turn_index], conversation_state)
def get_active_loop_name( state: State, ) -> Optional[Text]: """Get the name of current active loop. Args: state: The state from which the name of active loop should be extracted Return: the name of active loop or None """ if ( not state.get(ACTIVE_LOOP) or state[ACTIVE_LOOP].get(LOOP_NAME) == SHOULD_NOT_BE_SET ): return None # FIXME: better type annotation for `State` would require # a larger refactoring (e.g. switch to dataclass) return cast(Optional[Text], state[ACTIVE_LOOP].get(LOOP_NAME))
def _does_rule_match_state(rule_state: State, conversation_state: State) -> bool: for state_type, rule_sub_state in rule_state.items(): conversation_sub_state = conversation_state.get(state_type, {}) for key, value in rule_sub_state.items(): if isinstance(value, list): # json dumps and loads tuples as lists, # so we need to convert them back value = tuple(value) if ( # value should be set, therefore # check whether it is the same as in the state value and value != SHOULD_NOT_BE_SET and conversation_sub_state.get(key) != value ) or ( # value shouldn't be set, therefore # it should be None or non existent in the state value == SHOULD_NOT_BE_SET and conversation_sub_state.get(key)): return False return True
def _prev_action_listen_in_state(state: State) -> bool: prev_action_name = state.get(PREVIOUS_ACTION, {}).get(ACTION_NAME) return prev_action_name == ACTION_LISTEN_NAME
def _get_active_form_name( state: State, ) -> Optional[Union[Text, Tuple[Union[float, Text]]]]: return state.get(ACTIVE_LOOP, {}).get(LOOP_NAME)
def _expected_but_missing_slots(fingerprint: Dict[Text, List[Text]], state: State) -> Set[Text]: expected_slots = set(fingerprint.get(SLOTS, {})) current_slots = set(state.get(SLOTS, {}).keys()) # report all slots that are expected but aren't set in current slots return expected_slots.difference(current_slots)
def _is_rule_snippet_state(state: State) -> bool: prev_action_name = state.get(PREVIOUS_ACTION, {}).get(ACTION_NAME) return prev_action_name == RULE_SNIPPET_ACTION_NAME
def _is_prev_action_unlikely_intent_in_state(state: State) -> bool: prev_action_name = state.get(PREVIOUS_ACTION, {}).get(ACTION_NAME) return prev_action_name == ACTION_UNLIKELY_INTENT_NAME