Exemplo n.º 1
0
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]}
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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,
    )
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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
Exemplo n.º 12
0
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)
Exemplo n.º 13
0
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
Exemplo n.º 14
0
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
Exemplo n.º 15
0
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
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
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
Exemplo n.º 22
0
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
Exemplo n.º 23
0
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
Exemplo n.º 24
0
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
Exemplo n.º 25
0
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
Exemplo n.º 26
0
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]}]
Exemplo n.º 27
0
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
Exemplo n.º 28
0
    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"]))
Exemplo n.º 29
0
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
Exemplo n.º 30
0
def talk_about_emotion(user_utt, bot_uttr):
    return if_chat_about_particular_topic(
        user_utt, bot_uttr, compiled_pattern=TALK_ABOUT_EMO_TEMPLATE)