Compare commits

..

5 Commits

Author SHA1 Message Date
f69e664e04 Fix 2021-06-15 10:05:49 +02:00
508508a416 Delete meeeting fix 2021-06-15 09:43:04 +02:00
bf1c7b95fd Meeting list hotfix 2021-06-15 09:34:09 +02:00
af98dabec7 Meeting list functionality connected to DB 2021-06-15 09:25:48 +02:00
6e4e1271c4 Basic connection of DB 2021-06-14 17:27:27 +02:00
8 changed files with 266 additions and 351 deletions

View File

@ -43,6 +43,10 @@ class calender_db:
with open(self.db_file_path, 'r+') as f:
self.db = json.load(f)
def clear_db(self):
self.db = {}
self.save_db()
def save_db(self):
with open(self.db_file_path, 'w+') as f:
json.dump(self.db, f)
@ -72,19 +76,10 @@ class calender_db:
self.db[format_date(date_time)] = meetings
self.save_db()
def update_meeting(self, meeting_dict):
date_time = get_date(
meeting_dict['date'].lower(), meeting_dict['time'].lower())
if format_date(date_time) in self.db.keys():
meetings = self.db[format_date(date_time)]
for key, meeting in enumerate(meetings):
if format_time(meeting['time']) == format_time(meeting_dict['time'].lower()):
meetings.remove(meeting)
meetings.append(meeting_dict)
self.db[format_date(date_time)] = meetings
self.save_db()
def update_meeting(self, old_meeting_date, old_meeting_time, new_meeting_dict):
self.delete_meeting(old_meeting_date, old_meeting_time)
self.create_meeting(new_meeting_dict)
def find_meeting(self, date, time):
if date in self.db.keys():
@ -180,10 +175,15 @@ class calender_db:
# Tests
# db = calender_db()
# db.create_meeting({"date": "16.06.2021", "time": "15:00",
# "description": "chuj"})
# db.clear_db()
# db.create_meeting({"date": "16.06.2021", "time": "15:00", "description": "ciastko"})
# db.create_meeting({"date": "14.06.2021", "time": "13:00-18:00"})
# db.delete_meeting("16.06.2021", "15:00")
# print(db.find_meeting("16.06.2021", "13:00-14:00"))
# print(db.get_meetings(["16.06.2021", "14.06.2021"]))
# print(db.is_collision("16.06.2021", "12:30-13"))
#db.create_meeting({"date": "16.06.2021", "time": "12:00-13:00", "description": "costam"})
#print(db.get_meetings(["16.06.2021", "14.06.2021"]))
#db.update_meeting("16.06.2021", "12:00-13:00", {"date": "14.06.2021", "time": "11:00-12:00"})
#print(db.get_meetings(["16.06.2021", "14.06.2021"]))
#db.delete_meeting("16.06.2021", "15:00")
#print(db.find_meeting("16.06.2021", "13:00-14:00"))
#print(db.get_meetings(["16.06.2021", "14.06.2021"]))
#print(db.is_collision("16.06.2021", "12:30-13"))
#db.clear_db()

View File

@ -5,11 +5,18 @@ from collections import defaultdict
class DP:
def __init__(self, dst):
"""
Moduł decydujący o wyborze kolejnego aktu, który ma podjąć system prowadząc rozmowę.
Wejście: Reprezentacja stanu dialogu (rama)
Wyjście: Akt systemu (rama)
"""
def __init__(self, dst, db):
self.DST = dst
self.DB = db
self.meeting_to_update = False
def choose_tactic(self) -> SystemAct:
def chooseTactic(self) -> SystemAct:
dialogue_state, last_user_act, last_system_act = self.DST.get_dialogue_state()
slots = self.DST.get_dialogue_slots()
# stan dodawania spotkania
@ -65,6 +72,7 @@ class DP:
self.DST.system_update(system_act)
return system_act
else:
# TODO sprawdzanie czy spotkanie nie koliduje
system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, slots)
self.DST.system_update(system_act)
return system_act
@ -72,6 +80,7 @@ class DP:
if last_user_act == UserActType.CONFIRM:
system_act = SystemAct(SystemActType.AFFIRM, ['create_meeting'])
# implementacja wpisywanie spotkania do bazy
self.DB.create_meeting(slots)
self.DST.clear()
return system_act
elif last_user_act == UserActType.NEGATE:
@ -83,11 +92,11 @@ class DP:
elif dialogue_state == UserActType.UPDATE_MEETING:
if not last_system_act:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date', False])
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time', False])
system_act = SystemAct(SystemActType.REQUEST, ['time'])
self.DST.system_update(system_act)
return system_act
else:
@ -96,11 +105,11 @@ class DP:
elif last_system_act.getActType() == SystemActType.REQUEST:
if not self.meeting_to_update:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date', False])
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time', False])
system_act = SystemAct(SystemActType.REQUEST, ['time'])
self.DST.system_update(system_act)
return system_act
else:
@ -113,23 +122,23 @@ class DP:
slot_type = last_system_act.getActParams()[0]
self.DST.insert_empty_slot(slot_type)
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time', True])
system_act = SystemAct(SystemActType.REQUEST, ['time'])
self.DST.system_update(system_act)
return system_act
elif 'place' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['place', True])
system_act = SystemAct(SystemActType.REQUEST, ['place'])
self.DST.system_update(system_act)
return system_act
elif 'description' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['description', True])
system_act = SystemAct(SystemActType.REQUEST, ['description'])
self.DST.system_update(system_act)
return system_act
elif 'participants' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['participants', True])
system_act = SystemAct(SystemActType.REQUEST, ['participants'])
self.DST.system_update(system_act)
return system_act
else:
@ -138,23 +147,23 @@ class DP:
return system_act
else:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time', True])
system_act = SystemAct(SystemActType.REQUEST, ['time'])
self.DST.system_update(system_act)
return system_act
elif 'place' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['place', True])
system_act = SystemAct(SystemActType.REQUEST, ['place'])
self.DST.system_update(system_act)
return system_act
elif 'description' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['description', True])
system_act = SystemAct(SystemActType.REQUEST, ['description'])
self.DST.system_update(system_act)
return system_act
elif 'participants' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['participants', True])
system_act = SystemAct(SystemActType.REQUEST, ['participants'])
self.DST.system_update(system_act)
return system_act
else:
@ -174,7 +183,7 @@ class DP:
if last_user_act == UserActType.CONFIRM:
self.meeting_to_update = True
self.DST.clear_slots()
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
elif last_user_act == UserActType.NEGATE:
@ -195,7 +204,10 @@ class DP:
return system_act
else:
# implementacja wyszukiwania odpowiedniego spotkania w bazie
system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, ['meeting_to_cancel'])
slots_to_delete = self.DB.find_meeting(slots['date'], slots['time'])
self.DST.update_slots(slots_to_delete)
#system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, ['meeting_to_cancel'])
system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, slots_to_delete)
self.DST.system_update(system_act)
return system_act
elif last_system_act.getActType() == SystemActType.REQUEST:
@ -209,13 +221,17 @@ class DP:
return system_act
else:
# implementacja wyszukiwania odpowiedniego spotkania w bazie
system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, ['meeting_to_cancel'])
slots_to_delete = self.DB.find_meeting(slots['date'], slots['time'])
self.DST.update_slots(slots_to_delete)
# system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, ['meeting_to_cancel'])
system_act = SystemAct(SystemActType.CONFIRM_DOMAIN, slots_to_delete)
self.DST.system_update(system_act)
return system_act
elif last_system_act.getActType() == SystemActType.CONFIRM_DOMAIN:
if last_user_act == UserActType.CONFIRM:
system_act = SystemAct(SystemActType.AFFIRM, ['cancel_meeting'])
# implementacja usuwania spotkania z bazy
self.DB.delete_meeting(slots['date'], slots['time'])
self.DST.clear()
return system_act
elif last_user_act == UserActType.NEGATE:
@ -225,17 +241,42 @@ class DP:
return SystemAct(SystemActType.NOT_UNDERSTOOD, [])
# stan prośby o listę spotkań
elif dialogue_state == UserActType.MEETING_LIST:
if last_user_act == UserActType.NEGATE:
self.DST.clear()
return SystemAct(SystemActType.REQMORE, ['meeting_list'])
else:
if 'date' in slots:
system_act = SystemAct(SystemActType.MEETING_LIST, {'date': slots['date']})
return system_act
else:
if not last_system_act:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
else:
# implementacja wyszukiwania spotkań w bazie
meetings_slots = self.DB.get_meetings([slots['date']])
system_act = SystemAct(SystemActType.MEETING_LIST, meetings_slots)
self.DST.system_update(system_act)
return system_act
elif last_system_act.getActType() == SystemActType.REQUEST:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date'])
self.DST.system_update(system_act)
return system_act
else:
# implementacja wyszukiwania spotkań w bazie
meetings_slots = self.DB.get_meetings([slots['date']])
system_act = SystemAct(SystemActType.MEETING_LIST, meetings_slots)
self.DST.system_update(system_act)
return system_act
else:
return SystemAct(SystemActType.NOT_UNDERSTOOD, [])
# if last_user_act == UserActType.NEGATE:
# self.DST.clear()
# return SystemAct(SystemActType.REQMORE, ['meeting_list'])
# else:
# if 'date' in slots:
# system_act = SystemAct(SystemActType.MEETING_LIST, slots)
# self.DST.clear()
# return system_act
# else:
# system_act = SystemAct(SystemActType.REQUEST, ['date'])
# self.DST.system_update(system_act)
# return system_act
# stan prośby o czas wolny
elif dialogue_state == UserActType.FREE_TIME:
if last_user_act == UserActType.NEGATE:
@ -243,7 +284,8 @@ class DP:
return SystemAct(SystemActType.REQMORE, ['free_time'])
else:
if 'date' in slots:
system_act = SystemAct(SystemActType.FREE_TIME, {'date': slots['date']})
system_act = SystemAct(SystemActType.FREE_TIME, slots)
self.DST.clear()
return system_act
else:
system_act = SystemAct(SystemActType.REQUEST, ['date'])

View File

@ -4,6 +4,12 @@ from UserAct import UserAct
class DST:
"""
Moduł odpowiedzialny za śledzenie stanu dialogu. Przechowuje informacje o tym jakie dane zostały uzyskane od użytkownika w toku prowadzonej konwersacji.
Wejście: Akt użytkownika (rama)
Wyjście: Reprezentacja stanu dialogu (rama)
"""
def __init__(self):
self.state = None
self.last_user_act = None
@ -39,6 +45,9 @@ class DST:
def clear_slots(self):
self.slots = {}
def update_slots(self, slots):
self.slots = slots
def get_dialogue_state(self):
return self.state, self.last_user_act, self.last_system_act

View File

@ -1,143 +1,175 @@
from SystemAct import SystemAct
from SystemActType import SystemActType
from UserActType import UserActType
import random
class NLG:
"""
Moduł, który tworzy reprezentację tekstową aktu systemowego wybranego przez taktykę dialogu.
Wejście: Akt systemu (rama)
Wyjście: Tekst
"""
def __init__(self, dst):
self.DST = dst
def format_meeting(self, date, time, place, participants, description, format_type):
if participants:
participants = ', '.join(participants)
if format_type == 'create':
return f'Data: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {participants}\nOpis: {description}'.replace('None', 'BRAK')
elif format_type == 'update':
return f'Data: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {participants}\nOpis: {description}'.replace('None', 'BEZ ZMIAN')
else:
return f'Data: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {participants}\nOpis: {description}'
def generate_response(self, systemAct: SystemAct) -> str:
dialogue_state, _, _ = self.DST.get_dialogue_state()
def generateResponse(self, systemAct: SystemAct) -> str:
dialogue_state, _, last_system_act = self.DST.get_dialogue_state()
slots = self.DST.get_dialogue_slots()
if dialogue_state == UserActType.CREATE_MEETING:
if systemAct.getActType() == SystemActType.REQUEST:
if 'date' in systemAct.getActParams():
return random.choice(['W jakim dniu ma się odbyć to spotkanie?', 'Jakiego dnia odbędzie się to spotkanie?'])
elif 'time' in systemAct.getActParams():
return random.choice(['W jakim czasie ma się zacząć to spotkanie?', 'O której godzinie rozpoczyna się to spotkanie?'])
elif 'place' in systemAct.getActParams():
return random.choice(['W jakim miejscu odbywać się będzie to spotkanie?', 'Gdzie ma się odbyć to spotkanie?'])
elif 'description' in systemAct.getActParams():
return random.choice(['Czy mam dodać jakiś opis do tego spotkania?', 'Czy to spotkanie ma posiadać jakiś opis?'])
elif 'participants' in systemAct.getActParams():
return random.choice(['Kto będzie brał udział w spotkaniu?', 'Kto będzie uczestnikiem tego spotkania?'])
elif systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
slots = systemAct.getActParams()
meeting = self.format_meeting(slots['date'], slots['time'], slots['place'], slots['participants'], slots['description'], 'create')
return random.choice([f'Czy mam dodać te spotkanie do kalendarza?\n{meeting}', f'Czy chcesz, abym dodał to spotkanie do kalendarza?\n{meeting}'])
elif dialogue_state == UserActType.UPDATE_MEETING:
if systemAct.getActType() == SystemActType.REQUEST:
if False in systemAct.getActParams():
if 'date' in systemAct.getActParams():
return random.choice(['W jakim dniu odbywa się spotkanie, które chcesz edytować?', 'Podaj datę spotkania, które chcesz zmienić.'])
elif 'time' in systemAct.getActParams():
return random.choice(['O której godzinie zaczyna się spotkanie, które chcesz zmienić?', 'Podaj godzinę spotkania, które chcesz edytować.'])
elif True in systemAct.getActParams():
if 'date' in systemAct.getActParams():
slot_name = 'datę'
slot_question = 'podaj nową datę.'
elif 'time' in systemAct.getActParams():
slot_name = 'godzinę'
slot_question = 'podaj nową godzinę rozpoczęcia tego spotkania.'
elif 'place' in systemAct.getActParams():
slot_name = 'miejsce'
slot_question = 'podaj nowe miejsce, w jakim odbywa się to spotkanie.'
elif 'description' in systemAct.getActParams():
slot_name = 'opis'
slot_question = 'podaj nowy opis tego spotkania.'
else:
slot_name = 'uczestników'
slot_question = 'podaj kim będą nowi uczestnicy tego spotkania.'
return f'Czy chcesz zmienić {slot_name} tego spotkania? Jeśli tak, to {slot_question}'
if "date" in systemAct.getActParams():
return "W jakim dniu ma się odbyć to spotkanie?"
if "time" in systemAct.getActParams():
return "W jakim czasie ma się odbyć to spotkanie?"
if "place" in systemAct.getActParams():
return "Gdzie ma się odbyć to spotkanie?"
if "description" in systemAct.getActParams():
return "Czy mam dodać jakiś opis do tego spotkania?"
if "participants" in systemAct.getActParams():
return "Kto ma wziąć udział w spotkaniu?"
if systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
if 'meeting_to_update' in systemAct.getActParams():
response = random.choice([f'Czy to jest spotkanie które chcesz edytować?', f'Czy chcesz wprowadzić zmiany do następującego spotkania?'])
# TODO: pokazać prawdziwe spotkanie po ew. dodaniu DB
meeting = self.format_meeting('24.06.2021', '10:00', 'Kawiarnia Portowa', ['Andrzej Duda', 'Aleksander Kwaśniewski'], 'Spotkanie biznesowe w sprawie tarczy antyrakietowej', None)
return f'{response}\n{meeting}'
date = slots['date']
time = slots['time']
place = slots['place']
part_list = slots['participants']
part = ""
if part_list is None:
part = None
else:
slots = systemAct.getActParams()
meeting = self.format_meeting(slots['date'], slots['time'], slots['place'], slots['participants'], slots['description'], 'update')
return random.choice([f'Czy chcesz wprowadzić następujące zmiany do tego spotkania?\n{meeting}', f'Czy potwierdzasz następujące zmiany w tym spotkaniu?\n{meeting}'])
for p in part_list:
part += p
part += ", "
part = part[:-2]
desc = slots['description']
return f'Czy mam dodać te spotkanie do kalendarza?\n' \
f'Dzień: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {part}\nOpis: {desc}'
# TODO: nie sprawdzone - trudno wejść do tego stanu
elif dialogue_state == UserActType.UPDATE_MEETING:
# TODO zaślepka do wywalenia
response = "Przepraszam ale obecnie nie obsługuje jeszcze tej funkcji :("
self.DST.clear()
return response
# -------------------------------------
if systemAct.getActType() == SystemActType.REQUEST:
if "date" in systemAct.getActParams():
return "W jakim dniu miało się odbyć to spotkanie?"
if "time" in systemAct.getActParams():
return "W jakim czasie miało się odbyć to spotkanie?"
# TODO dopracować po dodaniu DB
if systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
date = slots['date']
time = slots['time']
place = slots['place']
part_list = slots['participants']
part = ""
if part_list is None:
part = None
else:
for p in part_list:
part += p
part += ", "
part = part[:-2]
desc = slots['description']
return f'Spotkanie:\n' \
f'Dzień: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {part}\nOpis: {desc}'
elif dialogue_state == UserActType.CANCEL_MEETING:
if systemAct.getActType() == SystemActType.REQUEST:
if 'date' in systemAct.getActParams():
return random.choice(['W jakim dniu odbywa się spotkanie, które chcesz anulować?', 'Podaj datę spotkania, które chcesz usunąć z kalendarza.'])
elif 'time' in systemAct.getActParams():
return random.choice(['O której godzinie zaczyna się spotkanie, które chcesz usunąć z kalendarza?', 'Podaj godzinę spotkania, które chcesz anulować.'])
# TODO dopracować po dodaniu DB
if "date" in systemAct.getActParams():
return "W jakim dniu miało się odbyć to spotkanie?"
if "time" in systemAct.getActParams():
return "W jakim czasie miało się odbyć to spotkanie?"
if systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
response = random.choice([f'Czy na pewno chcesz anulować następujące spotkanie?', f'Czy potwierdzasz usunięcie następującego spotkania?'])
# TODO: pokazać prawdziwe spotkanie po ew. dodaniu DB
meeting = self.format_meeting('24.06.2021', '10:00', 'Kawiarnia Portowa', ['Andrzej Duda', 'Aleksander Kwaśniewski'], 'Spotkanie biznesowe w sprawie tarczy antyrakietowej', None)
return f'{response}\n{meeting}'
date = slots['date']
time = slots['time']
place = slots['place']
part_list = slots['participants']
part = ""
if part_list is None:
part = None
else:
for p in part_list:
part += p
part += ", "
part = part[:-2]
desc = slots['description']
return f'Odwołać te spotkanie?:\n' \
f'Dzień: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {part}\nOpis: {desc}'
elif dialogue_state == UserActType.MEETING_LIST:
if systemAct.getActType() == SystemActType.REQUEST:
if "date" in systemAct.getActParams():
return random.choice(['Z jakiego dnia chcesz przejrzeć spotkania?', 'Spotkania z jakiego dnia chciałbyś zobaczyć?'])
elif systemAct.getActType() == SystemActType.MEETING_LIST:
date = systemAct.getActParams()['date']
response = random.choice([f'Dnia {date} masz zaplanowane następujące spotkania:', f'W dniu {date} odbywają się następujące spotkania:'])
# TODO: pokazać prawdziwe spotkania po ew. dodaniu DB
meetings = self.format_meeting(date, '10:00', 'Kawiarnia Portowa', ['Andrzej Duda', 'Aleksander Kwaśniewski'], 'Spotkanie biznesowe w sprawie tarczy antyrakietowej', None)
return "Z jakiego okresu chcesz przejrzeć spotkania?"
if systemAct.getActType() == SystemActType.MEETING_LIST:
response = ""
for s in last_system_act.getActParams():
date = s['date']
time = s['time']
place = s['place']
part_list = s['participants']
part = ""
if part_list is None:
part = None
else:
for p in part_list:
part += p
part += ", "
part = part[:-2]
desc = s['description']
response += f'\nSpotkanie:\nDzień: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {part}\nOpis: {desc}\n'
response += "--------------------"
self.DST.clear()
return f'{response}\n{meetings}'
return response
elif dialogue_state == UserActType.FREE_TIME:
# TODO zaślepka do wywalenia
response = "Przepraszam ale obecnie nie obsługuje jeszcze tej funkcji :("
self.DST.clear()
return response
#-------------------------------------
if systemAct.getActType() == SystemActType.REQUEST:
if 'date' in systemAct.getActParams():
return random.choice(['Z jakiego dnia chcesz zobaczyć wolne godziny?', 'Z jakiego dnia chciałbyś zobaczyć godziny, w których nie masz spotkań?'])
elif systemAct.getActType() == SystemActType.FREE_TIME:
date = systemAct.getActParams()['date']
response = random.choice([f'W następujących godzinach, dnia {date} nie masz zaplanowanych spotkań:', f'W dniu {date} następujące godziny są wolne od spotkań:'])
# TODO: pokazać prawdziwe godziny po ew. dodaniu DB
meeting_hours = '00:00-08:00\n10:00-16:00\n18:00-24:00'
self.DST.clear()
return f'{response}\n{meeting_hours}'
if "date" in systemAct.getActParams():
return "W jakim okresie chcesz znaleźć wolny czas?"
# TODO: dopracować po dodaniu DB
if systemAct.getActType() == SystemActType.FREE_TIME:
response = ""
for s in slots:
date = s['date']
time = s['time']
response += f'Spotkanie:\nDzień: {date}\nCzas: {time}\n'
return response
elif systemAct.getActType() == SystemActType.AFFIRM:
if "create_meeting" in systemAct.getActParams():
return "Spotkanie zostało dodane"
if "update_meeting" in systemAct.getActParams():
task_type_1 = 'zaktualizowane'
task_type_2 = 'Zaktualizowanie'
elif "cancel_meeting" in systemAct.getActParams():
task_type_1 = 'odwołane'
task_type_2 = 'Odwołanie'
else:
task_type_1 = 'dodane'
task_type_2 = 'Dodanie'
return random.choice([f'Spotkanie zostało pomyślnie {task_type_1}.', f'{task_type_2} spotkania przebiegło pomyślnie.'])
return "Spotkanie zostało zaktualizowane"
if "cancel_meeting" in systemAct.getActParams():
return "Spotkanie zostało odwołane"
elif systemAct.getActType() == SystemActType.REQMORE:
if "create_meeting" in systemAct.getActParams():
response = 'Tworzenie spotkania zostało przerwane. '
elif "update_meeting" in systemAct.getActParams():
response = 'Aktualizacja spotkania została przerwana. '
elif "cancel_meeting" in systemAct.getActParams():
response = 'Odwoływanie spotkania zostało przerwane. '
else:
response = ''
return random.choice([f'{response}Czy mogę Ci w czymś jeszcze pomóc?', f'{response}Czy jest jeszcze coś co mogę dla Ciebie zrobić?'])
return "Spotkanie zostało odrzucone. Mogę pomóc w czymś jeszcze?"
if "update_meeting" in systemAct.getActParams():
return "Aktualizacja spotkania została anulowana. Mogę pomóc w czymś jeszcze?"
if "cancel_meeting" in systemAct.getActParams():
return "Odwoływanie spotkania zostało anulowane. Mogę pomóc w czymś jeszcze?"
if "meeting_list" in systemAct.getActParams() or "free_time" in systemAct.getActParams():
return "Mogę pomóc w czymś jeszcze?"
else:
if systemAct.getActType() == SystemActType.WELCOME_MSG:
introduction = 'Nazywam się Janusz i jestem twoim asystentem kalendarza spotkań.'
return random.choice([f'Cześć. {introduction}', f'Dzień dobry. {introduction}', f'Witam. {introduction}'])
elif systemAct.getActType() == SystemActType.BYE:
return random.choice(['Do widzenia.', 'Miłego dnia.'])
elif systemAct.getActType() == SystemActType.NOT_UNDERSTOOD:
try_again = 'Spróbuj swoją wypowiedź sformułować w inny sposób.'
return random.choice([f'Nie rozumiem o czym mówisz. {try_again}', f'Nie zrozumiałem twojej ostatniej wypowiedzi. {try_again}', f'Twoja ostatnia prośba była dla mnie nie zrozumiała. {try_again}'])
return "Cześć"
if systemAct.getActType() == SystemActType.REQMORE:
return "Czy mogę Ci w czymś jeszcze pomóc?"
if systemAct.getActType() == SystemActType.BYE:
return "Do widzenia."
if systemAct.getActType() == SystemActType.NOT_UNDERSTOOD:
return "Nie rozumiem o czym mówisz."
# TODO: Not implemented in DP
# if systemAct.getActType() == SystemActType.INFORM:
# if "name" in systemAct.getActParams():
# return "Nazywam się Janusz"
raise Exception("SystemAct:{} not recognized".format(systemAct))

View File

@ -23,13 +23,7 @@
# text: cześć
# intent: hello
# slots:
1 cześć hello NoLabel
# text: cześć elo
# intent: hello
# slots:
1 cześć hello NoLabel
2 elo hello NoLabel
1 siema hello NoLabel
# text: do widzenia
# intent: bye
@ -63,7 +57,7 @@
2 takim bye NoLabel
3 razie bye NoLabel
4 to bye NoLabel
5 wszystko bye NoLabel
1 wszystko bye NoLabel
# text: potwierdzam
# intent: confirm
@ -104,23 +98,6 @@
# slots:
1 nie negate NoLabel
# text: nie usuwaj tego spotkania
# intent: negate
# slots:
1 nie negate NoLabel
2 usuwaj negate NoLabel
3 tego negate NoLabel
4 spotkania negate NoLabel
# text: jednak nie zmieniaj tego spotkania
# intent: negate
# slots:
1 jednak negate NoLabel
2 nie negate NoLabel
3 zmieniaj negate NoLabel
4 tego negate NoLabel
5 spotkania negate NoLabel
# text: bez
# intent: negate
# slots:
@ -169,13 +146,6 @@
1 28 inform/date B-date
2 lutego inform/date I-date
# text: 25 września 2022
# intent: inform/date
# slots:
1 25 inform/date B-date
2 września inform/date I-date
3 2022 inform/date I-date
# text: spotkanie odbędzie się 3 maja
# intent: inform/date
# slots:
@ -185,16 +155,6 @@
4 3 inform/date B-date
5 maja inform/date I-date
# text: spotkanie odbędzie się 4 marca 2023
# intent: inform/date
# slots:
1 spotkanie inform/date NoLabel
2 odbędzie inform/date NoLabel
3 się inform/date NoLabel
4 4 inform/date B-date
5 marca inform/date I-date
6 2023 inform/date I-date
# text: spotkanie w piątek
# intent: inform/date
# slots:
@ -232,8 +192,8 @@
# intent: inform/date
# slots:
1 data inform/date NoLabel
2 to inform/date NoLabel
3 11.11.2011 inform/date B-date
1 to inform/date NoLabel
1 11.11.2011 inform/date B-date
# text: spotkanie odbędzie się pojutrze
# intent: inform/date
@ -257,10 +217,10 @@
1 ustaw inform/date NoLabel
2 datę inform/date NoLabel
3 tego inform/date NoLabel
4 spotkania inform/date NoLabel
5 na inform/date NoLabel
6 najbliższy inform/date B-date
7 poniedziałek inform/date I-date
3 spotkania inform/date NoLabel
3 na inform/date NoLabel
3 najbliższy inform/date B-date
3 poniedziałek inform/date I-date
# text: spotkanie będzie o godzinie 19:30
# intent: inform/time
@ -524,18 +484,6 @@
7 prac inform/description I-description
8 projektowych inform/description I-description
# text: Proszę jako opis dodać spotkanie dotyczące zakupu firmy
# intent: inform/description
# slots:
1 Proszę inform/description NoLabel
2 jako inform/description NoLabel
3 opis inform/description NoLabel
4 dodać inform/description NoLabel
5 spotkanie inform/description B-description
6 dotyczące inform/description I-description
7 zakupu inform/description I-description
8 firmy inform/description I-description
# text: Spotkanie będzie dotyczyło omówienia strategii biznesowej
# intent: inform/description
# slots:
@ -647,13 +595,6 @@
6 na meeting/update NoLabel
7 17:30 meeting/update B-time
# text: chciałbym utworzyć spotkanie
# intent: meeting/create
# slots:
1 chciałbym meeting/create NoLabel
2 utworzyć meeting/create NoLabel
3 spotkanie meeting/create NoLabel
# text: chciałbym zapisać spotkanie
# intent: meeting/create
# slots:
@ -700,22 +641,6 @@
10 salka meeting/create B-place
11 A meeting/create I-place
# text: proszę ustawić spotkanie z Jan Nowak 24 grudnia 2022 o godzinie 21.30
# intent: meeting/create
# slots:
1 proszę meeting/create NoLabel
2 ustawić meeting/create NoLabel
3 spotkanie meeting/create NoLabel
4 z meeting/create NoLabel
5 Jan meeting/create B-participant
6 Nowak meeting/create I-participant
7 24 meeting/create B-date
8 grudnia meeting/create I-date
9 2022 meeting/create I-date
10 o meeting/create NoLabel
11 godzinie meeting/create NoLabel
11 21.30 meeting/create B-time
# text: chciałbym umówić spotkanie dzisiaj o godzinie 17.00
# intent: meeting/create
# slots:
@ -725,7 +650,7 @@
4 dzisiaj meeting/create B-date
5 o meeting/create B-date
6 godzinie meeting/create NoLabel
7 17.00 meeting/create B-time
7 17:00 meeting/create B-time
# text: zapisz mi proszę spotkanie z 3 marca o 17 wizyta u lekarza
# intent: meeting/create

View File

@ -124,6 +124,7 @@ def get_datetime_from_day(day, hours, minutes):
def get_date(date, time):
print("test\ndate: ", date, "\ntime: ", time)
# parsowanie czasu
if re.match(r'^[0-2][0-9]$', time):
hours = int(time)

View File

@ -1,94 +0,0 @@
# Ewaluacja - asystent kalendarza spotkań
## Ankieta zadowolenia użytkownika:
https://forms.office.com/r/L16YGV6MLz
Ankieta zadowolenia użytkownika poruszała kilka kwestii, takich jak:
* główne zadanie, jakie użytkownik chciał zrealizować przy pomocy systemu
* czy udało się powyższe zadanie w pełni przy pomocy systemu zrealizować
* łatwość realizacji tego zadania w skali 1-5
* zrozumiałość wypowiedzi użytkownika dla systemu w skali 1-5
* zrozumiałość wypowiedzi systemu w skali 1-5
* jak bardzo system reagował zgodnie z oczekiwaniami użytkownika w skali 1-5
* odpowiedniość tempa interakcji w skali 1-5
* czy użytkownik wiedział co odpowiedzieć na każdym etapie dialogu w skali 1-5
* czy błąd krytyczny systemu zakończył rozmowę
* 2 pytania opisowe, co wg. użytkownika działa w systemie najlepiej i najgorzej
* czy użytkownik zamierza używać systemu w przyszłości w skali 1-5
* ogólna ocena systemu w skali 1-5
<!-- end of the list -->
Udało się zebrać odpowiedzi dotyczące 10 przeprowadzonych rozmów.
### Pytanie 1: Główne zadanie użytkownika.
* 8 użytkowników wskazało jako główny cel <b>umówienie spotkania</b>
* 1 użytkownik chciał sprawdzić <b>listę spotkań</b>
* 1 użytkownik chciał <b>odwołać spotkanie</b>
### Pytanie 2: Czy udało się zrealizować główne zadanie?
* 7 użytkowników odpowiedziało <b>tak</b>
* 3 użytkowników odpowiedziało <b>nie</b>
<!-- end of the list -->
Wszyscy użytkownicy, którym udało się zrealizować główne zadanie chcieli utworzyć spotkanie. Można więc wysnuć wniosek, że to element systemu, który działa najlepiej i jednocześnie najpopularniejszy wśród użytkowników. Co za tym idzie system można nazwać dość skutecznym, jednak nie radzi sobie w pełni ze wszystkimi planowanymi zadaniami.
### Pytanie 3: Łatwość realizacji zadania.
Średnia ocena tej metryki to 3.5/5 <br>
Najczęstsze oceny to <b>4 - co oznacza łatwą realizację zadania</b> (5 użytkowników) oraz <b>3 - umiarkowanie</b> (3 użytkowników). <br>
Najniższe oceny dotyczyły rozmów, w których nie doszło do pomyślej realizacji zadania.
### Pytanie 4: Jak system rozumiał wypowiedzi użytkownika?
Średnia ocena tej metryki to 3.5/5 <br>
Najczęstsze oceny to <b>4 - co oznacza zrozumienie większości wypowiedzi</b> (6 użytkowników) oraz <b>2 - zrozumienie niektórych wypowiedzi</b> (3 użytkowników). <br>
Najniższe oceny dotyczyły rozmów, w których nie doszło do pomyślej realizacji zadania.
### Pytanie 5: Jak użytkownik rozumiał wypowiedzi systemu?
Średnia ocena tej metryki to 4.3/5 <br>
Najczęstsze oceny to <b>5 - użytkownik rozumiał w pełni wypowiedzi systemu</b> (5 użytkowników) oraz <b>4 - użytkownik rozumiał w większości wypowiedzi systemu</b> (4 użytkowników). <br>
Najniższa ocena (2) dotyczyła rozmowy, w której nie doszło do pomyślej realizacji zadania.
### Pytanie 6: System robił to, co oczekiwał użytkownik.
Średnia ocena tej metryki to 3.6/5 <br>
Najczęstsze oceny to <b>4 - zgadzam się</b> (7 użytkowników) oraz <b>3 - trudno powiedzieć</b> (2 użytkowników). <br>
Najniższe oceny (2 oraz 3) dotyczyły rozmów, w których nie doszło do pomyślej realizacji zadania.
### Pytanie 7: Tempo interakcji z systemem było odpowiednie.
Średnia ocena tej metryki to 4.1/5 <br>
Najczęstsze oceny to <b>4 - zgadzam się</b> (7 użytkowników) oraz <b>5 - całkowicie się zgadzam</b> (2 użytkowników). <br>
Najniższa ocena (3) dotyczyła rozmowy, w której nie doszło do pomyślej realizacji zadania.
### Pytanie 8: Użytkownik wiedział co ma odpowiadać na każdym etapie dialogu.
Średnia ocena tej metryki to 3.9/5 <br>
Najczęstsze oceny to <b>4 - zgadzam się</b> (6 użytkowników) oraz <b>5 - całkowicie się zgadzam</b> (2 użytkowników). <br>
Najniższe oceny (2 oraz 3) dotyczyły rozmów, w których nie doszło do pomyślej realizacji zadania.
### Pytanie 9: Czy krytyczny błąd systemu przerwał rozmowę?
* 7 użytkowników odpowiedziało <b>tak</b>
* 3 użytkowników odpowiedziało <b>nie</b>
<!-- end of the list -->
Najbardziej niepokojąca metryka w ankiecie. Aż 70% rozmów skończyło się krytycznym błędem systemu, jednak w większości przypadków nie wpłynęło to na realizację głównego zadania użytkownika. Z pewnością trzeba się skupić w przyszłości na wyeliminowaniu tych błędów.
### Pytanie 10: Co w systemie działało nagorzej (nieobowiązkowe pytanie opisowe)?
Najczęściej wskazywanymi mankamentami systemu były błędne przechwytywanie slotów, co często prowadziło do ponownego zadania tego samego pytania oraz nieoczekiwane zakończenie konwersacji błędem krytycznym. Aż 7 użytkowników zdecydowało się odpowiedzieć na to pytanie, co najprawdopodobniej oznacza, że system dalej posiada niewielkie błędy wpływające na jego jakość.
### Pytanie 11: Co w systemie działało najlepiej (nieobowiązkowe pytanie opisowe)?
Tylko 3 użytkowników zdecydowało się odpowiedzieć na to pytanie, co może oznaczać, że większość z nich nie widziała w systemie bardzo dobrze działających elementów. <br>
Użytkownicy, którzy odpowiedzieli na to pytanie jako główną zaletę wskazali, że system realizuje pomyślnie podstawowy scenariusz, czyli tworzenie spotkania.
### Pytanie 12: Czy użytkownik zamierza używać systemu w przyszłości?
Średnia ocena tej metryki to 2.9/5 <br>
Najczęstsza ocena to <b>3 - trudno powiedzieć</b> (9 użytkowników). <br>
Większość użytkowników nie ma wyrobionego zdania na temat przydatności systemu. Może to oznaczać, że system nie przekonał użytkowników podczas testów lub nie zawiera wszystkich oczekiwanych funkcjonalności.
### Pytanie 13: Ogólna ocena systemu przez użytkownika.
Średnia ocena tej metryki to 3.9/5 <br>
Najczęstsza ocena to <b>4</b> (5 użytkowników). <br>
Ogólnie system wypada dość dobrze. Najniższe oceny dotyczyły rozmów, podczas których nie udało się zrealizować zadania oraz system zakończył niespodziewanie rozmowe przez błąd. Można więc wysnuć wniosek, że wyeliminowanie tych błędów i poprawa skuteczności podniosłaby ogólną ocenę systemu.
## Inne metryki ewaluacyjne.
### Task success rate:
System poprawnie zrealizował 9 zadań z 16 możliwych, co daje <b>56,25%</b> skuteczności. <br>
Tą skuteczność można uznać za dość dobrą, jednak na pewno trzeba by ją zwiększyć w toku dalszych prac nad systemem. <br>
Głownym elementem systemu, który powodował niepomyślną realizację zadań był moduł NLU (głównie błędne wyłapywanie wartości slotów) oraz moduł NLG (system nie generował odpowiedzi przy niektórych nieprzewidzianych scenariuszach).
### Slot error rate:
System poprawnie wyłapał 23 wartości slotu na 55 przypadków, co daje <b>41,81%</b> skuteczności. <br>
System przede wszystkim miał problem ze slotem <b>opis spotkania</b> oraz <b>uczestnik spotkania</b>. Dość sprawnie wyłapuje slot <b>data</b> oraz <b>godzina</b>.

30
main.py
View File

@ -3,36 +3,36 @@ from NaturalLanguageUnderstanding import NLU
from NaturalLanguageGeneration import NLG
from DialogueStateTracker import DST
from DialoguePolicy import DP
from DBManager import calender_db
if __name__ == "__main__":
db = calender_db()
nlu = NLU()
dst = DST()
dp = DP(dst)
dp = DP(dst, db)
nlg = NLG(dst)
while(1):
user_input = input("Wpisz tekst: ")
user_input = input("\nWpisz tekst: ")
user_frame = nlu.parse_user_input(user_input)
print('------ rozpoznany user frame ------')
print(user_frame)
# print('\n------ rozpoznany user frame ------')
# print(user_frame)
dst.user_update(user_frame)
state, last_user_act, last_system_act = dst.get_dialogue_state()
slots = dst.get_dialogue_slots()
system_act = dp.choose_tactic()
system_act = dp.chooseTactic()
print('------ stan ------')
print(state, last_user_act, last_system_act)
print('------ przechowywane sloty ------')
print(slots)
print('------ wybrana akcja systemu ------')
# print('\n------ stan ------')
# print(state, last_user_act, last_system_act)
# print('\n------ przechowywane sloty ------')
# print(slots)
print('\n------ wybrana akcja systemu ------')
print(system_act)
system_response = nlg.generate_response(system_act)
print('------ wygenerowana odpowiedź systemu ------')
system_response = nlg.generateResponse(system_act)
print('\n------ wygenerowana odpowiedź systemu ------')
print(system_response)
print('-----------------------------------')
print('-----------------------------------')
if system_act.getActType() == SystemActType.BYE:
break