def suggest_cook_response(vars): user_utt = state_utils.get_last_human_utterance(vars) try: linkto_food_skill_agreed = any( [req.lower() in state_utils.get_last_bot_utterance(vars)["text"].lower() for req in TRIGGER_PHRASES] ) if linkto_food_skill_agreed: if is_yes(user_utt) or bool(re.search(LIKE_RE, user_utt["text"].lower())): state_utils.set_confidence(vars, confidence=CONF_HIGH) state_utils.set_can_continue(vars, continue_flag=MUST_CONTINUE) elif not is_no(user_utt): state_utils.set_confidence(vars, confidence=CONF_MIDDLE) state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_SCENARIO) elif is_no(user_utt): state_utils.set_confidence(vars, confidence=CONF_HIGH) state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE) return ACKNOWLEDGEMENTS["fav_food_cook"] else: state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE) return error_response(vars) return "May I recommend you a meal to try to practice cooking?" else: state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE) return error_response(vars) except Exception as exc: logger.exception(exc) sentry_sdk.capture_exception(exc) return error_response(vars)
def switch_to_particular_game_discussion(vars): user_uttr = state_utils.get_last_human_utterance(vars) user_text = user_uttr.get("text", "").lower() prev_bot_uttr = state_utils.get_last_bot_utterance(vars) prev_bot_text = prev_bot_uttr.get("text", "") found_video_game_in_user_uttr = find_games_in_text(user_text) logger.info( f"(switch_to_particular_game_discussion)found_video_game_in_user_uttr: {found_video_game_in_user_uttr}" ) found_video_game_in_user_uttr = bool(found_video_game_in_user_uttr) found_video_game_in_bot_uttr = find_games_in_text(prev_bot_text) logger.info( f"(switch_to_particular_game_discussion)found_video_game_in_bot_uttr: {found_video_game_in_bot_uttr}" ) found_video_game_in_bot_uttr = bool(found_video_game_in_bot_uttr) choose_particular_game = if_choose_topic( user_uttr, prev_bot_uttr) and found_video_game_in_user_uttr question_answer_contains_video_game = ("?" not in user_text and "?" in prev_bot_text and found_video_game_in_user_uttr) bot_asked_about_game_and_user_answered_yes = (found_video_game_in_bot_uttr and "?" in prev_bot_text and is_yes(user_uttr)) flag = (lets_talk_about( vars, GAMES_WITH_AT_LEAST_1M_COPIES_SOLD_COMPILED_PATTERN) or choose_particular_game or question_answer_contains_video_game or bot_asked_about_game_and_user_answered_yes) logger.info(f"switch_to_particular_game_discussion={flag}") return flag
def wikihow_step_request(ngrams, vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars) isyes = is_yes(state_utils.get_last_human_utterance(vars)) shared_memory = state_utils.get_shared_memory(vars) wikihow_article = shared_memory.get("wikihow_article", "") prev_wikihow_title = shared_memory.get("prev_wikihow_title", "") used_wikihow_titles = set(shared_memory.get("used_wikihow_titles", [])) logger.info( f"wikihow_step_request, prev_wikihow_title {prev_wikihow_title} used_wikihow_titles " f"{used_wikihow_titles}") found_title = "" if wikihow_article: article_content = get_wikihow_content(wikihow_article) if article_content: all_page_titles = article_content.keys() for title in all_page_titles: if title not in used_wikihow_titles: found_title = title break further = re.findall(r"(more|further|continue|follow)", user_uttr["text"], re.IGNORECASE) if found_title or prev_wikihow_title: flag = True if prev_wikihow_title and not (isyes or further): flag = False logger.info(f"wikihow_step_request={flag}") return flag
def what_cuisine_response(vars): user_utt = state_utils.get_last_human_utterance(vars) bot_utt = state_utils.get_last_bot_utterance(vars)["text"].lower() banned_words = ["water"] linkto_food_skill_agreed = any([req.lower() in bot_utt for req in TRIGGER_PHRASES]) lets_talk_about_asked = bool(lets_talk_about_check(vars)) try: if not any([i in user_utt["text"].lower() for i in banned_words]): if linkto_food_skill_agreed: if is_yes(user_utt): state_utils.set_confidence(vars, confidence=CONF_HIGH) state_utils.set_can_continue(vars, continue_flag=MUST_CONTINUE) elif not is_no(user_utt): state_utils.set_confidence(vars, confidence=CONF_MIDDLE) state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_PROMPT) elif is_no(user_utt): state_utils.set_confidence(vars, confidence=CONF_HIGH) state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE) return ACKNOWLEDGEMENTS["cuisine"] elif lets_talk_about_asked: state_utils.set_confidence(vars, confidence=CONF_HIGH) state_utils.set_can_continue(vars, continue_flag=MUST_CONTINUE) else: state_utils.set_confidence(vars, confidence=CONF_LOW) state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_SCENARIO) return "I'm a fan of Mediterranean cuisine dishes. What cuisine do you prefer?" except Exception as exc: logger.exception(exc) sentry_sdk.capture_exception(exc) return error_response(vars)
def provide_facts_response(ctx, actor, page_source, wiki_page): wiki = ctx.misc.get("wiki", {}) user_uttr: dict = ctx.misc.get("agent", {}).get("dialog", {}).get("human_utterances", [{}])[-1] isyes = is_yes(user_uttr) or re.findall(CONTINUE_PATTERN, user_uttr["text"]) response = "" cur_wiki_page = wiki.get("cur_wiki_page", "") if not cur_wiki_page: wiki["cur_wiki_page"] = wiki_page if page_source == "wikiHow": page_content = get_wikihow_content(wiki_page, wikihow_cache) wiki_page_content_list = preprocess_wikihow_page(page_content) memory["wiki_page_content"] = wiki_page_content_list elif page_source == "wikipedia": page_content = get_wikipedia_content(wiki_page) wiki_page_content_list = preprocess_wikipedia_page(wiki_page.lower(), [], page_content) memory["wiki_page_content"] = wiki_page_content_list logger.info(f"wiki_page {wiki_page}") used_wiki_page_nums_dict = wiki.get("used_wiki_page_nums", {}) used_wiki_page_nums = used_wiki_page_nums_dict.get(wiki_page, []) wiki_page_content_list = memory.get("wiki_page_content", []) logger.info(f"response, used_wiki_page_nums {used_wiki_page_nums}") logger.info(f"response, wiki_page_content_list {wiki_page_content_list[:3]}") if wiki_page_content_list: for num, fact in enumerate(wiki_page_content_list): if num not in used_wiki_page_nums: facts_str = fact.get("facts_str", "") question = fact.get("question", "") response = f"{facts_str} {question}".strip().replace(" ", " ") used_wiki_page_nums.append(num) used_wiki_page_nums_dict[wiki_page] = used_wiki_page_nums wiki["used_wiki_page_nums"] = used_wiki_page_nums_dict break if len(wiki_page_content_list) == len(used_wiki_page_nums): if len(wiki_page_content_list) == len(used_wiki_page_nums): wiki["wiki_page"] = "" memory["wiki_page_content"] = [] logger.info(f"response, final {response}") if response: if isyes: context.set_confidence(ctx, actor, 1.0) context.set_can_continue(ctx, actor, common_constants.MUST_CONTINUE) else: context.set_confidence(ctx, actor, 0.99) context.set_can_continue(ctx, actor, common_constants.CAN_CONTINUE_SCENARIO) else: context.set_confidence(ctx, actor, 0.0) context.set_can_continue(ctx, actor, common_constants.CAN_NOT_CONTINUE) if hasattr(ctx, "a_s"): processed_node = ctx.a_s.get("processed_node", ctx.a_s["next_node"]) processed_node.response = response ctx.a_s["processed_node"] = processed_node else: processed_node = ctx.framework_states["actor"].get("processed_node", ctx.framework_states["actor"]["next_node"]) processed_node.response = response ctx.framework_states["actor"]["processed_node"] = processed_node return ctx
def check_condition_element(elem, user_uttr, bot_uttr, shared_memory={}): flag = False annotations = user_uttr["annotations"] isyes = is_yes(user_uttr) isno = is_no(user_uttr) user_info = shared_memory.get("user_info", {}) entity_triplets = shared_memory.get("entity_triplets", {}) if elem[0] == "is_yes" and isyes: flag = True elif elem[0] == "is_no" and isno: flag = True elif "pattern" in elem[0]: pattern = elem[0]["pattern"] if elem[1] == "user" and ( (isinstance(pattern, str) and re.findall(pattern, user_uttr["text"], re.IGNORECASE)) or (isinstance(pattern, re.Pattern) and re.findall(pattern, user_uttr["text"]))): flag = True if elem[1] == "bot" and ( (isinstance(pattern, str) and re.findall(pattern, bot_uttr.get("text", ""), re.IGNORECASE)) or (isinstance(pattern, re.Pattern) and re.findall(pattern, bot_uttr.get("text", "")))): flag = True elif "cobot_entities_type" in elem[0]: cobot_entities_type = elem[0]["cobot_entities_type"] nounphrases = annotations.get("cobot_entities", {}).get("labelled_entities", []) for nounphr in nounphrases: nounphr_label = nounphr.get("label", "") if nounphr_label == cobot_entities_type: flag = True elif "wiki_parser_types" in elem[0]: wp_types = elem[0]["wiki_parser_types"] found_entity, *_ = find_entity_by_types(annotations, wp_types) if found_entity: flag = True elif "user_info" in elem[0]: info_to_check = elem[0]["user_info"] for key, value in info_to_check.items(): if key in user_info and user_info[key] == value: flag = True break elif "entity_triplets" in elem[0]: checked_entity_triplets = elem[0]["entity_triplets"] objects = set(checked_entity_triplets[-1]) mem_objects = entity_triplets for key in checked_entity_triplets[:-1]: if key in user_info: key = user_info[key] mem_objects = mem_objects.get(key, {}) if set(mem_objects).intersection(objects): flag = True elif elem[0] == "any": flag = True if len(elem) == 3 and not elem[2]: flag = not flag return flag
def is_staying_home_requested(prev_bot_utt, user_utt): for phrase in [ REMOTE_WORK_CORONAVIRUS_PHRASE, STAY_HOME_CORONAVIRUS_PHRASE ]: if phrase.lower() in prev_bot_utt.get("text", "").lower(): if is_yes(user_utt) or is_no(user_utt): return True return False
def user_doesnt_say_yes_request(ngrams, vars, additional_check=None): uttr = state_utils.get_last_human_utterance(vars) flag = not is_yes(uttr) and perform_additional_check( additional_check, ngrams, vars) logger.info( f"user_doesnt_say_yes_request {get_additional_check_description(additional_check)}: {flag}" ) return flag
def drawing_request(vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) isyes = is_yes(user_uttr) if re.findall("do you like drawing", bot_uttr.get("text", "")) and isyes: flag = True return flag
def is_speech_function_agree(vars): human_utterance = state_utils.get_last_human_utterance(vars) sf_type, sf_confidence = get_speech_function_for_human_utterance( human_utterance) flag = sf_type and bool(re.search(agree_patterns_re, sf_type)) # fallback to yes/no intents flag = flag or common_utils.is_yes(human_utterance) return flag
def what_cuisine_request(ngrams, vars): linkto_food_skill_agreed = any( [req.lower() in state_utils.get_last_bot_utterance(vars)["text"].lower() for req in TRIGGER_PHRASES] ) and any( [is_yes(state_utils.get_last_human_utterance(vars)), not is_no(state_utils.get_last_human_utterance(vars))] ) flag = (bool(lets_talk_about_check(vars)) or linkto_food_skill_agreed) and (not dont_want_talk(vars)) logger.info(f"what_cuisine_request {flag}") return flag
def user_wants_game_description_2_or_more_of_description_turns_remain_request( ngrams, vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars) isyes = is_yes(user_uttr) if not isyes: flag = True logger.info( f"user_wants_game_description_2_or_more_of_description_turns_remain_request={flag}" ) return flag
def is_speech_function_demand_opinion(vars): human_utterance = state_utils.get_last_human_utterance(vars) sf_type, sf_confidence = get_speech_function_for_human_utterance( human_utterance) flag = sf_type and bool(re.search(demand_opinion_patterns_re, sf_type)) # # fallback to CoBot intents flag = flag or is_cobot_opinion_demanded(vars) flag = flag or common_utils.is_no(human_utterance) # bug check (sometimes opinion by MIDAS can be incorrectly detected in a simple yes/no answer from user) flag = flag and not common_utils.is_no( human_utterance) and not common_utils.is_yes(human_utterance) return flag
def my_pets_request(ngrams, vars): flag = False bot_uttr = state_utils.get_last_bot_utterance(vars)["text"] isyes = is_yes(state_utils.get_last_human_utterance(vars)) shared_memory = state_utils.get_shared_memory(vars) told_about_cat = shared_memory.get("told_about_cat", False) told_about_dog = shared_memory.get("told_about_dog", False) if "Would you like to learn more about my pets?" in bot_uttr and isyes and not ( told_about_cat and told_about_dog): flag = True logger.info(f"my_pets_request={flag}") return flag
def is_speech_function_agree(vars): # fallback to MIDAS human_utterance = state_utils.get_last_human_utterance(vars) sf_type, sf_confidence = get_speech_function_for_human_utterance( human_utterance) flag = sf_type and bool(re.search(agree_patterns_re, sf_type)) # fallback to MIDAS flag = flag or is_midas_positive_answer(vars) # fallback to yes/no intents flag = flag or common_utils.is_yes(human_utterance) flag = flag and not is_not_interested_speech_function(vars) return flag
def user_has_pets_request(ngrams, vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars)["text"] bot_uttr = state_utils.get_last_bot_utterance(vars)["text"].lower() isno = is_no(state_utils.get_last_human_utterance(vars)) isyes = is_yes(state_utils.get_last_human_utterance(vars)) user_has = re.findall("i (have|had)", user_uttr) bot_asked_like = "do you like animals" in bot_uttr bot_asked_have = "do you have pets" in bot_uttr if ((re.search(PETS_TEMPLATE_EXT, user_uttr) and not isno) or (re.search(PETS_TEMPLATE_EXT, bot_uttr) and (isyes or user_has)) or (bot_asked_like and user_has) or (bot_asked_have and isyes)): flag = True logger.info(f"user_has_pets_request={flag}") return flag
def check_cooking_request(ngrams, vars): linkto_food_skill_agreed = any( [req.lower() in state_utils.get_last_bot_utterance(vars)["text"].lower() for req in TRIGGER_PHRASES] ) and any( [ is_yes(state_utils.get_last_human_utterance(vars)), not is_no(state_utils.get_last_human_utterance(vars)), bool(re.search(LIKE_RE, state_utils.get_last_human_utterance(vars)["text"].lower())), ] ) if linkto_food_skill_agreed: flag = True else: flag = False logger.info(f"check_cooking_request {flag}") return flag
def check_condition(vars, condition): flag = False user_uttr = state_utils.get_last_human_utterance(vars) if callable(condition): flag = condition(vars) elif isinstance(condition, str): if re.findall(condition, user_uttr["text"], re.IGNORECASE): flag = True elif isinstance(condition, re.Pattern): if re.findall(condition, user_uttr["text"]): flag = True elif condition == intents.yes_intent(vars) and is_yes(user_uttr): flag = True elif condition == intents.always_true(vars): flag = True return flag
def if_wants_more(vars, all_titles): flag = False isyes = is_yes(state_utils.get_last_human_utterance(vars)) isno = is_no(state_utils.get_last_human_utterance(vars)) user_uttr = state_utils.get_last_human_utterance(vars) further = re.findall(r"(more|further|continue|follow)", user_uttr["text"], re.IGNORECASE) another_topic = another_topic_question(vars, all_titles) if isyes or (further and not isno): flag = True if another_topic and not isyes: flag = False if isno: flag = False logger.info(f"wants_more={flag}") return flag
def sys_what_animals_request(ngrams, vars): flag = False linkto_like_animals = any([ req.lower() in state_utils.get_last_bot_utterance(vars)["text"].lower() for req in LIKE_ANIMALS_REQUESTS ]) text = state_utils.get_last_human_utterance(vars)["text"] user_agrees = is_yes(state_utils.get_last_human_utterance(vars)) check_linkto = lets_talk_about_request(vars) or ( linkto_like_animals and user_agrees) or text == "animals" find_pets = re.findall(r"(\bpet\b|\bpets\b)", text) or re.search( PETS_TEMPLATE, text) if check_linkto and not find_pets: flag = True logger.info(f"sys_what_animals_request={flag}") return flag
def user_mentioned_his_pet_request(ngrams, vars): flag = False user_uttr = state_utils.get_last_human_utterance(vars) bot_uttr = state_utils.get_last_bot_utterance(vars) isyes = is_yes(user_uttr) users_pet = re.findall(r"my (cat|dog|puppy|kitty|kitten)", user_uttr["text"], re.IGNORECASE) has_pet = re.findall(r"i (have |had )(a )?(cat|dog|puppy|kitty|kitten)", user_uttr["text"], re.IGNORECASE) found_badlist = re.findall(NOT_SWITCH_TEMPLATE, user_uttr["text"]) bot_asked_pet = "do you have pets" in bot_uttr["text"].lower() found_pet = re.search(PETS_TEMPLATE, user_uttr["text"]) if (users_pet or has_pet or (bot_asked_pet and (found_pet or isyes))) and not found_badlist: flag = True logger.info(f"user_mentioned_his_pet_request={flag}") return flag
def more_details_request(ngrams, vars): flag = False shared_memory = state_utils.get_shared_memory(vars) mentions_list = shared_memory.get("mentions", []) user_uttr = state_utils.get_last_human_utterance(vars) annotations = user_uttr["annotations"] bot_uttr = state_utils.get_last_bot_utterance(vars) bot_more_details = "more details" in bot_uttr["text"] user_more_details = re.findall(COMPILE_LETS_TALK, user_uttr["text"]) isyes = is_yes(state_utils.get_last_human_utterance(vars)) nounphrases = annotations.get("spacy_nounphrases", []) inters = set(nounphrases).intersection(set(mentions_list)) started = shared_memory.get("start", False) if ((user_more_details and inters) or (bot_more_details and isyes)) and started: flag = True logger.info(f"more_details_request={flag}") return flag
def switch_to_general_gaming_discussion(vars): user_uttr = state_utils.get_last_human_utterance(vars) user_text = user_uttr.get("text", "").lower() prev_bot_uttr = state_utils.get_last_bot_utterance(vars) prev_bot_text = prev_bot_uttr.get("text", "") found_video_game_words_in_user_uttr = bool( VIDEO_GAME_WORDS_COMPILED_PATTERN.search(user_text)) choose_gaming_discussion = if_choose_topic( user_uttr, prev_bot_uttr) and found_video_game_words_in_user_uttr question_answer_contains_video_game_words = ( "?" not in user_text and "?" in prev_bot_text and found_video_game_words_in_user_uttr) bot_asked_about_game_and_user_answered_yes = is_yes( user_uttr) and is_question_about_games(prev_bot_text) flag = (lets_talk_about(vars, VIDEO_GAME_WORDS_COMPILED_PATTERN) or choose_gaming_discussion or question_answer_contains_video_game_words or bot_asked_about_game_and_user_answered_yes) logger.info(f"switch_to_general_gaming_discussion={flag}") return flag
def what_pets_request(ngrams, vars): flag = False bot_uttr = state_utils.get_last_bot_utterance(vars) user_uttr = state_utils.get_last_human_utterance(vars) isyes = is_yes(state_utils.get_last_human_utterance(vars)) user_has = re.findall(r"i (have|had)", user_uttr["text"]) mention_pet = re.findall(PETS_TEMPLATE, user_uttr["text"]) asked_about_pets = "do you have pets" in bot_uttr["text"].lower() bot_asked_pet = re.findall( r"do you have a (cat|dog|rat|fish|bird|parrot|hamster)", bot_uttr["text"], re.IGNORECASE) logger.info( f"what_pets_request, {asked_about_pets}, {isyes}, {user_has}, {mention_pet}" ) my_pets = my_pets_request(ngrams, vars) if not my_pets and asked_about_pets and ( isyes or user_has) and not mention_pet and not (bot_asked_pet and is_yes): flag = True logger.info(f"what_pets_request={flag}") return flag
def retrieve_and_save(vars): user_uttr = state_utils.get_last_human_utterance(vars)["text"] bot_uttr = state_utils.get_last_bot_utterance(vars)["text"] isyes = is_yes(state_utils.get_last_human_utterance(vars)) shared_memory = state_utils.get_shared_memory(vars) found_users_pet = shared_memory.get("users_pet", "") found_pet_bot_uttr = [] if not found_users_pet: found_users_pet = extract_pet(user_uttr) found_pet_bot_uttr = re.findall( r"(do you have a )(cat|dog|rat|fish|bird|parrot|hamster|puppy|kitten|kitty)", bot_uttr, re.IGNORECASE) if found_users_pet: state_utils.save_to_shared_memory(vars, users_pet=found_users_pet) elif found_pet_bot_uttr and isyes: state_utils.save_to_shared_memory( vars, users_pet=found_pet_bot_uttr[0][1]) found_users_pet = found_pet_bot_uttr[0][1] logger.info( f"retrieve_and_save, found_users_pet {found_users_pet} found_pet_bot_uttr {found_pet_bot_uttr}" f" isyes {isyes}") return found_users_pet
def user_wants_to_talk_about_minecraft_request(ngrams, vars): if common_intents.switch_to_particular_game_discussion(vars): user_uttr = state_utils.get_last_human_utterance(vars) prev_bot_uttr = state_utils.get_last_bot_utterance(vars) game_names_from_local_list_of_games = find_games_in_text( user_uttr.get("text", "")) if is_yes(user_uttr): game_names_from_local_list_of_games += find_games_in_text( prev_bot_uttr.get("text", "")) logger.info( f"(user_wants_to_talk_about_minecraft_request)game_names_from_local_list_of_games: " f"{game_names_from_local_list_of_games}") assert ( game_names_from_local_list_of_games ), "At least one game should have been found in function `switch_to_particular_game_discussion()`" flag = any([ "minecraft" in gn[0].lower() for gn in game_names_from_local_list_of_games ]) else: flag = False logger.info(f"user_wants_to_talk_about_minecraft_request={flag}") return flag
def get_entities_with_attitudes(annotated_uttr: dict, prev_annotated_uttr: dict): entities_with_attitudes = {"like": [], "dislike": []} all_entities = get_entities(annotated_uttr, only_named=False, with_labels=False) all_prev_entities = get_entities(prev_annotated_uttr, only_named=False, with_labels=False) logger.info( f"Consider all curr entities: {all_entities}, and all previous entities: {all_prev_entities}" ) curr_entity = all_entities[0] if all_entities else "" prev_entity = all_prev_entities[-1] if all_prev_entities else "" curr_uttr_text = annotated_uttr.get("text", "") prev_uttr_text = prev_annotated_uttr.get("text", "") curr_sentiment = get_sentiment(annotated_uttr, probs=False, default_labels=["neutral"])[0] current_first_sentence = (annotated_uttr.get("annotations", {}).get( "sentseg", {}).get("segments", [curr_uttr_text])[0]) if "?" in current_first_sentence: pass elif WHAT_FAVORITE_PATTERN.search(prev_uttr_text): # what is your favorite ..? - animals -> `like animals` entities_with_attitudes["like"] += [curr_entity] elif WHAT_LESS_FAVORITE_PATTERN.search(prev_uttr_text): # what is your less favorite ..? - animals -> `dislike animals` entities_with_attitudes["dislike"] += [curr_entity] elif DO_YOU_LOVE_PATTERN.search(prev_uttr_text): if is_no(annotated_uttr): # do you love .. animals? - no -> `dislike animals` entities_with_attitudes["dislike"] += [prev_entity] elif is_yes(annotated_uttr): # do you love .. animals? - yes -> `like animals` entities_with_attitudes["like"] += [prev_entity] elif DO_YOU_HATE_PATTERN.search(prev_uttr_text): if is_no(annotated_uttr): # do you hate .. animals? - no -> `like animals` entities_with_attitudes["like"] += [prev_entity] elif is_yes(annotated_uttr): # do you hate .. animals? - yes -> `dislike animals` entities_with_attitudes["dislike"] += [prev_entity] elif I_HATE_PATTERN.search(curr_uttr_text): # i hate .. animals -> `dislike animals` entities_with_attitudes["dislike"] += [curr_entity] elif I_LOVE_PATTERN.search(curr_uttr_text) or MY_FAVORITE_PATTERN.search( curr_uttr_text): # i love .. animals -> `like animals` entities_with_attitudes["like"] += [curr_entity] elif if_chat_about_particular_topic( annotated_uttr, prev_annotated_uttr=prev_annotated_uttr, key_words=[curr_entity]): # what do you want to chat about? - ANIMALS -> `like animals` entities_with_attitudes["like"] += [curr_entity] elif if_not_want_to_chat_about_particular_topic( annotated_uttr, prev_annotated_uttr=prev_annotated_uttr): # i don't wanna talk about animals -> `dislike animals` entities_with_attitudes["dislike"] += [curr_entity] elif WHAT_DO_YOU_THINK_PATTERN.search(prev_uttr_text): if curr_sentiment == "negative": # what do you thank .. animals? - negative -> `dislike animals` entities_with_attitudes["dislike"] += [prev_entity] elif curr_sentiment == "positive": # what do you thank .. animals? - positive -> `like animals` entities_with_attitudes["like"] += [prev_entity] entities_with_attitudes["like"] = [ el for el in entities_with_attitudes["like"] if el ] entities_with_attitudes["dislike"] = [ el for el in entities_with_attitudes["dislike"] if el ] return entities_with_attitudes
def if_chat_about_particular_topic(annotated_uttr, prev_annotated_uttr=None, key_words=None, compiled_pattern=r""): """Dialog context implies that the last utterances chooses particular conversational topic: - annotated_uttr asks "let's talk about PARTICULAR-TOPIC" - prev_annotated_uttr asks "what do you want to talk about?", and annotated_uttr says PARTICULAR-TOPIC. - prev_annotated_uttr asks "what are your interests?", and annotated_uttr says PARTICULAR-TOPIC. """ prev_annotated_uttr = {} if prev_annotated_uttr is None else prev_annotated_uttr key_words = [] if key_words is None else key_words uttr_ = annotated_uttr.get("text", "").lower() prev_uttr_ = prev_annotated_uttr.get("text", "").lower() # current uttr is lets talk about blabla chat_about_intent = "lets_chat_about" in get_intents( annotated_uttr, probs=False, which="intent_catcher") chat_about = chat_about_intent or if_lets_chat_about_topic(uttr_) # prev uttr is what do you want to talk about? prev_chat_about_intent = "lets_chat_about" in get_intents( prev_annotated_uttr, probs=False, which="intent_catcher") prev_what_to_chat_about = prev_chat_about_intent or if_utterance_requests_topic( prev_annotated_uttr) not_want = if_not_want_to_chat_about_particular_topic( annotated_uttr, prev_annotated_uttr) if not_want: return False elif prev_what_to_chat_about or chat_about: if key_words: trigger_pattern = re.compile( rf"{join_word_beginnings_in_or_pattern(key_words)}[a-zA-Z0-9,\-\' ]+\?", re.IGNORECASE) offered_this_topic = trigger_pattern.search(prev_uttr_) user_agrees_or_any = ANY_TOPIC_AMONG_OFFERED.search( uttr_) or is_yes(annotated_uttr) if any([word in uttr_ for word in key_words ]) or (offered_this_topic and user_agrees_or_any): return True else: return False elif compiled_pattern: if isinstance(compiled_pattern, str): offered_this_topic = re.search( rf"{compiled_pattern}[a-zA-Z0-9,\-\' ]+\?", prev_uttr_, re.IGNORECASE) else: offered_this_topic = re.search( rf"{compiled_pattern.pattern}[a-zA-Z0-9,\-\' ]+\?", prev_uttr_, re.IGNORECASE) user_agrees_or_any = ANY_TOPIC_AMONG_OFFERED.search( uttr_) or is_yes(annotated_uttr) if re.search(compiled_pattern, uttr_) or (offered_this_topic and user_agrees_or_any): return True else: return False else: return True return False
def get_response_for_particular_topic_and_status(topic, curr_meta_script_status, dialog, source_topic): attr = { "meta_script_topic": topic, "meta_script_status": curr_meta_script_status } if len(dialog["human_utterances"]) > 0: user_uttr = dialog["human_utterances"][-1] text_user_uttr = dialog["human_utterances"][-1]["text"].lower() last_user_sent_text = (dialog["human_utterances"][-1].get( "annotations", {}).get("sentseg", {}).get("segments", [""])[-1].lower()) else: user_uttr = {"text": ""} text_user_uttr = "" last_user_sent_text = "" if len(dialog["bot_utterances"]) > 0: bot_uttr = dialog["bot_utterances"][-1] else: bot_uttr = {} if curr_meta_script_status == "starting": response, confidence, attr = get_starting_phrase(dialog, topic, attr) attr["response_parts"] = ["prompt"] can_offer_topic = if_choose_topic(dialog["human_utterances"][-1], bot_uttr) talk_about_user_topic = is_custom_topic( topic) and if_chat_about_particular_topic(user_uttr, bot_uttr) prev_what_to_talk_about_outputs = [ get_outputs_with_response_from_dialog(dialog["utterances"][-3:], response=response, activated=True) for response in GREETING_QUESTIONS[list(GREETING_QUESTIONS.keys())[0]] ] prev_what_to_talk_about_outputs = sum([ list_of_outputs for list_of_outputs in prev_what_to_talk_about_outputs if len(list_of_outputs) > 0 ], []) prev_what_to_talk_about_greeting = len( prev_what_to_talk_about_outputs) > 0 and bot_uttr.get( "active_skill", "") in ["dff_friendship_skill", "program_y"] if (not prev_what_to_talk_about_greeting and can_offer_topic) or talk_about_user_topic: # if person wants to talk about something particular and we have extracted some topic - do that! confidence = MATCHED_DIALOG_BEGIN_CONFIDENCE elif "?" in last_user_sent_text or prev_what_to_talk_about_greeting: # if some question was asked by user, do not start script at all! response, confidence = "", 0.0 elif len(dialog["utterances"]) <= 20: confidence = DEFAULT_DIALOG_BEGIN_CONFIDENCE elif source_topic == NP_SOURCE: confidence = NOUN_TOPIC_STARTING_CONFIDENCE else: confidence = DEFAULT_STARTING_CONFIDENCE else: if curr_meta_script_status == "deeper1" and "?" in last_user_sent_text and "what" not in text_user_uttr: response, confidence, attr = "", 0.0, {} elif "?" in last_user_sent_text and not check_topic_lemmas_in_sentence( text_user_uttr, topic): logger.info( "Question by user was detected. Without any word from topic in it. " "Don't continue the script on this turn.") response, confidence, attr = "", 0.0, {} elif is_switch_topic(user_uttr) or if_chat_about_particular_topic( user_uttr): logger.info("Topic switching was detected. Finish script.") response, confidence = FINISHED_SCRIPT_RESPONSE, 0.5 attr["meta_script_status"] = FINISHED_SCRIPT attr["can_continue"] = CAN_NOT_CONTINUE elif get_user_replies_to_particular_skill( dialog["utterances"], "meta_script_skill")[-2:] == ["no.", "no."]: logger.info( "Two consequent `no` answers were detected. Finish script.") response, confidence = FINISHED_SCRIPT_RESPONSE, 0.5 attr["meta_script_status"] = FINISHED_SCRIPT attr["can_continue"] = CAN_NOT_CONTINUE elif curr_meta_script_status == "comment": response, confidence, attr = get_comment_phrase(dialog, attr) attr["can_continue"] = CAN_NOT_CONTINUE elif curr_meta_script_status == "opinion": response, confidence, attr = get_opinion_phrase( dialog, topic, attr) elif curr_meta_script_status == "deeper1" and ( is_no(user_uttr) or "never" in text_user_uttr): response, confidence = FINISHED_SCRIPT_RESPONSE, 0.5 attr["meta_script_status"] = FINISHED_SCRIPT attr["can_continue"] = CAN_NOT_CONTINUE else: response, confidence, attr = get_statement_phrase( dialog, topic, attr, TOPICS) attr["can_continue"] = CAN_CONTINUE_SCENARIO if confidence > 0.7 and (is_yes(user_uttr) or len(text_user_uttr.split()) > 7): # if yes detected, confidence 1.0 - we like agreements! confidence = 1.0 if confidence > 0.7 and bot_uttr.get("active_skill", "") != "meta_script_skill": confidence = BROKEN_DIALOG_CONTINUE_CONFIDENCE logger.info( f"User sent: `{text_user_uttr}`. Response: `{response}`. Attr: `{attr}.`" ) return response, confidence, attr
def misheard_response(): st_time = time.time() dialogs_batch = request.json["dialogs"] final_confidences = [] final_responses = [] final_human_attributes = [] final_bot_attributes = [] for dialog in dialogs_batch: prev_user_utt = None if len(dialog["human_utterances"]) > 1: prev_user_utt = dialog["human_utterances"][-2] bot_attributes = dialog["bot"]["attributes"] human_attributes = dialog["human"]["attributes"] current_user_utt = dialog["human_utterances"][-1] prev_bot_utt = dialog["bot_utterances"][-1] if len( dialog["bot_utterances"]) > 0 else {} logger.debug( f"MISHEARD ASR INPUT: current utt text: {current_user_utt['text']};" f"bot attrs: {bot_attributes}; user attrs: {human_attributes}" f"HYPOTS: {current_user_utt['hypotheses']}" f"PREV BOT UTT: {prev_bot_utt}") if bot_attributes.get("asr_misheard") is True and prev_bot_utt[ "active_skill"] == "misheard_asr": bot_attributes["asr_misheard"] = False if is_yes(current_user_utt): hypots = prev_user_utt["hypotheses"] logger.debug(f"PREV HYPOTS: {hypots}") candidates = [] confs = [] for resp in hypots: if resp["skill_name"] != "misheard_asr": candidates.append(resp["text"]) confs.append(resp["confidence"]) final_responses.append(candidates) final_confidences.append(confs) final_human_attributes.append([human_attributes] * len(candidates)) final_bot_attributes.append([bot_attributes] * len(candidates)) elif is_no(current_user_utt): response = "What is it that you'd like to chat about?" final_responses.append([response]) final_confidences.append([1.0]) final_human_attributes.append([human_attributes]) final_bot_attributes.append([bot_attributes]) else: final_responses.append(["sorry"]) final_confidences.append([0.0]) final_human_attributes.append([human_attributes]) final_bot_attributes.append([bot_attributes]) else: bot_attributes["asr_misheard"] = False if current_user_utt["annotations"]["asr"][ "asr_confidence"] == "very_low": final_responses.append([np.random.choice(misheard_responses)]) final_confidences.append([1.0]) final_human_attributes.append([human_attributes]) final_bot_attributes.append([bot_attributes]) elif current_user_utt["annotations"]["asr"][ "asr_confidence"] == "medium": response = f"Excuse me, I misheard you. Have you said: \"{dialog['human_utterances'][-1]['text']}\"?" final_responses.append([response]) final_confidences.append([1.0]) bot_attributes["asr_misheard"] = True final_human_attributes.append([human_attributes]) final_bot_attributes.append([bot_attributes]) else: final_responses.append(["sorry"]) final_confidences.append([0.0]) final_human_attributes.append([human_attributes]) final_bot_attributes.append([bot_attributes]) total_time = time.time() - st_time logger.info(f"misheard_asr#misheard_respond exec time: {total_time:.3f}s") resp = list( zip(final_responses, final_confidences, final_human_attributes, final_bot_attributes)) logger.debug(f"misheard_asr#misheard_respond OUTPUT: {resp}") return jsonify(resp)