dream

Форк
0
351 строка · 13.7 Кб
1
# %%
2
import logging
3
import os
4
import random
5
import re
6

7
from common.fact_random import get_fact
8
from enum import Enum, auto
9

10
import sentry_sdk
11

12
from dff import dialogflow_extension
13
import common.dialogflow_framework.utils.state as state_utils
14
import common.dialogflow_framework.utils.condition as condition_utils
15
import dialogflows.scopes as scopes
16
from common.constants import CAN_CONTINUE_PROMPT, CAN_NOT_CONTINUE, CAN_CONTINUE_SCENARIO
17
from common.universal_templates import DONOTKNOW_LIKE, COMPILE_NOT_WANT_TO_TALK_ABOUT_IT
18
from common.utils import get_entities, join_words_in_or_pattern, get_comet_conceptnet_annotations
19
from common.food import (
20
    FAST_FOOD_FACTS,
21
    FAST_FOOD_QUESTIONS,
22
    FAST_FOOD_WHAT_QUESTIONS,
23
    FOOD_WORDS,
24
    CONCEPTNET_SYMBOLOF_FOOD,
25
    CONCEPTNET_HASPROPERTY_FOOD,
26
    CONCEPTNET_CAUSESDESIRE_FOOD,
27
)
28

29
sentry_sdk.init(dsn=os.getenv("SENTRY_DSN"))
30

31

32
logger = logging.getLogger(__name__)
33

34

35
CONF_HIGH = 1.0
36
CONF_MIDDLE = 0.95
37
CONF_LOW = 0.9
38
CONF_LOWEST = 0.8
39

40
FOOD_WORDS_RE = re.compile(FOOD_WORDS, re.IGNORECASE)
41
NO_WORDS_RE = re.compile(r"(\bnot\b|n't|\bno\b) ", re.IGNORECASE)
42
DONOTKNOW_LIKE_RE = re.compile(join_words_in_or_pattern(DONOTKNOW_LIKE), re.IGNORECASE)
43

44

45
class State(Enum):
46
    USR_START = auto()
47
    #
48
    SYS_SAID_FAV_FOOD = auto()
49
    USR_HOW_OFTEN = auto()
50
    SYS_HOW_OFTEN = auto()
51
    USR_WHAT_EAT = auto()
52
    SYS_FOOD_CHECK = auto()
53
    USR_FAST_FOOD_FACT = auto()
54
    SYS_SMTH = auto()
55
    SYS_SMTH_ELSE = auto()
56
    USR_LINKTO = auto()
57
    #
58
    SYS_ERR = auto()
59
    USR_ERR = auto()
60

61

62
# %%
63

64
##################################################################################################################
65
# Init DialogFlow
66
##################################################################################################################
67

68

69
simplified_dialogflow = dialogflow_extension.DFEasyFilling(State.USR_START)
70

71
##################################################################################################################
72
##################################################################################################################
73
# Design DialogFlow.
74
##################################################################################################################
75
##################################################################################################################
76
##################################################################################################################
77
# yes
78
##################################################################################################################
79

80

81
def yes_request(ngrams, vars):
82
    flag = condition_utils.is_yes_vars(vars)
83
    logger.info(f"yes_request {flag}")
84
    return flag
85

86

87
##################################################################################################################
88
# no
89
##################################################################################################################
90

91

92
def no_request(ngrams, vars):
93
    flag = condition_utils.is_no_vars(vars)
94
    logger.info(f"no_request {flag}")
95
    return flag
96

97

98
##################################################################################################################
99
# error
100
##################################################################################################################
101

102

103
def error_response(vars):
104
    state_utils.set_confidence(vars, 0)
105
    return "Sorry"
106

107

108
##################################################################################################################
109
# let's talk about fast food
110
##################################################################################################################
111

112

113
def is_question(vars):
114
    annotations_sentseg = state_utils.get_last_human_utterance(vars)["annotations"].get("sentseg", {})
115
    flag = "?" in annotations_sentseg.get("punct_sent", "")
116
    return flag
117

118

119
def check_conceptnet(vars):
120
    annotations_conceptnet = get_comet_conceptnet_annotations(state_utils.get_last_human_utterance(vars))
121
    conceptnet = False
122
    food_item = None
123
    for elem, triplets in annotations_conceptnet.items():
124
        conceptnet_symbolof = any([i in triplets.get("SymbolOf", []) for i in CONCEPTNET_SYMBOLOF_FOOD])
125
        conceptnet_hasproperty = any([i in triplets.get("HasProperty", []) for i in CONCEPTNET_HASPROPERTY_FOOD])
126
        causes_desire = triplets.get("CausesDesire", [])
127
        conceptnet_causesdesire = any([i in causes_desire for i in CONCEPTNET_CAUSESDESIRE_FOOD]) or any(
128
            ["eat" in i for i in causes_desire] + ["cook" in i for i in causes_desire]
129
        )
130
        conceptnet = any([conceptnet_symbolof, conceptnet_hasproperty, conceptnet_causesdesire])
131
        if conceptnet:
132
            food_item = elem
133
            return conceptnet, food_item
134
    return conceptnet, food_item
135

136

137
def dont_want_talk(vars):
138
    utt = state_utils.get_last_human_utterance(vars)["text"]
139
    flag = bool(re.search(COMPILE_NOT_WANT_TO_TALK_ABOUT_IT, utt))
140
    logger.info(f"dont_want_talk {flag}")
141
    return flag
142

143

144
def smth_request(ngrams, vars):
145
    flag = condition_utils.no_requests(vars) and (not dont_want_talk(vars))
146
    logger.info(f"smth_request {flag}")
147
    return flag
148

149

150
def fast_food_request(ngrams, vars):
151
    if all([not condition_utils.no_requests(vars), dont_want_talk(vars), is_question(vars)]):
152
        flag = False
153
    else:
154
        flag = True
155
    logger.info(f"fast_food_request {flag}")
156
    return flag
157

158

159
def fast_food_response(vars):
160
    try:
161
        shared_memory = state_utils.get_shared_memory(vars)
162
        used_facts = shared_memory.get("fast_food_facts", [])
163
        unused_facts = [i for i in FAST_FOOD_FACTS if i not in used_facts]
164
        used_questions = shared_memory.get("fast_food_questions", [])
165
        unused_questions = [i for i in FAST_FOOD_QUESTIONS if i not in used_questions]
166
        fact = ""
167
        question = ""
168
        if unused_facts:
169
            fact = random.choice(unused_facts)
170
            state_utils.save_to_shared_memory(vars, fast_food_facts=used_facts + [fact])
171
        if unused_questions:
172
            question = random.choice(unused_questions)
173
            state_utils.save_to_shared_memory(vars, fast_food_questions=used_questions + [question])
174
        if fact and question:
175
            state_utils.set_confidence(vars, confidence=CONF_MIDDLE)
176
            state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_PROMPT)
177
            return f"I just found out that {fact} {question}"
178
        else:
179
            state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE)
180
            return error_response(vars)
181
    except Exception as exc:
182
        logger.exception(exc)
183
        sentry_sdk.capture_exception(exc)
184
        return error_response(vars)
185

186

187
def what_eat_response(vars):
188
    try:
189
        shared_memory = state_utils.get_shared_memory(vars)
190
        used_questions = shared_memory.get("fast_food_what_questions", [])
191
        question = random.choice([i for i in FAST_FOOD_WHAT_QUESTIONS if i not in used_questions])
192
        user_utt = state_utils.get_last_human_utterance(vars)["text"].lower()
193
        bot_utt = state_utils.get_last_bot_utterance(vars)["text"].lower()
194
        state_utils.save_to_shared_memory(vars, fast_food_what_questions=used_questions + [question])
195
        if "how often" in bot_utt:
196
            if any([i in user_utt for i in ["times", "every"]]):
197
                question = "Not so often as some people do! " + question
198
            else:
199
                question = "Okay. " + question
200
        state_utils.set_confidence(vars, confidence=CONF_HIGH)
201
        state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_PROMPT)
202
        return question
203
    except Exception as exc:
204
        logger.exception(exc)
205
        sentry_sdk.capture_exception(exc)
206
        return error_response(vars)
207

208

209
def fav_food_request(ngrams, vars):
210
    flag = False
211
    user_fav_food = get_entities(state_utils.get_last_human_utterance(vars), only_named=False, with_labels=False)
212
    food_words_search = re.search(FOOD_WORDS_RE, state_utils.get_last_human_utterance(vars)["text"])
213
    if all(
214
        [
215
            any([user_fav_food, check_conceptnet(vars), food_words_search]),
216
            condition_utils.no_requests(vars),
217
            not re.search(NO_WORDS_RE, state_utils.get_last_human_utterance(vars)["text"]),
218
        ]
219
    ):
220
        flag = True
221
    logger.info(f"fav_food_request {flag}")
222
    return flag
223

224

225
def food_fact_response(vars):
226
    acknowledgements = ["I like it too.", "I'm not fond of it.", "It's awesome.", "Fantastic.", "Loving it.", "Yummy!"]
227
    human_utt = state_utils.get_last_human_utterance(vars)
228
    annotations = human_utt["annotations"]
229
    human_utt_text = human_utt["text"].lower()
230
    bot_utt_text = state_utils.get_last_bot_utterance(vars)["text"].lower()
231

232
    fact = ""
233
    berry_name = ""
234
    entity = ""
235
    facts = annotations.get("fact_random", [])
236
    if "berry" in bot_utt_text:
237
        berry_names = get_entities(state_utils.get_last_human_utterance(vars), only_named=False, with_labels=False)
238
        if berry_names:
239
            berry_name = berry_names[0]
240

241
        if all(["berry" not in human_utt_text, len(human_utt_text.split()) == 1, berry_name]):
242
            berry_name += "berry"
243
            fact = get_fact(berry_name, f"fact about {berry_name}")
244
            entity = berry_name
245
        elif berry_name:
246
            if facts:
247
                fact = facts[0].get("fact", "")
248
                entity = facts[0].get("entity_substr", "")
249
    else:
250
        if facts:
251
            fact = facts[0].get("fact", "")
252
            entity = facts[0].get("entity_substr", "")
253
    try:
254
        state_utils.set_confidence(vars, confidence=CONF_MIDDLE)
255
        if re.search(DONOTKNOW_LIKE_RE, human_utt_text):
256
            state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE)
257
            return error_response(vars)
258
        # "I have never heard about it. Could you tell me more about that please."
259
        elif (not fact) and check_conceptnet(vars):
260
            state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_SCENARIO)
261
            return "I haven't tried yet. Why do you like it?"
262
        elif not fact:
263
            state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE)
264
            return error_response(vars)
265
        elif fact and entity:
266
            state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_SCENARIO)
267
            return f"{entity}. {random.choice(acknowledgements)} {fact}"
268
        elif fact:
269
            state_utils.set_can_continue(vars, continue_flag=CAN_CONTINUE_SCENARIO)
270
            return f"Okay. {fact}"
271
        else:
272
            state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE)
273
            return error_response(vars)
274
    except Exception as exc:
275
        logger.exception(exc)
276
        sentry_sdk.capture_exception(exc)
277
        return error_response(vars)
278

279

280
def where_are_you_from_response(vars):
281
    try:
282
        state_utils.set_confidence(vars, confidence=CONF_LOW)
283
        state_utils.set_can_continue(vars, continue_flag=CAN_NOT_CONTINUE)
284
        return "Where are you from?"
285
    except Exception as exc:
286
        logger.exception(exc)
287
        sentry_sdk.capture_exception(exc)
288
        return error_response(vars)
289

290

291
##################################################################################################################
292
##################################################################################################################
293
# linking
294
##################################################################################################################
295
##################################################################################################################
296

297

298
##################################################################################################################
299
#  START
300
simplified_dialogflow.add_user_transition(State.USR_START, State.SYS_SAID_FAV_FOOD, fast_food_request)
301
simplified_dialogflow.set_error_successor(State.USR_START, State.SYS_ERR)
302

303

304
##################################################################################################################
305

306
simplified_dialogflow.add_system_transition(State.SYS_SAID_FAV_FOOD, State.USR_HOW_OFTEN, fast_food_response)
307
simplified_dialogflow.set_error_successor(State.SYS_SAID_FAV_FOOD, State.SYS_ERR)
308

309

310
simplified_dialogflow.add_user_transition(State.USR_HOW_OFTEN, State.SYS_HOW_OFTEN, smth_request)
311
simplified_dialogflow.set_error_successor(State.USR_HOW_OFTEN, State.SYS_ERR)
312

313

314
simplified_dialogflow.add_system_transition(State.SYS_HOW_OFTEN, State.USR_WHAT_EAT, what_eat_response)
315
simplified_dialogflow.set_error_successor(State.SYS_HOW_OFTEN, State.SYS_ERR)
316

317

318
simplified_dialogflow.add_user_serial_transitions(
319
    State.USR_WHAT_EAT,
320
    {
321
        State.SYS_FOOD_CHECK: fav_food_request,
322
        State.SYS_SMTH_ELSE: smth_request,
323
    },
324
)
325
simplified_dialogflow.set_error_successor(State.USR_WHAT_EAT, State.SYS_ERR)
326

327

328
simplified_dialogflow.add_system_transition(State.SYS_FOOD_CHECK, State.USR_FAST_FOOD_FACT, food_fact_response)
329
simplified_dialogflow.set_error_successor(State.SYS_FOOD_CHECK, State.SYS_ERR)
330

331

332
simplified_dialogflow.add_user_transition(State.USR_FAST_FOOD_FACT, State.SYS_SMTH, smth_request)
333
simplified_dialogflow.set_error_successor(State.USR_FAST_FOOD_FACT, State.SYS_ERR)
334

335

336
simplified_dialogflow.add_system_transition(State.SYS_SMTH, State.USR_HOW_OFTEN, fast_food_response)
337
simplified_dialogflow.set_error_successor(State.SYS_SMTH, State.SYS_ERR)
338

339

340
simplified_dialogflow.add_system_transition(State.SYS_SMTH_ELSE, State.USR_LINKTO, where_are_you_from_response)
341
simplified_dialogflow.set_error_successor(State.SYS_SMTH_ELSE, State.SYS_ERR)
342

343

344
#################################################################################################################
345
#  SYS_ERR
346
simplified_dialogflow.add_system_transition(
347
    State.SYS_ERR,
348
    (scopes.MAIN, scopes.State.USR_ROOT),
349
    error_response,
350
)
351
dialogflow = simplified_dialogflow.get_dialogflow()
352

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

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

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

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