dream

Форк
0
190 строк · 6.8 Кб
1
#!/usr/bin/env python
2

3
import logging
4
import time
5
from os import getenv
6
import random
7
import pathlib
8
import datetime
9
import copy
10
import difflib
11

12
from flask import Flask, request, jsonify
13
from healthcheck import HealthCheck
14
import sentry_sdk
15
from sentry_sdk.integrations.logging import ignore_logger
16

17
from common.constants import CAN_NOT_CONTINUE, CAN_CONTINUE_SCENARIO, MUST_CONTINUE
18
from common.universal_templates import is_switch_topic, if_chat_about_particular_topic
19

20
from common.utils import get_skill_outputs_from_dialog, is_yes
21
from common.game_cooperative_skill import game_skill_was_proposed, GAMES_COMPILED_PATTERN, FALLBACK_ACKN_TEXT
22
from common.gaming import find_games_in_text
23
from common.dialogflow_framework.programy.text_preprocessing import clean_text
24

25
from router import run_skills as skill
26

27

28
ignore_logger("root")
29

30
sentry_sdk.init(getenv("SENTRY_DSN"))
31
DB_FILE = pathlib.Path(getenv("DB_FILE", "/data/game-cooperative-skill/game_db.json"))
32
MEMORY_LENGTH = 3
33

34
logging.basicConfig(format="%(asctime)s - %(pathname)s - %(lineno)d - %(levelname)s - %(message)s", level=logging.INFO)
35
logger = logging.getLogger(__name__)
36

37
app = Flask(__name__)
38
health = HealthCheck(app, "/healthcheck")
39
logging.getLogger("werkzeug").setLevel("WARNING")
40

41

42
# add your own check function to the healthcheck
43
def db_is_updated():
44
    curr_date = datetime.datetime.now()
45
    min_update_time = datetime.timedelta(hours=25)
46
    if DB_FILE.exists():
47
        file_modification_time = datetime.datetime.fromtimestamp(DB_FILE.lstat().st_mtime)
48
        data_is_expired = curr_date - min_update_time > file_modification_time
49
        msg = "db is expired" if data_is_expired else "db is updated"
50
        msg += f", last modified date of db is {file_modification_time.strftime('%m/%d/%Y, %H:%M:%S')}"
51
        if data_is_expired:
52
            sentry_sdk.capture_message(msg)
53
        return True, msg
54
    else:
55
        msg = "db file is not created"
56
        logger.error(msg)
57
        sentry_sdk.capture_message(msg)
58
        return False, msg
59

60

61
health.add_check(db_is_updated)
62

63

64
def get_agent_intents(last_utter):
65
    annotations = last_utter.get("annotations", {})
66
    agent_intents = {}
67
    for intent_name, intent_detector in annotations.get("intent_catcher", {}).items():
68
        if intent_detector.get("detected", 0) == 1:
69
            agent_intents[intent_name] = True
70

71
    if not agent_intents.get("topic_switching") and (
72
        is_switch_topic(last_utter)
73
        or agent_intents.get("exit")
74
        or agent_intents.get("stupid")
75
        or agent_intents.get("cant_do")
76
        or agent_intents.get("tell_me_a_story")
77
        or agent_intents.get("weather_forecast_intent")
78
        or agent_intents.get("what_can_you_do")
79
        or agent_intents.get("what_is_your_job")
80
        or agent_intents.get("what_is_your_name")
81
        or agent_intents.get("what_time")
82
    ):
83
        agent_intents["topic_switching"] = True
84
    return agent_intents
85

86

87
@app.route("/respond", methods=["POST"])
88
def respond():
89
    dialogs_batch = [None]
90
    st_time = time.time()
91
    dialogs_batch = request.json["dialogs"]
92
    rand_seed = request.json.get("rand_seed")
93

94
    responses = []
95
    for dialog in dialogs_batch:
96
        prev_skill_outputs = get_skill_outputs_from_dialog(
97
            dialog["utterances"][-MEMORY_LENGTH:], "game_cooperative_skill", activated=True
98
        )
99
        is_active_last_answer = bool(prev_skill_outputs)
100
        human_attr = dialog["human"]["attributes"]
101
        prev_state = human_attr.get("game_cooperative_skill", {}).get("state", {})
102
        try:
103
            state = copy.deepcopy(prev_state)
104
            if state and not is_active_last_answer:
105
                state["messages"] = []
106
            # pre_len = len(state.get("messages", []))
107

108
            last_utter = dialog["human_utterances"][-1]
109

110
            last_utter_text = last_utter["text"].lower()
111
            agent_intents = get_agent_intents(last_utter)
112

113
            # for tests
114
            attr = {}
115
            if rand_seed:
116
                random.seed(int(rand_seed))
117
            response, state = skill([last_utter_text], state, agent_intents)
118

119
            # logger.info(f"state = {state}")
120
            # logger.info(f"last_utter_text = {last_utter_text}")
121
            # logger.info(f"response = {response}")
122
            bot_utterance = dialog["bot_utterances"][-1] if dialog["bot_utterances"] else {}
123
            text = response.get("text", "Sorry")
124
            if not response.get("confidence"):
125
                confidence = 0
126
            elif (
127
                not is_active_last_answer
128
                and if_chat_about_particular_topic(
129
                    dialog["human_utterances"][-1],
130
                    bot_utterance,
131
                    compiled_pattern=GAMES_COMPILED_PATTERN,
132
                )
133
                and find_games_in_text(last_utter_text)
134
            ):
135
                confidence = 0
136
            elif not is_active_last_answer and if_chat_about_particular_topic(
137
                dialog["human_utterances"][-1],
138
                bot_utterance,
139
                compiled_pattern=GAMES_COMPILED_PATTERN,
140
            ):
141
                confidence = 1
142
            elif is_active_last_answer:
143
                confidence = 1
144
            elif is_yes(dialog["human_utterances"][-1]) and game_skill_was_proposed(bot_utterance):
145
                confidence = 1
146
            elif not is_yes(dialog["human_utterances"][-1]) and game_skill_was_proposed(bot_utterance):
147
                confidence = 0.95
148
                text = FALLBACK_ACKN_TEXT
149
                state = prev_state
150
            elif GAMES_COMPILED_PATTERN.search(last_utter_text) and not is_active_last_answer:
151
                confidence = 0.98
152
            else:
153
                confidence = 0
154

155
            curr_text = clean_text(text.lower())
156
            last_text = clean_text(bot_utterance.get("text", "").lower())
157
            ratio = difflib.SequenceMatcher(None, curr_text.split(), last_text.split()).ratio()
158

159
            if ratio > 0.95:
160
                confidence = 0
161

162
            if confidence == 1:
163
                can_continue = MUST_CONTINUE
164
            elif confidence > 0.95:
165
                can_continue = CAN_CONTINUE_SCENARIO
166
            else:
167
                can_continue = CAN_NOT_CONTINUE
168

169
            human_attr["game_cooperative_skill"] = {"state": state}
170
            attr["can_continue"] = can_continue
171

172
        except Exception as exc:
173
            sentry_sdk.capture_exception(exc)
174
            logger.exception(exc)
175
            text = ""
176
            confidence = 0.0
177
            human_attr["game_cooperative_skill"] = {"state": prev_state}
178
            attr = {}
179

180
        bot_attr = {}
181
        responses.append((text, confidence, human_attr, bot_attr, attr))
182

183
        total_time = time.time() - st_time
184
        logger.info(f"game_cooperative_skill exec time = {total_time:.3f}s")
185

186
    return jsonify(responses)
187

188

189
if __name__ == "__main__":
190
    app.run(debug=False, host="0.0.0.0", port=3000)
191

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

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

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

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