def programy_post_formatter_dialog(dialog: Dict) -> Dict: # Used by: program_y, program_y_dangerous, program_y_wide # Look at skills/program_y* dialog = get_last_n_turns(dialog, bot_last_turns=6) first_uttr_hi = False if len(dialog["human_utterances"] ) == 1 and not if_chat_about_particular_topic( dialog["human_utterances"][-1]): first_uttr_hi = True dialog = remove_clarification_turns_from_dialog(dialog) dialog = last_n_human_utt_dialog_formatter(dialog, last_n_utts=5)[0] sentences = dialog["sentences_batch"][0] intents = dialog["intents"][0] # modify sentences with yes/no intents to yes/no phrase # todo: sent may contain multiple sentence, logic here could be improved prioritized_intents = service_intents - {"yes", "no"} for i, (sent, ints) in enumerate(zip(sentences, intents)): ints = set(ints) if "?" not in sent and len(ints & prioritized_intents) == 0: if "yes" in ints: sentences[i] = "yes." elif "no" in ints: sentences[i] = "no." if first_uttr_hi: sentences = ["hi."] return {"sentences_batch": [sentences]}
def chat_about_weather_condition(ctx: Context, actor: Actor, *args, **kwargs) -> bool: human_utter = get_last_human_utterance(ctx, actor) bot_utter = get_last_bot_utterance(ctx, actor) return bool( if_chat_about_particular_topic( human_utter, bot_utter, compiled_pattern=WEATHER_COMPILED_PATTERN))
def lets_talk_about_request(vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) have_pets = re.search(HAVE_LIKE_PETS_TEMPLATE, user_uttr["text"]) found_prompt = any([ phrase.lower() in bot_uttr["text"].lower() for phrase in TRIGGER_PHRASES ]) isno = is_no(user_uttr) is_stop = re.findall(r"(stop|shut|something else|change|don't want)", user_uttr["text"]) chat_about = if_chat_about_particular_topic( user_uttr, bot_uttr, compiled_pattern=ANIMALS_FIND_TEMPLATE) find_pattern = re.findall(ANIMALS_FIND_TEMPLATE, user_uttr["text"]) dont_like = re.findall(NOT_LIKE_PATTERN, user_uttr["text"]) was_prev_active = if_was_prev_active(vars) if chat_about and find_pattern: flag = True if not dont_like and (have_pets or (find_pattern and (not is_last_state(vars, "SYS_WHAT_ANIMALS") or not was_prev_active)) or (found_prompt and not isno and not is_stop)): flag = True if re.findall(NOT_SWITCH_TEMPLATE, user_uttr["text"]): flag = False logger.info(f"lets_talk_about_request={flag}") return flag
def ask_if_user_thinks_that_gaming_is_unhealthy_response(vars): response = ( "It is known that people who play computer games too much can have health problems, " "both physical and emotional. Do you agree?") human_uttr = state_utils.get_last_human_utterance(vars) entities = get_entities(human_uttr, only_named=True) logger.info( f"(ask_if_user_thinks_that_gaming_is_unhealthy_response)entities: {entities}" ) bot_text = state_utils.get_last_bot_utterance(vars).get("text", "").lower() flags_set = False if not if_chat_about_particular_topic( human_uttr, compiled_pattern=VIDEO_GAME_WORDS_COMPILED_PATTERN): flags_set, response = common_nlg.maybe_set_confidence_and_continue_based_on_previous_bot_phrase( vars, bot_text, response) if not flags_set: if entities: state_utils.set_confidence( vars, confidence=common_nlg.CONF_092_CAN_CONTINUE) state_utils.set_can_continue( vars, continue_flag=common_constants.CAN_CONTINUE_SCENARIO) else: state_utils.set_confidence(vars, confidence=common_nlg.CONF_1) state_utils.set_can_continue( vars, continue_flag=common_constants.MUST_CONTINUE) return response
def user_maybe_wants_to_talk_about_particular_game_request(ngrams, vars): user_uttr = state_utils.get_last_human_utterance(vars) user_text = user_uttr.get("text", "").lower() bot_text = state_utils.get_last_bot_utterance(vars).get("text", "").lower() game_names_from_local_list_of_games = find_games_in_text( user_text) + find_games_in_text(bot_text) if game_names_from_local_list_of_games: if does_text_contain_link_to_gaming(bot_text): logger.info("performing additional check") flag = False elif common_intents.switch_to_particular_game_discussion(vars): assert ( game_names_from_local_list_of_games ), "At least one game should have been found in function `switch_to_particular_game_discussion()`" possible_game_name = game_names_from_local_list_of_games[0][0] flag = (not any([ n.lower() in possible_game_name.lower() for n in WORDS_THAT_ARE_DEFINITELY_GAME_NAMES ]) and not does_text_contain_video_game_words( user_text ) and not does_text_contain_link_to_gaming(bot_text) and ( not was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) or was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) and if_chat_about_particular_topic( user_uttr, compiled_pattern= GAMES_WITH_AT_LEAST_1M_COPIES_SOLD_COMPILED_PATTERN))) else: flag = False else: flag = False logger.info( f"user_maybe_wants_to_talk_about_particular_game_request={flag}") return flag
def is_lets_chat_about_topic_human_initiative(ctx: Context, actor: Actor) -> bool: flag = universal_templates.if_chat_about_particular_topic( int_ctx.get_last_human_utterance(ctx, actor), int_ctx.get_last_bot_utterance(ctx, actor)) logger.debug(f"is_lets_chat_about_topic_human_initiative = {flag}") return bool(flag)
def user_mentioned_games_as_his_interest_request(ngrams, vars, first_time=True): user_uttr = state_utils.get_last_human_utterance(vars) user_text = user_uttr.get("text", "").lower() bot_text = state_utils.get_last_bot_utterance(vars).get("text", "").lower() game_names_from_local_list_of_games = find_games_in_text( user_text) + find_games_in_text(bot_text) flag = ( not game_names_from_local_list_of_games and common_intents.switch_to_general_gaming_discussion(vars) and not user_doesnt_like_gaming_request(ngrams, vars) and not user_didnt_name_game_after_question_about_games_and_didnt_refuse_to_discuss_request( ngrams, vars) and (first_time and ANSWER_TO_GENERAL_WISH_TO_DISCUSS_VIDEO_GAMES_AND_QUESTION_WHAT_GAME_YOU_PLAY not in bot_text or not first_time and ANSWER_TO_GENERAL_WISH_TO_DISCUSS_VIDEO_GAMES_AND_QUESTION_WHAT_GAME_YOU_PLAY in bot_text) and (not was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) or was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) and if_chat_about_particular_topic( user_uttr, compiled_pattern=VIDEO_GAME_WORDS_COMPILED_PATTERN))) logger.info(f"user_mentioned_games_as_his_interest_request={flag}") return flag
def start_condition(ctx: Context, actor: Actor) -> bool: return if_chat_about_particular_topic( ctx.misc.get("agent", {}).get("dialog", {}).get("human_utterances", [{}])[-1], ctx.misc.get("agent", {}).get("dialog", {}).get("bot_utterances", [{}])[-1], compiled_pattern=BOOK_PATTERN, )
def set_start_confidence(ctx: Context, actor: Actor) -> Context: user_uttr = int_ctx.get_last_human_utterance(ctx, actor) bot_uttr = int_ctx.get_last_bot_utterance(ctx, actor) if if_chat_about_particular_topic(user_uttr, bot_uttr, compiled_pattern=ART_PATTERN): int_ctx.set_confidence(ctx, actor, SUPER_CONFIDENCE) elif re.findall(ART_PATTERN, user_uttr["text"]): int_ctx.set_confidence(ctx, actor, HIGH_CONFIDENCE) return ctx
def which_topic_lets_chat_about(last_user_uttr, last_bot_uttr): for topic in TOPIC_PATTERNS: if if_chat_about_particular_topic( last_user_uttr, last_bot_uttr, compiled_pattern=TOPIC_PATTERNS[topic]): return topic return None
def lets_talk_about(vars, compiled_pattern): flag = False user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) chat_about = if_chat_about_particular_topic( user_uttr, bot_uttr, compiled_pattern=compiled_pattern) if chat_about: flag = True return flag
def if_chat_about_science_topic_pattern( vars, compiled_pattern=SCIENCE_COMPILED_PATTERN): uttr = state_utils.get_last_human_utterance(vars) prev_uttr = state_utils.get_last_bot_utterance(vars) prev_uttr = {} if prev_uttr is None else prev_uttr flag = if_chat_about_particular_topic(uttr, prev_uttr, compiled_pattern=compiled_pattern) return bool(flag)
def lets_talk_about_request(ngrams, vars): user_lets_chat_about_music = if_chat_about_particular_topic( state_utils.get_last_human_utterance(vars), state_utils.get_last_bot_utterance(vars), compiled_pattern=music_words_re, ) flag = bool(user_lets_chat_about_music) logger.info(f"lets_talk_about_request {flag}") return flag
def confess_bot_never_played_game_and_ask_user_response( vars, candidate_game_id_is_already_set, did_user_play=False, how_long_user_played=False): if not (isinstance(did_user_play, bool) and isinstance(how_long_user_played, bool) and did_user_play + how_long_user_played == 1): raise ValueError( f"One of parameters `did_user_play` and `how_long_user_played` has to be `True` and the other" f"has to be `False`. did_user_play={did_user_play}, how_long_user_played={how_long_user_played}" ) gaming_memory.set_current_igdb_game_id_if_game_for_discussion_is_identified( vars, candidate_game_id_is_already_set) game = gaming_memory.get_current_igdb_game(vars, assert_not_empty=False) if game is None: logger.warning( "No appropriate igdb game description were found. Game description could be filtered because it lacked " "required keys. Another cause possible cause of this situation is that local igdb saved search results " "do not have detected game. In such a case you should update local copy of igdb.com search results." ) response = error_response(vars) state_utils.set_confidence(vars, confidence=common_nlg.CONF_0) state_utils.set_can_continue( vars, continue_flag=common_constants.CAN_NOT_CONTINUE) else: if "genres" not in game or not game["genres"]: logger.warning(f"No genre for game '{game['name']}'.") genres = "" elif len(game["genres"]) == 1: genres = IGDB_GAME_GENRES_FOR_REPLICAS[game["genres"][0]] else: genres = ( f"{IGDB_GAME_GENRES_FOR_REPLICAS[game['genres'][0]]} " f"and {IGDB_GAME_GENRES_FOR_REPLICAS[game['genres'][1]]}") response = f"I've heard it is a cool {genres}. Unfortunately, I haven't tried it out. " if did_user_play: response += f"Have you ever played {game['name']}?" elif how_long_user_played: response += f"When did you start to play {game['name']}?" else: assert False bot_text = state_utils.get_last_bot_utterance(vars).get("text", "").lower() human_uttr = state_utils.get_last_human_utterance(vars) flags_set = False if not if_chat_about_particular_topic( human_uttr, compiled_pattern= GAMES_WITH_AT_LEAST_1M_COPIES_SOLD_COMPILED_PATTERN): flags_set, response = common_nlg.maybe_set_confidence_and_continue_based_on_previous_bot_phrase( vars, bot_text, response) if not flags_set: state_utils.set_confidence(vars, confidence=common_nlg.CONF_1) state_utils.set_can_continue( vars, continue_flag=common_constants.MUST_CONTINUE) return response
def if_must_switch(user_uttr, bot_uttr): flag = False user_uttr_annotations = user_uttr["annotations"] lets_chat = if_chat_about_particular_topic(user_uttr, bot_uttr) found_entity_substr_wp, *_, conf_type_wp = find_entity_wp( user_uttr_annotations, bot_uttr) found_entity_substr_nphr, conf_type_nphr = find_entity_nounphr( user_uttr_annotations) if (lets_chat and (found_entity_substr_wp or found_entity_substr_nphr) and (conf_type_wp == "SURE_WIKI_TYPE" or conf_type_nphr == "WIKI_TOPIC")): flag = True return flag
def lets_chat_about_movies(uttr, prev_uttr=None): prev_uttr = {} if prev_uttr is None else prev_uttr curr_uttr_is_about_movies = re.search(MOVIE_PATTERN, uttr.get("text", "").lower()) lets_talk_about_movies = if_chat_about_particular_topic( uttr, prev_uttr, compiled_pattern=MOVIE_PATTERN) chosed_topic = if_choose_topic(uttr, prev_uttr) and curr_uttr_is_about_movies if (lets_talk_about_movies or chosed_topic or ("?" not in uttr.get("text", "") and "?" in prev_uttr.get("text", "") and curr_uttr_is_about_movies)): return True else: return False
def user_wants_to_discuss_minecraft_request(ngrams, vars): flag = (user_definitely_wants_to_talk_about_particular_game_request( ngrams, vars, additional_check=is_minecraft_mentioned_in_user_or_bot_uttr, ) or user_definitely_wants_to_talk_about_game_that_user_played_request( ngrams, vars, additional_check=is_minecraft_mentioned_in_user_or_bot_uttr) or was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) and if_chat_about_particular_topic( state_utils.get_last_human_utterance(vars), key_words=["minecraft"])) logger.info(f"user_wants_to_discuss_minecraft_request={flag}") return flag
def ask_what_game_user_likes_response(vars): response = ANSWER_TO_GENERAL_WISH_TO_DISCUSS_VIDEO_GAMES_AND_QUESTION_WHAT_GAME_YOU_PLAY bot_text = state_utils.get_last_bot_utterance(vars).get("text", "").lower() human_uttr = state_utils.get_last_bot_utterance(vars) flags_set = False if not if_chat_about_particular_topic( human_uttr, compiled_pattern=GAMES_WITH_AT_LEAST_1M_COPIES_SOLD_COMPILED_PATTERN ): flags_set, response = common_nlg.maybe_set_confidence_and_continue_based_on_previous_bot_phrase( vars, bot_text, response) if not flags_set: state_utils.set_confidence(vars, confidence=common_nlg.CONF_1) state_utils.set_can_continue( vars, continue_flag=common_constants.MUST_CONTINUE) return response
def switch_wiki_skill_on_news(user_uttr, bot_uttr): user_uttr_annotations = user_uttr["annotations"] news = user_uttr_annotations.get("news_api_annotator", []) if if_chat_about_particular_topic(user_uttr, bot_uttr) and news: nounphrases = user_uttr_annotations.get("cobot_entities", {}).get( "labelled_entities", []) if nounphrases and news: for nounphr in nounphrases: for elem in news: if (elem["entity"] == nounphr["text"] and "Q5" in find_entity_types( elem["entity"], user_uttr_annotations) and nounphr["text"] not in badlist_words and nounphr["text"] not in prohibited_topics): return True return False
def get_intents_flags(utt): special_intents = [ "cant_do", "repeat", "weather_forecast_intent", "what_are_you_talking_about", "what_can_you_do", "what_is_your_job", "what_is_your_name", "what_time", "where_are_you_from", "who_made_you", ] detected_intents = get_intents(utt, which="intent_catcher") lets_chat_about_flag = if_chat_about_particular_topic(utt) special_intents_flag = any( [si in detected_intents for si in special_intents]) return lets_chat_about_flag, special_intents_flag
def is_about_movies(uttr, prev_uttr=None): prev_uttr = {} if prev_uttr is None else prev_uttr curr_uttr_is_about_movies = re.search(MOVIE_PATTERN, uttr.get("text", "").lower()) prev_uttr_last_sent = prev_uttr.get("annotations", {}).get("sentseg", {}).get("segments", [""])[-1].lower() prev_uttr_is_about_movies = re.search(MOVIE_PATTERN, prev_uttr_last_sent) lets_talk_about_movies = if_chat_about_particular_topic( uttr, prev_uttr, compiled_pattern=MOVIE_PATTERN) chosed_topic = if_choose_topic(uttr, prev_uttr) and curr_uttr_is_about_movies if (lets_talk_about_movies or chosed_topic or curr_uttr_is_about_movies or ("?" in prev_uttr_last_sent and prev_uttr_is_about_movies)): return True else: return False
def check_switch(vars, topic_config): user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) shared_memory = state_utils.get_shared_memory(vars) found_topic = shared_memory.get("special_topic", "") first_utt = False utt_can_continue = "can" utt_conf = 0.0 shared_memory = state_utils.get_shared_memory(vars) for topic in topic_config: linkto = topic_config[topic].get("linkto", []) for phrase in linkto: if phrase.lower() in bot_uttr["text"].lower(): found_topic = topic first_utt = True break pattern = topic_config[topic].get("pattern", "") if pattern: if if_chat_about_particular_topic(user_uttr, bot_uttr, compiled_pattern=pattern): utt_can_continue = "must" utt_conf = 1.0 found_topic = topic first_utt = True elif re.findall(pattern, user_uttr["text"]) and not found_topic: utt_can_continue = "prompt" utt_conf = 0.95 found_topic = topic first_utt = True switch_on = topic_config[topic].get("switch_on", []) for switch_elem in switch_on: condition = switch_elem["cond"] if check_condition(condition, user_uttr, bot_uttr, shared_memory): found_topic = topic utt_can_continue = switch_elem.get("can_continue", "can") utt_conf = switch_elem.get("conf", utt_conf) first_utt = True break if found_topic: break return found_topic, first_utt, utt_can_continue, utt_conf
def ask_user_when_he_started_to_play_minecraft_response( vars, candidate_game_id_is_already_set): shared_memory_ops.set_current_igdb_game_id_if_game_for_discussion_is_identified( vars, candidate_game_id_is_already_set) response = ( "Perfect taste! Minecraft is the best game ever! I dived into the game right after I was created. " "And what about you? When did you start to play Minecraft?") human_uttr = state_utils.get_last_human_utterance(vars) bot_text = state_utils.get_last_bot_utterance(vars).get("text", "") state_utils.add_acknowledgement_to_response_parts(vars) flags_set = False if not if_chat_about_particular_topic( human_uttr, compiled_pattern=re.compile("minecraft", flags=re.I)): flags_set, response = common_nlg.maybe_set_confidence_and_continue_based_on_previous_bot_phrase( vars, bot_text, response) logger.info(f"flags_set: {flags_set}") if not flags_set: state_utils.set_confidence(vars, confidence=common_nlg.CONF_1) state_utils.set_can_continue( vars, continue_flag=common_constants.MUST_CONTINUE) return response
def lets_talk_about_check(vars): # user_lets_chat_about = ( # "lets_chat_about" in get_intents(state_utils.get_last_human_utterance(vars), which="intent_catcher") # or if_chat_about_particular_topic(state_utils.get_last_human_utterance(vars), prev_uttr) # ) human_utt = state_utils.get_last_human_utterance(vars) bot_utt = state_utils.get_last_bot_utterance(vars) # if "weather" in human_utt["text"].lower(): # flag = "" # logger.info(f"lets_talk_about_check {flag}, weather detected") # return flag if dont_want_talk(vars): flag = "" elif if_chat_about_particular_topic(human_utt, bot_utt, compiled_pattern=FOOD_WORDS_RE): flag = "if_chat_about_particular_topic" elif bool(re.search(FOOD_WORDS_RE, human_utt["text"])): flag = "FOOD_WORDS_RE" elif bool(re.search(FOOD_UTTERANCES_RE, bot_utt["text"])): flag = "FOOD_UTTERANCES_RE" elif bool(re.search(CUISINE_UTTERANCES_RE, bot_utt["text"])): flag = "CUISINE_UTTERANCES_RE" elif check_conceptnet(vars)[0]: flag = "check_conceptnet" elif bool(re.search(DONOTKNOW_LIKE_RE, human_utt["text"])): flag = "DONOTKNOW_LIKE_RE" else: flag = "" # user_lets_chat_about_food = any( # [ # bool(re.search(FOOD_WORDS_RE, human_utt["text"].lower())), # if_chat_about_particular_topic(human_utt, bot_utt, compiled_pattern=FOOD_WORDS_RE), # check_conceptnet(vars)[0], # bool(re.search(FOOD_SKILL_TRANSFER_PHRASES_RE, human_utt["text"].lower())), # bool(re.search(DONOTKNOW_LIKE_RE, human_utt["text"].lower())) # ] # ) # and (not state_utils.get_last_human_utterance(vars)["text"].startswith("what")) # flag = user_lets_chat_about_food logger.info(f"lets_talk_about_check {flag}") return flag
def user_definitely_wants_to_talk_about_game_that_user_played_request( ngrams, vars, additional_check=None): user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) game_names_from_local_list_of_games = find_games_in_text( user_uttr.get("text", "")) flag = ( bool(game_names_from_local_list_of_games) and does_text_contain_link_to_gaming(bot_uttr.get("text", "")) and additional_check(ngrams, vars) and (not was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) or was_link_from_gaming_to_other_skill_made_in_previous_bot_utterance( vars) and if_chat_about_particular_topic( user_uttr, compiled_pattern= GAMES_WITH_AT_LEAST_1M_COPIES_SOLD_COMPILED_PATTERN))) logger.info( f"user_definitely_wants_to_talk_about_game_that_user_played_and_bot_didnt_play with additional check " f"{common_intents.get_additional_check_description(additional_check)}: {flag}" ) return flag
def last_n_human_utt_dialog_formatter( dialog: Dict, last_n_utts: int, only_last_sentence: bool = False) -> List: """ Args: dialog (Dict): full dialog state last_n_utts (int): how many last user utterances to take only_last_sentence (bool, optional): take only last sentence in each utterance. Defaults to False. """ dialog = deepcopy(dialog) if len(dialog["human_utterances"] ) <= last_n_utts and not if_chat_about_particular_topic( dialog["human_utterances"][0]): # in all cases when not particular topic, convert first phrase in the dialog to `hello!` if "sentseg" in dialog["human_utterances"][0].get("annotations", {}): dialog["human_utterances"][0]["annotations"]["sentseg"][ "punct_sent"] = "hello!" dialog["human_utterances"][0]["annotations"]["sentseg"][ "segments"] = ["hello"] else: dialog["human_utterances"][0]["text"] = "hello" human_utts = [] detected_intents = [] for utt in dialog["human_utterances"][-last_n_utts:]: if "sentseg" in utt.get("annotations", {}): sentseg_ann = utt["annotations"]["sentseg"] if only_last_sentence: text = sentseg_ann["segments"][-1] if len( sentseg_ann["segments"]) > 0 else "" else: text = sentseg_ann["punct_sent"] else: text = utt["text"] human_utts += [text] detected_intents += [get_intents(utt, which="all")] return [{"sentences_batch": [human_utts], "intents": [detected_intents]}]
def if_switch_wiki_skill(user_uttr, bot_uttr): flag = False user_uttr_annotations = user_uttr["annotations"] found_entity_substr, found_entity_id, found_entity_types, conf_type_wp = find_entity_wp( user_uttr_annotations, bot_uttr) found_entity_substr, conf_type_nounphr = find_entity_nounphr( user_uttr_annotations) user_dont_know = if_user_dont_know_topic(user_uttr, bot_uttr) asked_name = "what is your name" in bot_uttr.get("text", "").lower() asked_news = "news" in user_uttr["text"] for topic, topic_info in topic_config.items(): pattern = topic_info.get("pattern", "") if ((isinstance(pattern, str) and re.findall(pattern, user_uttr["text"], re.IGNORECASE)) or (isinstance(pattern, re.Pattern) and re.findall(pattern, user_uttr["text"])) or if_chat_about_particular_topic( user_uttr, bot_uttr, compiled_pattern=pattern)): flag = True switch_on = topic_info.get("switch_on", []) for switch_elem in switch_on: condition = switch_elem["cond"] checked_condition = check_condition(condition, user_uttr, bot_uttr, {}) if checked_condition: flag = True break if (found_entity_id or found_entity_substr or user_dont_know) and not asked_name and not asked_news: flag = True all_confs = [(conf_type, CONF_DICT[conf_type]) for conf_type in [conf_type_wp, conf_type_nounphr]] all_confs = sorted(all_confs, key=lambda x: x[1], reverse=True) wiki_skill_conf_type = all_confs[0][0] return flag, wiki_skill_conf_type
async def send(self, payload: Dict, callback: Callable): st_time = time.time() try: dialog = payload["payload"]["states_batch"][0] skills_for_uttr = [] user_uttr = dialog["human_utterances"][-1] user_uttr_text = user_uttr["text"].lower() user_uttr_annotations = user_uttr["annotations"] bot_uttr = dialog["bot_utterances"][-1] if len( dialog["bot_utterances"]) else {} bot_uttr_text_lower = bot_uttr.get("text", "").lower() prev_active_skill = bot_uttr.get("active_skill", "") intent_catcher_intents = get_intents(user_uttr, probs=False, which="intent_catcher") high_priority_intent_detected = any([ k for k in intent_catcher_intents if k in high_priority_intents["dff_intent_responder_skill"] ]) low_priority_intent_detected = any([ k for k in intent_catcher_intents if k in low_priority_intents ]) detected_topics = set(get_topics(user_uttr, which="all")) is_factoid = get_factoid(user_uttr).get("is_factoid", 0.0) > 0.96 is_celebrity_mentioned = check_is_celebrity_mentioned(user_uttr) if_choose_topic_detected = if_choose_topic(user_uttr, bot_uttr) if_lets_chat_about_particular_topic_detected = if_chat_about_particular_topic( user_uttr, bot_uttr) dialog_len = len(dialog["human_utterances"]) exit_cond = "exit" in intent_catcher_intents and ( dialog_len == 1 or (dialog_len == 2 and len(user_uttr_text.split()) > 3)) repeat_cond = ("repeat" in intent_catcher_intents and prev_active_skill in UNPREDICTABLE_SKILLS and re.match(r"^what.?$", user_uttr_text)) cant_do_cond = ("cant_do" in intent_catcher_intents and "play" in user_uttr_text and any([ phrase in bot_uttr_text_lower for phrase in GREETING_QUESTIONS_TEXTS ])) for intent_name, condition in zip( ["exit", "repeat", "cant_do"], [exit_cond, repeat_cond, cant_do_cond]): if condition: high_priority_intent_detected = False not_detected = {"detected": 0, "confidence": 0.0} user_uttr["annotations"]["intent_catcher"][ intent_name] = not_detected dialog["utterances"][-1]["annotations"]["intent_catcher"][ intent_name] = not_detected if "/new_persona" in user_uttr_text: # process /new_persona command skills_for_uttr.append( "personality_catcher" ) # TODO: rm crutch of personality_catcher elif user_uttr_text == "/get_dialog_id": skills_for_uttr.append("dummy_skill") elif high_priority_intent_detected: # process intent with corresponding IntentResponder skills_for_uttr.append("dff_intent_responder_skill") elif is_sensitive_topic_and_request(user_uttr): # process user utterance with sensitive content, "safe mode" # adding open-domain skills without opinion expression skills_for_uttr.append("dff_program_y_dangerous_skill") skills_for_uttr.append("meta_script_skill") skills_for_uttr.append("personal_info_skill") skills_for_uttr.append("factoid_qa") skills_for_uttr.append("dff_grounding_skill") skills_for_uttr.append("dummy_skill") skills_for_uttr.append("small_talk_skill") if if_lets_chat_about_particular_topic_detected: skills_for_uttr.append("news_api_skill") if if_special_weather_turn_on(user_uttr, bot_uttr): skills_for_uttr.append("dff_weather_skill") if is_celebrity_mentioned: skills_for_uttr.append("dff_gossip_skill") # adding closed-domain skills skills_for_uttr += turn_on_skills( detected_topics, intent_catcher_intents, user_uttr_text, bot_uttr.get("text", ""), available_skills=[ "news_api_skill", "dff_coronavirus_skill", "dff_funfact_skill", "dff_weather_skill", "dff_short_story_skill", ], ) # adding linked-to skills skills_for_uttr.extend(get_linked_to_skills(dialog)) skills_for_uttr.extend(get_previously_active_skill(dialog)) else: # general case if low_priority_intent_detected: skills_for_uttr.append("dff_intent_responder_skill") # adding open-domain skills skills_for_uttr.append("dff_grounding_skill") skills_for_uttr.append("dff_program_y_skill") skills_for_uttr.append("personal_info_skill") skills_for_uttr.append("meta_script_skill") skills_for_uttr.append("dummy_skill") skills_for_uttr.append("dialogpt") # generative skill skills_for_uttr.append("small_talk_skill") skills_for_uttr.append("knowledge_grounding_skill") skills_for_uttr.append("convert_reddit") skills_for_uttr.append("comet_dialog_skill") skills_for_uttr.append("dff_program_y_wide_skill") # adding friendship only in the beginning of the dialog if len(dialog["utterances"]) < 20: skills_for_uttr.append("dff_friendship_skill") if if_choose_topic_detected or if_lets_chat_about_particular_topic_detected: skills_for_uttr.append("knowledge_grounding_skill") skills_for_uttr.append("news_api_skill") switch_wiki_skill, _ = if_switch_wiki_skill( user_uttr, bot_uttr) if switch_wiki_skill or switch_wiki_skill_on_news( user_uttr, bot_uttr): skills_for_uttr.append("dff_wiki_skill") if if_switch_test_skill(user_uttr, bot_uttr): skills_for_uttr.append("dff_art_skill") # adding factoidQA Skill if user utterance is factoid question if is_factoid: skills_for_uttr.append("factoid_qa") if "dummy_skill" in prev_active_skill and len( dialog["utterances"]) > 4: skills_for_uttr.append("dummy_skill_dialog") # if user mentions if is_celebrity_mentioned: skills_for_uttr.append("dff_gossip_skill") # some special cases if if_special_weather_turn_on(user_uttr, bot_uttr): skills_for_uttr.append("dff_weather_skill") if if_turn_on_emotion(user_uttr, bot_uttr): skills_for_uttr.append("emotion_skill") if get_named_locations(user_uttr): skills_for_uttr.append("dff_travel_skill") if extract_movies_names_from_annotations(user_uttr): skills_for_uttr.append("dff_movie_skill") # adding closed-domain skills skills_for_uttr += turn_on_skills( detected_topics, intent_catcher_intents, user_uttr_text, bot_uttr.get("text", ""), available_skills=[ "dff_art_skill", "dff_movie_skill", "dff_book_skill", "news_api_skill", "dff_food_skill", "dff_animals_skill", "dff_sport_skill", "dff_music_skill", "dff_science_skill", "dff_gossip_skill", "game_cooperative_skill", "dff_weather_skill", "dff_funfact_skill", "dff_travel_skill", "dff_coronavirus_skill", "dff_bot_persona_skill", "dff_gaming_skill", "dff_short_story_skill", ], ) # adding linked-to skills skills_for_uttr.extend(get_linked_to_skills(dialog)) skills_for_uttr.extend(get_previously_active_skill(dialog)) # NOW IT IS NOT ONLY FOR USUAL CONVERSATION BUT ALSO FOR SENSITIVE/HIGH PRIORITY INTENTS/ETC if "dff_coronavirus_skill" in skills_for_uttr: # no convert & comet when about coronavirus if "convert_reddit" in skills_for_uttr: skills_for_uttr.remove("convert_reddit") if "comet_dialog_skill" in skills_for_uttr: skills_for_uttr.remove("comet_dialog_skill") if len(dialog["utterances"]) > 1: # Use only misheard asr skill if asr is not confident and skip it for greeting if user_uttr_annotations.get("asr", {}).get("asr_confidence", "high") == "very_low": skills_for_uttr = ["misheard_asr"] if "/alexa_" in user_uttr_text: # adding alexa handler for Amazon Alexa specific commands skills_for_uttr = ["alexa_handler"] logger.info(f"Selected skills: {skills_for_uttr}") total_time = time.time() - st_time logger.info(f"rule_based_selector exec time = {total_time:.3f}s") asyncio.create_task( callback(task_id=payload["task_id"], response=list(set(skills_for_uttr)))) except Exception as e: total_time = time.time() - st_time logger.info(f"rule_based_selector exec time = {total_time:.3f}s") logger.exception(e) sentry_sdk.capture_exception(e) asyncio.create_task( callback(task_id=payload["task_id"], response=["dff_program_y_skill", "dummy_skill"]))
def tag_based_response_selection(dialog, candidates, scores, confidences, bot_utterances, all_prev_active_skills=None): all_prev_active_skills = all_prev_active_skills if all_prev_active_skills is not None else [] all_prev_active_skills = Counter(all_prev_active_skills) annotated_uttr = dialog["human_utterances"][-1] all_user_intents, all_user_topics, all_user_named_entities, all_user_nounphrases = get_main_info_annotations( annotated_uttr) _is_switch_topic_request = is_switch_topic(annotated_uttr) _is_force_intent = any( [_intent in all_user_intents for _intent in FORCE_INTENTS_IC.keys()]) # if user utterance contains any question (REGEXP & punctuation check!) _is_require_action_intent = is_any_question_sentence_in_utterance({ "text": annotated_uttr.get("annotations", {}).get("sentseg", {}).get("punct_sent", annotated_uttr["text"]) }) # if user utterance contains any question AND requires some intent by socialbot _is_require_action_intent = _is_require_action_intent and any([ _intent in all_user_intents for _intent in REQUIRE_ACTION_INTENTS.keys() ]) _force_intents_detected = [ _intent for _intent in FORCE_INTENTS_IC.keys() if _intent in all_user_intents ] # list of user intents which require some action by socialbot _require_action_intents_detected = [ _intent for _intent in REQUIRE_ACTION_INTENTS.keys() if _intent in all_user_intents ] _force_intents_skills = sum([ FORCE_INTENTS_IC.get(_intent, []) for _intent in _force_intents_detected ], []) # list of intents required by the socialbot _required_actions = sum([ REQUIRE_ACTION_INTENTS.get(_intent, []) for _intent in _require_action_intents_detected ], []) _contains_entities = len( get_entities(annotated_uttr, only_named=False, with_labels=False)) > 0 _is_active_skill_can_not_continue = False _prev_bot_uttr = dialog["bot_utterances"][-1] if len( dialog["bot_utterances"]) > 0 else {} _prev_active_skill = dialog["bot_utterances"][-1]["active_skill"] if len( dialog["bot_utterances"]) > 0 else "" _prev_prev_active_skill = dialog["bot_utterances"][-2][ "active_skill"] if len(dialog["bot_utterances"]) > 1 else "" _no_script_two_times_in_a_row = False if _prev_active_skill and _prev_prev_active_skill: if all([ skill not in ACTIVE_SKILLS + ALMOST_ACTIVE_SKILLS for skill in [_prev_active_skill, _prev_prev_active_skill] ]): _no_script_two_times_in_a_row = True disliked_skills = get_updated_disliked_skills( dialog, can_not_be_disliked_skills=CAN_NOT_BE_DISLIKED_SKILLS) _is_dummy_linkto_available = any([ cand_uttr["skill_name"] == "dummy_skill" and cand_uttr.get("type", "") == "link_to_for_response_selector" for cand_uttr in candidates ]) categorized_hyps = {} categorized_prompts = {} for dasuffix in ["reqda", ""]: for actsuffix in ["active", "continued", "finished"]: for suffix in [ "same_topic_entity_no_db", "same_topic_entity_db", "othr_topic_entity_no_db", "othr_topic_entity_db", ]: categorized_hyps[f"{actsuffix}_{suffix}_{dasuffix}"] = [] categorized_prompts[f"{actsuffix}_{suffix}_{dasuffix}"] = [] CASE = "" acknowledgement_hypothesis = {} for cand_id, cand_uttr in enumerate(candidates): if confidences[cand_id] == 0.0 and cand_uttr[ "skill_name"] not in ACTIVE_SKILLS: logger.info( f"Dropping cand_id: {cand_id} due to toxicity/badlists") continue all_cand_intents, all_cand_topics, all_cand_named_entities, all_cand_nounphrases = get_main_info_annotations( cand_uttr) skill_name = cand_uttr["skill_name"] _is_dialog_abandon = get_dialog_breakdown_annotations( cand_uttr) and PRIORITIZE_NO_DIALOG_BREAKDOWN _is_just_prompt = (cand_uttr["skill_name"] == "dummy_skill" and any([ question_type in cand_uttr.get("type", "") for question_type in ["normal_question", "link_to_for_response_selector"] ])) or cand_uttr.get("response_parts", []) == ["prompt"] if cand_uttr["confidence"] == 1.0: # for those hypotheses where developer forgot to set tag to MUST_CONTINUE cand_uttr["can_continue"] = MUST_CONTINUE _can_continue = cand_uttr.get("can_continue", CAN_NOT_CONTINUE) _user_wants_to_chat_about_topic = ( if_chat_about_particular_topic(annotated_uttr) and "about it" not in annotated_uttr["text"].lower()) _user_does_not_want_to_chat_about_topic = if_not_want_to_chat_about_particular_topic( annotated_uttr) _user_wants_bot_to_choose_topic = if_choose_topic( annotated_uttr, _prev_bot_uttr) if any([ phrase.lower() in cand_uttr["text"].lower() for phrase in LINK_TO_PHRASES ]): # add `prompt` to response_parts if any linkto phrase in hypothesis cand_uttr["response_parts"] = cand_uttr.get("response_parts", []) + ["prompt"] # identifies if candidate contains named entities from last human utterance _same_named_entities = (len( get_common_tokens_in_lists_of_strings( all_cand_named_entities, all_user_named_entities)) > 0) # identifies if candidate contains all (not only named) entities from last human utterance _same_nounphrases = len( get_common_tokens_in_lists_of_strings(all_cand_nounphrases, all_user_nounphrases)) > 0 _same_topic_entity = (_same_named_entities or _same_nounphrases ) and PRIORITIZE_WITH_SAME_TOPIC_ENTITY _is_active_skill = (_prev_active_skill == cand_uttr["skill_name"] or cand_uttr.get("can_continue", "") == MUST_CONTINUE) _is_active_skill = _is_active_skill and skill_name in ACTIVE_SKILLS _is_active_skill = _is_active_skill and (_can_continue in [ MUST_CONTINUE, CAN_CONTINUE_SCENARIO, CAN_NOT_CONTINUE ] or (_can_continue == CAN_CONTINUE_PROMPT and all_prev_active_skills.get(skill_name, []) < 10)) _is_active_skill = _is_active_skill and PRIORITIZE_SCRIPTED_SKILLS if _is_active_skill: # we will forcibly add prompt if current scripted skill finishes scenario, # and has no opportunity to continue at all. _is_active_skill_can_not_continue = _is_active_skill and _can_continue in [ CAN_NOT_CONTINUE ] if _is_force_intent: # =====force intents, choose as best_on_topic hypotheses from skills responding this request===== CASE = "Force intent." if cand_uttr["skill_name"] in _force_intents_skills: categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) elif _is_switch_topic_request or _user_does_not_want_to_chat_about_topic or _user_wants_bot_to_choose_topic: # =====direct request by user to switch the topic of current conversation===== # give priority to dummy linkto hypothesis if available, else other prompts if available. _is_active_skill = ( cand_uttr.get("type", "") == "link_to_for_response_selector" if _is_dummy_linkto_available else _is_just_prompt) # no priority to must_continue to skip incorrect continuation of script _can_continue = CAN_CONTINUE_SCENARIO if _can_continue == MUST_CONTINUE else _can_continue CASE = "Switch topic intent." if len(all_user_named_entities) > 0 or len( all_user_nounphrases) > 0: # -----user defines new topic/entity----- # _same_topic_entity does not depend on hyperparameter in these case _same_topic_entity = _same_named_entities or _same_nounphrases categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) else: # -----user want socialbot to define new topic/entity----- categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) elif _user_wants_to_chat_about_topic: # user wants to chat about particular topic CASE = "User wants to talk about topic." # in this case we do not give priority to previously active skill (but give to must continue skill!) # because now user wants to talk about something particular _is_active_skill = cand_uttr.get("can_continue", "") == MUST_CONTINUE # _same_topic_entity does not depend on hyperparameter in these case _same_topic_entity = _same_named_entities or _same_nounphrases categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) elif _is_require_action_intent and PRIORITIZE_WITH_REQUIRED_ACT: # =====user intent requires particular action===== CASE = "User intent requires action. USER UTTERANCE CONTAINS QUESTION." _is_grounding_reqda = (skill_name == "dff_grounding_skill" and cand_uttr.get( "type", "") == "universal_response") _is_active_skill = cand_uttr.get( "can_continue", "") == MUST_CONTINUE # no priority to prev active skill _can_continue = CAN_NOT_CONTINUE # no priority to scripted skills if set(all_cand_intents).intersection( set(_required_actions )) or _is_grounding_reqda or _is_active_skill: # -----one of the can intent is in intents required by user----- categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=True, ) else: # -----NO required dialog acts----- categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) else: # =====user intent does NOT require particular action===== CASE = "General case." categorized_hyps, categorized_prompts = categorize_candidate( cand_id, skill_name, categorized_hyps, categorized_prompts, _is_just_prompt, _is_active_skill, _can_continue, _same_topic_entity, _is_dialog_abandon, _is_required_da=False, ) # a bit of rule based help if (len(dialog["human_utterances"]) == 1 and cand_uttr["skill_name"] == "dff_friendship_skill" and greeting_spec in cand_uttr["text"]): categorized_hyps = add_to_top1_category(cand_id, categorized_hyps, _is_require_action_intent) elif (cand_uttr["skill_name"] == "dff_friendship_skill" and (how_are_you_spec in cand_uttr["text"] or what_i_can_do_spec in cand_uttr["text"]) and len(dialog["utterances"]) < 16): categorized_hyps = add_to_top1_category(cand_id, categorized_hyps, _is_require_action_intent) # elif cand_uttr["skill_name"] == 'program_y_dangerous' and cand_uttr['confidence'] == 0.98: # categorized_hyps = add_to_top1_category(cand_id, categorized_hyps, _is_require_action_intent) elif cand_uttr[ "skill_name"] == "small_talk_skill" and is_sensitive_situation( dialog["human_utterances"][-1]): # let small talk to talk about sex ^_^ categorized_hyps = add_to_top1_category(cand_id, categorized_hyps, _is_require_action_intent) elif cand_uttr["confidence"] >= 1.0: # -------------------- SUPER CONFIDENCE CASE HERE! -------------------- categorized_hyps = add_to_top1_category(cand_id, categorized_hyps, _is_require_action_intent) if cand_uttr["skill_name"] == "dff_grounding_skill" and [ "acknowledgement" ] == cand_uttr.get("response_parts", []): acknowledgement_hypothesis = deepcopy(cand_uttr) logger.info(f"Current CASE: {CASE}") # now compute current scores as one float value curr_single_scores = compute_curr_single_scores(candidates, scores, confidences) # remove disliked skills from hypotheses if IGNORE_DISLIKED_SKILLS: for category in categorized_hyps: new_ids = [] for cand_id in categorized_hyps[category]: if (candidates[cand_id]["skill_name"] in disliked_skills and candidates[cand_id].get("can_continue", CAN_NOT_CONTINUE) == MUST_CONTINUE): disliked_skills.remove(candidates[cand_id]["skill_name"]) if candidates[cand_id]["skill_name"] not in disliked_skills: new_ids.append(cand_id) categorized_hyps[category] = deepcopy(new_ids) for category in categorized_prompts: new_ids = [] for cand_id in categorized_prompts[category]: if (candidates[cand_id]["skill_name"] in disliked_skills and candidates[cand_id].get("can_continue", CAN_NOT_CONTINUE) == MUST_CONTINUE): disliked_skills.remove(candidates[cand_id]["skill_name"]) if candidates[cand_id]["skill_name"] not in disliked_skills: new_ids.append(cand_id) categorized_prompts[category] = deepcopy(new_ids) best_cand_id = pickup_best_id(categorized_hyps, candidates, curr_single_scores, bot_utterances) best_candidate = candidates[best_cand_id] best_candidate["human_attributes"] = best_candidate.get( "human_attributes", {}) # save updated disliked skills to human attributes of the best candidate best_candidate["human_attributes"]["disliked_skills"] = disliked_skills logger.info(f"Best candidate: {best_candidate}") n_sents_without_prompt = len(sent_tokenize(best_candidate["text"])) _is_best_not_script = best_candidate[ "skill_name"] not in ACTIVE_SKILLS + ALMOST_ACTIVE_SKILLS no_question_by_user = "******" not in dialog["human_utterances"][-1][ "annotations"].get("sentseg", {}).get("punct_sent", dialog["human_utterances"][-1]["text"]) # if `no` to 1st in a row linkto question, and chosen response is not from scripted skill _no_to_first_linkto = is_no(dialog["human_utterances"][-1]) and any([ phrase.lower() in _prev_bot_uttr.get("text", "").lower() for phrase in LINK_TO_PHRASES ]) # if chosen short response or question by not-scripted skill _is_short_or_question_by_not_script = _is_best_not_script and ( "?" in best_candidate["text"] or len(best_candidate["text"].split()) < 4) _no_questions_for_3_steps = not any([ is_any_question_sentence_in_utterance(uttr) for uttr in dialog["bot_utterances"][-3:] ]) if PRIORITIZE_PROMTS_WHEN_NO_SCRIPTS: if (_no_script_two_times_in_a_row and _is_short_or_question_by_not_script and no_question_by_user) or (_no_to_first_linkto and _is_best_not_script): # if no scripted skills 2 time sin a row before, current chosen best cand is not scripted, contains `?`, # and user utterance does not contain "?", replace utterance with dummy! best_prompt_id = pickup_best_id(categorized_prompts, candidates, curr_single_scores, bot_utterances) best_candidate = deepcopy(candidates[best_prompt_id]) best_cand_id = best_prompt_id if does_not_require_prompt(candidates, best_cand_id): # the candidate already contains a prompt or a question or of a length more than 200 symbols logger.info( "Best candidate contains prompt, question, request or length of > 200 symbols. Do NOT add prompt." ) pass elif sum(categorized_prompts.values(), []): # best cand is 3d times in a row not scripted skill, let's append linkto # need to add some prompt, and have a prompt _add_prompt_forcibly = best_candidate[ "skill_name"] == _prev_active_skill and _is_active_skill_can_not_continue _add_prompt_forcibly = _add_prompt_forcibly and not _contains_entities # prompts are added: # - in 1 out of 10 cases, if current human utterance does not contain entities, # and no prompt for several last bot utterances # - if PRIORITIZE_PROMTS_WHEN_NO_SCRIPTS and current utterance is from active on prev step scripted skill and # it has a status can-not-continue # - if PRIORITIZE_PROMTS_WHEN_NO_SCRIPTS and last 2 bot uttr are not from scripted skill, # and current best uttr is also from not-scripted skill if ((prompt_decision() and not _contains_entities and _no_questions_for_3_steps) or (_add_prompt_forcibly and PRIORITIZE_PROMTS_WHEN_NO_SCRIPTS) or (PRIORITIZE_PROMTS_WHEN_NO_SCRIPTS and _no_script_two_times_in_a_row and _is_best_not_script)): logger.info("Decided to add a prompt to the best candidate.") best_prompt_id = pickup_best_id(categorized_prompts, candidates, curr_single_scores, bot_utterances) # as we have only one active skill, let's consider active skill as that one providing prompt # but we also need to reassign all the attributes best_prompt = candidates[best_prompt_id] best_candidate[ "text"] = f'{best_candidate["text"]} {best_prompt["text"]}' best_candidate["attributes"] = best_candidate.get("attributes", {}) best_candidate["attributes"]["prompt_skill"] = best_prompt # anyway we must combine used links best_candidate["human_attributes"] = best_candidate.get( "human_attributes", {}) best_candidate["human_attributes"] = join_used_links_in_attributes( best_candidate["human_attributes"], best_prompt.get("human_attributes", {})) if len(best_candidate["human_attributes"]["used_links"]) == 0: best_candidate["human_attributes"].pop("used_links") was_ackn = if_acknowledgement_in_previous_bot_utterance(dialog) best_resp_cont_ackn = "acknowledgement" in best_candidate.get( "response_parts", []) if (ADD_ACKNOWLEDGMENTS_IF_POSSIBLE and acknowledgement_hypothesis and acknowledgement_decision(all_user_intents) and n_sents_without_prompt == 1 and not was_ackn and not best_resp_cont_ackn): logger.info( "Acknowledgement is given, Final hypothesis contains only 1 sentence, no ackn in prev bot uttr," "and we decided to add an acknowledgement to the best candidate.") best_candidate[ "text"] = f'{acknowledgement_hypothesis["text"]} {best_candidate["text"]}' best_candidate["response_parts"] = ["acknowledgement" ] + best_candidate.get( "response_parts", []) return best_candidate, best_cand_id, curr_single_scores
def talk_about_emotion(user_utt, bot_uttr): return if_chat_about_particular_topic( user_utt, bot_uttr, compiled_pattern=TALK_ABOUT_EMO_TEMPLATE)