Skip to content

Commit e594de2

Browse files
mtalimanchukIgnatovFedordilyararimovnakudep
authored
Feat/run tg rework (#114)
Co-authored-by: Fedor Ignatov <[email protected]> Co-authored-by: dilyararimovna <[email protected]> Co-authored-by: Denis Kuznetosv <[email protected]>
1 parent cb78f97 commit e594de2

32 files changed

+823
-267
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
include requirements.txt
22
include deeppavlov_agent/http_api/templates/*.html
33
include deeppavlov_agent/log_config.yml
4+
include deeppavlov_agent/channels/telegram/config/*.yml

deeppavlov_agent/channels/__init__.py

Whitespace-only changes.

deeppavlov_agent/channels/telegram/__init__.py

Whitespace-only changes.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import asyncio
2+
import logging
3+
from pathlib import Path
4+
5+
from aiogram import Bot, Dispatcher, types
6+
from aiogram.contrib.fsm_storage.memory import MemoryStorage
7+
from aiogram.dispatcher import FSMContext
8+
from aiogram.dispatcher.filters.state import State, StatesGroup
9+
from aiogram.utils import executor
10+
11+
from .utils import MessageResponder
12+
13+
config_dir = Path(__file__).resolve().parent / 'config'
14+
15+
logging.basicConfig(
16+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
17+
)
18+
logger = logging.getLogger(__name__)
19+
20+
21+
class DialogState(StatesGroup):
22+
active = State()
23+
awaiting_rating = State()
24+
inactive = State()
25+
26+
27+
def run_tg(token, proxy, agent):
28+
loop = asyncio.get_event_loop()
29+
bot = Bot(token=token, loop=loop, proxy=proxy)
30+
storage = MemoryStorage() # TODO change to actual storage maybe?
31+
dp = Dispatcher(bot, storage=storage)
32+
responder = MessageResponder(
33+
config_path=config_dir / "telegram_config.yml",
34+
messages_path=config_dir / "telegram_messages.yml",
35+
keyboards_path=config_dir / "telegram_keyboards.yml",
36+
)
37+
38+
@dp.message_handler(commands="start")
39+
async def start_handler(message: types.Message):
40+
text = responder.message("start")
41+
reply_markup = responder.reply_keyboard("dialog_inactive")
42+
43+
await message.answer(text, reply_markup=reply_markup)
44+
45+
@dp.message_handler(commands="help", state="*")
46+
async def help_handler(message: types.Message):
47+
text = responder.message("help")
48+
49+
await message.answer(text)
50+
51+
@dp.message_handler(commands="complain", state="*")
52+
async def complain_handler(message: types.Message, state: FSMContext):
53+
# TODO Add actual complaint logic
54+
if await state.get_state() == DialogState.active.state:
55+
text = responder.message("complain_success")
56+
else:
57+
text = responder.message("complain_fail")
58+
59+
await message.answer(text)
60+
61+
@dp.message_handler(commands="begin", state="*")
62+
async def begin_dialog(message: types.Message, state: FSMContext):
63+
state = await state.get_state()
64+
must_evaluate = (
65+
state == DialogState.awaiting_rating.state
66+
and responder.config.evaluation_options.user_must_evaluate
67+
)
68+
is_not_finished = state == DialogState.active
69+
70+
if must_evaluate or is_not_finished:
71+
text = responder.message("begin_fail")
72+
reply_markup = None
73+
74+
else:
75+
await DialogState.active.set()
76+
77+
text = responder.message("begin_success")
78+
reply_markup = responder.reply_keyboard("dialog_active")
79+
80+
await message.answer(text, reply_markup=reply_markup)
81+
82+
@dp.message_handler(commands="end", state="*")
83+
async def end_dialog(message: types.Message, state: FSMContext):
84+
if await state.get_state() != DialogState.active.state:
85+
text = responder.message("end_fail")
86+
reply_markup = responder.reply_keyboard("dialog_inactive")
87+
else:
88+
text = responder.message("end_success")
89+
dialog_id = await agent.state_manager.drop_active_dialog(
90+
str(message.from_user.id)
91+
)
92+
reply_markup = responder.dialog_rating_inline_keyboard(dialog_id)
93+
94+
await DialogState.awaiting_rating.set()
95+
96+
await message.answer(text, reply_markup=reply_markup)
97+
98+
@dp.callback_query_handler(
99+
lambda c: c.data.startswith("utt"), state=DialogState.active
100+
)
101+
async def handle_utterance_rating(
102+
callback_query: types.CallbackQuery, state: FSMContext
103+
):
104+
_, utterance_id, rating = callback_query.data.split("-")
105+
await agent.state_manager.set_rating_utterance(
106+
str(callback_query.from_user.id), utterance_id, rating
107+
)
108+
await bot.answer_callback_query(callback_query.id, text=rating.capitalize())
109+
110+
@dp.callback_query_handler(lambda c: c.data.startswith("dialog"), state="*")
111+
async def handle_dialog_rating(
112+
callback_query: types.CallbackQuery, state: FSMContext
113+
):
114+
if await state.get_state() != DialogState.active.state:
115+
_, dialog_id, rating = callback_query.data.split("-")
116+
117+
await agent.state_manager.set_rating_dialog(
118+
str(callback_query.from_user.id), dialog_id, rating
119+
)
120+
121+
edited_inline_keyboard = responder.dialog_rating_inline_keyboard(
122+
dialog_id, chosen_rating=rating
123+
)
124+
125+
await bot.edit_message_reply_markup(
126+
chat_id=callback_query.from_user.id,
127+
message_id=callback_query.message.message_id,
128+
reply_markup=edited_inline_keyboard,
129+
)
130+
131+
if responder.config.dialog_options.reveal_dialog_id:
132+
message_text = responder.message(
133+
"evaluate_dialog_success_reveal_id", dialog_id=dialog_id
134+
)
135+
else:
136+
message_text = responder.message("evaluate_dialog_success")
137+
callback_text = "Evaluation saved!"
138+
reply_markup = responder.reply_keyboard("dialog_inactive")
139+
140+
await DialogState.inactive.set()
141+
142+
else:
143+
callback_text = ""
144+
message_text = responder.message("evaluate_dialog_success")
145+
reply_markup = None
146+
147+
await bot.answer_callback_query(callback_query.id, text=callback_text)
148+
await bot.send_message(
149+
callback_query.from_user.id, message_text, reply_markup=reply_markup
150+
)
151+
152+
@dp.message_handler(state="*")
153+
async def handle_message(message: types.Message, state: FSMContext):
154+
if await state.get_state() == DialogState.active.state:
155+
response_data = await agent.register_msg(
156+
utterance=message.text,
157+
user_external_id=str(message.from_user.id),
158+
user_device_type="telegram",
159+
date_time=message.date,
160+
location="",
161+
channel_type="telegram",
162+
require_response=True,
163+
)
164+
text = response_data["dialog"].utterances[-1].text
165+
utterance_id = response_data["dialog"].utterances[-1].utt_id
166+
reply_markup = responder.utterance_rating_inline_keyboard(utterance_id)
167+
else:
168+
text = responder.message("unexpected_message")
169+
reply_markup = None
170+
171+
await message.answer(text, reply_markup=reply_markup)
172+
173+
executor.start_polling(dp, skip_updates=True)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dialog_options:
2+
reveal_dialog_id: true
3+
4+
evaluation_options:
5+
user_must_evaluate: true
6+
min_score: 1
7+
max_score: 5
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dialog_inactive:
2+
- '/begin'
3+
- '/help'
4+
5+
dialog_active:
6+
- '/end'
7+
- '/complain'
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
start: >
2+
This chatbot is developed by Neural Networks and Deep Learning Lab at MIPT.
3+
Please have a chat with it and evaluate its performance.
4+
To begin a conversation enter /begin. To end a conversation: enter /end.
5+
When the dialogue is finished, you will be asked to evaluate it.
6+
You will have to rate the conversation from 1 (bad) to 5 (excellent).
7+
Your conversations will be recorded for further use.
8+
By starting a chat you give permission for your anonymized conversation data
9+
to be released publicly under Apache License Version 2.0
10+
https://www.apache.org / licenses / LICENSE – 2.0.
11+
12+
help: >
13+
This chatbot is developed by Neural Networks and Deep Learning Lab at MIPT.
14+
Please have a chat with it and evaluate its performance.
15+
To begin a conversation enter /begin. To end a conversation: enter /end.
16+
When the dialogue is finished, you will be asked to evaluate it.
17+
You will have to rate the conversation from 1 (bad) to 5 (excellent).
18+
Your conversations will be recorded for further use.
19+
By starting a chat you give permission for your anonymized conversation data
20+
to be released publicly under Apache License Version 2.0
21+
https://www.apache.org / licenses / LICENSE – 2.0.
22+
23+
complain_success: >
24+
Your complaint has been recorded and will be examined by the system administrator.
25+
Note that your conversation is still active.
26+
You can always use /end command to end it.
27+
28+
complain_fail: >
29+
Could not save your complaint. Did you /begin the dialog?
30+
You cannot complain when there are no messages in the dialog.
31+
32+
begin_success: >
33+
Starting a dialog. To finish the dialog enter /end.
34+
35+
begin_fail: >
36+
Cannot start a new conversation.
37+
Please finish and evaluate your current dialog first.
38+
Use /help command for usage instructions.
39+
40+
end_success: >
41+
Dialog is finished.
42+
Please evaluate the whole dialog using one of the buttons below:
43+
44+
end_fail: >
45+
You're not in a dialog now.
46+
47+
evaluate_dialog_success: >
48+
Thank you for participation!
49+
50+
evaluate_dialog_success_reveal_id: >
51+
Thank you for participation!
52+
Evaluated dialog secret id: ${dialog_id}
53+
54+
evaluate_dialog_fail: >
55+
Evaluation is not allowed at the moment.
56+
Use /help command for usage instructions.
57+
58+
unexpected_message: >
59+
Unexpected message.
60+
You are not in a dialog yet or the dialog has already been finished.
61+
Use /help command for usage instructions.

0 commit comments

Comments
 (0)