def _create_loop_unhappy_lookup_from_states( self, trackers_as_states: List[List[State]], trackers_as_actions: List[List[Text]], ) -> Dict[Text, Text]: """Creates lookup dictionary from the tracker represented as states. Args: trackers_as_states: representation of the trackers as a list of states trackers_as_actions: representation of the trackers as a list of actions Returns: lookup dictionary """ lookup = {} for states, actions in zip(trackers_as_states, trackers_as_actions): action = actions[0] active_loop = get_active_loop_name(states[-1]) # even if there are two identical feature keys # their loop will be the same if not active_loop: continue states = self._states_for_unhappy_loop_predictions(states) feature_key = self._create_feature_key(states) if not feature_key: continue # Since rule snippets and stories inside the loop contain # only unhappy paths, notify the loop that # it was predicted after an answer to a different question and # therefore it should not validate user input if ( # loop is predicted after action_listen in unhappy path, # therefore no validation is needed is_prev_action_listen_in_state(states[-1]) and action == active_loop ): lookup[feature_key] = DO_NOT_VALIDATE_LOOP elif ( # some action other than action_listen and active_loop # is predicted in unhappy path, # therefore active_loop shouldn't be predicted by the rule not is_prev_action_listen_in_state(states[-1]) and action not in {ACTION_LISTEN_NAME, active_loop} ): lookup[feature_key] = DO_NOT_PREDICT_LOOP_ACTION return lookup
def encode_state( self, state: State, interpreter: NaturalLanguageInterpreter ) -> Dict[Text, List["Features"]]: """Encode the given state with the help of the given interpreter. Args: state: The state to encode interpreter: The interpreter used to encode the state Returns: A dictionary of state_type to list of features. """ state_features = {} for state_type, sub_state in state.items(): if state_type == PREVIOUS_ACTION: state_features.update( self._extract_state_features(sub_state, interpreter, sparse=True) ) # featurize user only if it is "real" user input, # i.e. input from a turn after action_listen if state_type == USER and is_prev_action_listen_in_state(state): state_features.update( self._extract_state_features(sub_state, interpreter, sparse=True) ) if sub_state.get(ENTITIES): state_features[ENTITIES] = self._create_features( sub_state, ENTITIES, sparse=True ) if state_type in {SLOTS, ACTIVE_LOOP}: state_features[state_type] = self._create_features( sub_state, state_type, sparse=True ) return state_features
def encode_state( self, state: State, precomputations: Optional[MessageContainerForCoreFeaturization], ) -> Dict[Text, List[Features]]: """Encode the given state. Args: state: The state to encode precomputations: Contains precomputed features and attributes. Returns: A dictionary of state_type to list of features. """ state_features = {} for state_type, sub_state in state.items(): if state_type == PREVIOUS_ACTION: state_features.update( self._extract_state_features( sub_state, precomputations=precomputations, sparse=True, ) ) # featurize user only if it is "real" user input, # i.e. input from a turn after action_listen if state_type == USER and is_prev_action_listen_in_state(state): state_features.update( self._extract_state_features( sub_state, precomputations=precomputations, sparse=True, ) ) if sub_state.get(ENTITIES): state_features[ENTITIES] = self._create_features( sub_state, ENTITIES, sparse=True ) if state_type in {SLOTS, ACTIVE_LOOP}: state_features[state_type] = self._create_features( sub_state, state_type, sparse=True ) return state_features
def _choose_last_user_input(self, trackers_as_states: List[List[State]], use_text_for_last_user_input: bool) -> None: for states in trackers_as_states: last_state = states[-1] # only update the state of the real user utterance if not is_prev_action_listen_in_state(last_state): continue if use_text_for_last_user_input: # remove intent features to only use text if last_state.get(USER, {}).get(INTENT): del last_state[USER][INTENT] # don't add entities if text is used for featurization if last_state.get(USER, {}).get(ENTITIES): del last_state[USER][ENTITIES] else: # remove text features to only use intent if last_state.get(USER, {}).get(TEXT): del last_state[USER][TEXT] # make sure that all dialogue steps are either intent or text based self._remove_user_text_if_intent(trackers_as_states)