dream

Форк
0
/
emotion.py 
239 строк · 8.0 Кб
1
import re
2

3
from common.greeting import HOW_ARE_YOU_RESPONSES
4
from common.utils import get_emotions, get_comet_conceptnet_annotations
5
from common.universal_templates import if_chat_about_particular_topic
6

7

8
POSITIVE_EMOTIONS = set(
9
    [
10
        "interest",
11
        "inspiration",
12
        "enthusiasm",
13
        "laughter",
14
        "amusement",
15
        "empathy",
16
        "curiosity",
17
        "cheer",
18
        "contentment",
19
        "calmness",
20
        "serenity",
21
        "peace",
22
        "trust",
23
        "bliss",
24
        "delight",
25
        "happiness",
26
        "pleasure",
27
        "joy",
28
        "carefree",
29
        "ease",
30
        "satisfaction",
31
        "fulfillment",
32
        "hopeful",
33
        "confidence",
34
        "optimism",
35
        "passion",
36
        "harmony",
37
        "excitement",
38
        "gratitude",
39
        "kindness",
40
        "affection",
41
        "love",
42
        "surprise",
43
        "good",
44
        "well",
45
        "amazing",
46
    ]
47
)
48

49
NEGATIVE_EMOTIONS = set(
50
    [
51
        "grief",
52
        "sorrow",
53
        "heartache",
54
        "sadness",
55
        "unhappiness",
56
        "depression",
57
        "hatred",
58
        "blame",
59
        "regret",
60
        "misery",
61
        "resentment",
62
        "threatening",
63
        "antagonism",
64
        "anger",
65
        "fury",
66
        "hostility",
67
        "hate",
68
        "shame",
69
        "insecurity",
70
        "self-consciousness",
71
        "bravado",
72
        "embarrassment",
73
        "worry",
74
        "panic",
75
        "frustration",
76
        "pessimistic",
77
        "cynicism",
78
        "jealousy",
79
        "weariness",
80
        "pain",
81
        "anxiety",
82
        "fright",
83
        "fear",
84
        "sad",
85
        "bored",
86
        "sick",
87
        "bad",
88
    ]
89
)
90
POSITIVE_EMOTION = "positive_emotion"
91
NEGATIVE_EMOTION = "negative_emotion"
92

93
HOW_DO_YOU_FEEL = "How do you feel?"
94

95
# templates
96
PAIN_PATTERN = (
97
    r"\b(pain|backache|heart attack|earache|headache|" r"stomachache|toothache|diseased|ailing|damaged|sick|sore)\b"
98
)
99
SAD_PATTERN = (
100
    r"\b(sad|horrible|depressed|terrible|tired|awful|dire|upset|trash|"
101
    r"pity|poor|ill|low|exhausted|inferior|crying|miserable|cry|naughty|nasty|foul|ugly|grisly|harmful|"
102
    r"spoiled|depraved|tained|awry|so so|badly|sadly|wretched|bad|unhappy)\b"
103
)
104
POSITIVE_PATTERN = (
105
    r"\b(happy|good|okay|great|yeah|cool|awesome|perfect|nice|well|ok|fine|"
106
    r"neat|swell|fabulous|peachy|excellent|exciting|excited|splendid|all right"
107
    r"|super|classy|tops|famous|superb|incredible|tremendous|class|crackajack|crackerjack)\b"
108
)
109
ALONE_PATTERN = r"(i am alone|lonely|loneliness|do you love me)"
110
NOT_PATTERN = r"((\bnot|n't\bno)( too| that| really| so| feel| going)?)"
111
JOKE_PATTERN = r"(((tell me|tell|hear)( [a-z]+){0,3} jokes?)|^joke)"
112
POOR_ASR_PATTERN = r"^say$"
113

114
POSITIVE_TEMPLATE = re.compile(POSITIVE_PATTERN, re.IGNORECASE)
115
NOT_POSITIVE_TEMPLATE = re.compile(rf"{NOT_PATTERN} {POSITIVE_PATTERN}", re.IGNORECASE)
116
PAIN_TEMPLATE = re.compile(PAIN_PATTERN, re.IGNORECASE)
117
NOT_PAIN_TEMPLATE = re.compile(rf"{NOT_PATTERN} {PAIN_PATTERN}", re.IGNORECASE)
118
LONELINESS_TEMPLATE = re.compile(rf"{ALONE_PATTERN}", re.IGNORECASE)
119
NOT_LONELINESS_TEMPLATE = re.compile(rf"{NOT_PATTERN} {ALONE_PATTERN}", re.IGNORECASE)
120
SAD_TEMPLATE = re.compile(rf"({SAD_PATTERN}|{POOR_ASR_PATTERN})", re.IGNORECASE)
121
NOT_SAD_TEMPLATE = re.compile(rf"{NOT_PATTERN} {SAD_PATTERN}", re.IGNORECASE)
122
BORING_TEMPLATE = re.compile(r"(boring|bored)", re.IGNORECASE)
123
NOT_BORING_TEMPLATE = re.compile(rf"{NOT_PATTERN} (boring|bored)", re.IGNORECASE)
124
JOKE_REQUEST_TEMPLATE = re.compile(rf"{JOKE_PATTERN}", re.IGNORECASE)
125
NOT_JOKE_REQUEST_TEMPLATE = re.compile(rf"{NOT_PATTERN} {JOKE_PATTERN}", re.IGNORECASE)
126
ADVICE_PATTERN = (
127
    r"((((can|could) you )?(give|suggest|tell) (me )?(a |an |some )?advice)|" r"(advice me (something|anything)))"
128
)
129
ADVICE_REQUEST_TEMPLATE = re.compile(ADVICE_PATTERN, re.IGNORECASE)
130

131
TALK_ABOUT_EMO_TEMPLATE = re.compile(r"\b(emotion|feeling|i feel\b|depress)", re.IGNORECASE)
132

133

134
def talk_about_emotion(user_utt, bot_uttr):
135
    return if_chat_about_particular_topic(user_utt, bot_uttr, compiled_pattern=TALK_ABOUT_EMO_TEMPLATE)
136

137

138
def is_sad(annotated_uttr):
139
    uttr_text = annotated_uttr["text"]
140
    is_sad = re.search(SAD_TEMPLATE, uttr_text) and not re.search(NOT_SAD_TEMPLATE, uttr_text)
141
    not_positive = re.search(NOT_POSITIVE_TEMPLATE, uttr_text)
142
    return is_sad or not_positive
143

144

145
def is_boring(annotated_uttr):
146
    uttr_text = annotated_uttr["text"]
147
    return re.search(BORING_TEMPLATE, uttr_text) and not re.search(NOT_BORING_TEMPLATE, uttr_text)
148

149

150
def is_pain(annotated_uttr):
151
    uttr_text = annotated_uttr["text"]
152

153
    for elem, triplets in get_comet_conceptnet_annotations(annotated_uttr).items():
154
        if "SymbolOf" in triplets and "pain" in triplets["SymbolOf"]:
155
            return True
156
    return re.search(PAIN_TEMPLATE, uttr_text) and not re.search(NOT_PAIN_TEMPLATE, uttr_text)
157

158

159
def is_alone(annotated_uttr):
160
    uttr_text = annotated_uttr["text"]
161
    return re.search(LONELINESS_TEMPLATE, uttr_text) and not re.search(NOT_LONELINESS_TEMPLATE, uttr_text)
162

163

164
def is_joke_requested(annotated_uttr):
165
    uttr_text = annotated_uttr["text"]
166
    return re.search(JOKE_REQUEST_TEMPLATE, uttr_text) and not re.search(NOT_JOKE_REQUEST_TEMPLATE, uttr_text)
167

168

169
def is_negative_regexp_based(annotated_uttr):
170
    return any([negative_function(annotated_uttr) for negative_function in [is_sad, is_boring, is_alone, is_pain]])
171

172

173
def is_positive_regexp_based(annotated_uttr):
174
    uttr_text = annotated_uttr["text"]
175
    positive = re.search(POSITIVE_TEMPLATE, uttr_text) and not re.search(NOT_POSITIVE_TEMPLATE, uttr_text)
176
    not_sad = re.search(NOT_SAD_TEMPLATE, uttr_text)
177
    return positive or not_sad
178

179

180
def emo_advice_requested(uttr):
181
    return bool(re.search(ADVICE_REQUEST_TEMPLATE, uttr))
182

183

184
def skill_trigger_phrases():
185
    return [HOW_DO_YOU_FEEL] + sum([HOW_ARE_YOU_RESPONSES[lang] for lang in ["RU", "EN"]], [])
186

187

188
def emotion_from_feel_answer(prev_bot_uttr, user_uttr):
189
    if HOW_DO_YOU_FEEL.lower() in prev_bot_uttr.lower():
190
        for w in user_uttr.split(" "):
191
            w = re.sub(r"\W", " ", w.lower()).strip()
192
            if w in POSITIVE_EMOTIONS:
193
                return POSITIVE_EMOTION
194
            elif w in NEGATIVE_EMOTIONS:
195
                return NEGATIVE_EMOTION
196
    return None
197

198

199
def if_turn_on_emotion(user_utt, bot_uttr):
200
    emotions = get_emotions(user_utt, probs=True)
201
    emo_prob_threshold = 0.8  # to check if any emotion has at least this prob
202
    found_emotion, found_prob = "neutral", 1
203
    for emotion, prob in emotions.items():
204
        if prob == max(emotions.values()):
205
            found_emotion, found_prob = emotion, prob
206
    emo_found_emotion = found_emotion != "neutral" and found_prob > emo_prob_threshold
207
    good_emotion_prob = max([emotions.get("joy", 0), emotions.get("love", 0)])
208
    bad_emotion_prob = max([emotions.get("anger", 0), emotions.get("fear", 0), emotions.get("sadness", 0)])
209
    not_strange_emotion_prob = not (good_emotion_prob > 0.6 and bad_emotion_prob > 0.5)
210
    how_are_you = any(
211
        [
212
            how_are_you_response.lower() in bot_uttr.get("text", "").lower()
213
            for how_are_you_response in sum([HOW_ARE_YOU_RESPONSES[lang] for lang in ["RU", "EN"]], [])
214
        ]
215
    )
216
    joke_request_detected = is_joke_requested(user_utt)
217
    talk_about_regexp = talk_about_emotion(user_utt, bot_uttr)
218
    pain_detected_by_regexp = is_pain(user_utt)
219
    sadness_detected_by_regexp = is_sad(user_utt)
220
    loneliness_detected_by_regexp = is_alone(user_utt)
221
    advice_request_detected_by_regexp = emo_advice_requested(user_utt.get("text", ""))
222
    detected_from_feel_answer = emotion_from_feel_answer(bot_uttr.get("text", ""), user_utt.get("text", ""))
223
    should_run_emotion = (
224
        any(
225
            [
226
                emo_found_emotion,
227
                joke_request_detected,
228
                sadness_detected_by_regexp,
229
                loneliness_detected_by_regexp,
230
                pain_detected_by_regexp,
231
                advice_request_detected_by_regexp,
232
                talk_about_regexp,
233
                detected_from_feel_answer,
234
                how_are_you,
235
            ]
236
        )
237
        and not_strange_emotion_prob
238
    )
239
    return should_run_emotion
240

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.