-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
128 lines (96 loc) · 4.46 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import random
import re
import nltk
import json
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, filters
with open("./data/examples_bot_intents.json", "r") as intents_file:
BIG_INTENTS = json.load(intents_file)
INTENTS = BIG_INTENTS["intents"]
x = [] # Фразы
y = [] # Интенты
failure_phrases = BIG_INTENTS['failure_phrases']
for name, intent in INTENTS.items():
for phrase in intent['examples']:
x.append(phrase)
y.append(name)
for phrase in intent['responses']:
x.append(phrase)
y.append(name)
vectorizer = CountVectorizer()
vectorizer.fit(x)
vecX = vectorizer.transform(x)
mlp_model = MLPClassifier(max_iter=500)
mlp_model.fit(vecX, y)
rf_model = RandomForestClassifier()
rf_model.fit(vecX, y)
# Выбираем модель которая лучше обучилась
if mlp_model.score(vecX, y) > rf_model.score(vecX, y):
MODEL = mlp_model
else:
MODEL = rf_model
def get_intent_ml(text):
vec_text = vectorizer.transform([text])
intent_ml = MODEL.predict(vec_text)[0]
return intent_ml
# Функция очистки текста от знаков препинания и лишних пробелов, а так же приведение к нижнему регистру.
def filter_text(text):
text = text.lower().strip()
expression = r'[^\w\s]'
return re.sub(expression, "", text)
# Функция сравнивает текст пользователя с примером и решает похожи ли они
def text_match(user_text, example):
# Убираем все лишнее
user_text = filter_text(user_text)
example = filter_text(example)
if len(user_text) == 0 or len(example) == 0:
return False
example_length = len(example) # Длина фразы example
if example_length == 0:
return False
# На сколько в % отличаются фразы
difference = nltk.edit_distance(user_text, example) / example_length
return difference < 0.2 # Если разница меньше 20%
# Определить намерение по тексту
def get_intent(text):
# Проверить все существующие intent'ы
for intent_name in INTENTS.keys():
examples = INTENTS[intent_name]["examples"]
# Проверить все examples
for example in examples:
# Какой-нибудь один будет иметь example похожий на text
if text_match(text, example):
return intent_name
# Берёт случайный response для данного intent'а
def get_response(intent):
return random.choice(INTENTS[intent]["responses"])
# Сам бот
def bot(text):
text = filter_text(text)
intent = get_intent(text) # Найти намерение
if not intent: # Если намерение не найдено
intent = get_intent_ml(text) # Пробуем подключить МЛ модель
if intent: # Если нашлось в итоге, выводим ответ
return get_response(intent)
else:
return random.choice(failure_phrases) # Выводим случайную заглушку из фраз ошибок
# Приветствие пользователя по команде /start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text(f'Hello {update.effective_user.first_name}')
# Функция для MessageHandler'а, вызывать ее при каждом сообщении боту
async def reply(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
question = update.message.text
reply_t = bot(question)
await update.message.reply_text(reply_t) # Ответ пользователю
TOKEN = 'Your token' # Get your token from BotFather
app = ApplicationBuilder().token(TOKEN).build()
# Добавляем обработчик /start
app.add_handler(CommandHandler("start", start))
# Создаем обработчик текстовых сообщений
handler = MessageHandler(filters.Text(), reply)
app.add_handler(handler) # Добавляем обработчик в приложение
# Запускаем опрос Telegram
app.run_polling()