DP, DST and NLG fixes

This commit is contained in:
Łukasz Jędyk 2021-06-18 15:26:21 +02:00
parent 8a796b96cc
commit 588e00981e
5 changed files with 161 additions and 157 deletions

View File

@ -5,17 +5,11 @@ from collections import defaultdict
class DP:
"""
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):
self.DST = dst
self.meeting_to_update = False
def chooseTactic(self) -> SystemAct:
def choose_tactic(self) -> SystemAct:
dialogue_state, last_user_act, last_system_act = self.DST.get_dialogue_state()
slots = self.DST.get_dialogue_slots()
# stan dodawania spotkania
@ -89,11 +83,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'])
system_act = SystemAct(SystemActType.REQUEST, ['date', False])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time'])
system_act = SystemAct(SystemActType.REQUEST, ['time', False])
self.DST.system_update(system_act)
return system_act
else:
@ -102,11 +96,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'])
system_act = SystemAct(SystemActType.REQUEST, ['date', False])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time'])
system_act = SystemAct(SystemActType.REQUEST, ['time', False])
self.DST.system_update(system_act)
return system_act
else:
@ -119,23 +113,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'])
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time'])
system_act = SystemAct(SystemActType.REQUEST, ['time', True])
self.DST.system_update(system_act)
return system_act
elif 'place' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['place'])
system_act = SystemAct(SystemActType.REQUEST, ['place', True])
self.DST.system_update(system_act)
return system_act
elif 'description' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['description'])
system_act = SystemAct(SystemActType.REQUEST, ['description', True])
self.DST.system_update(system_act)
return system_act
elif 'participants' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['participants'])
system_act = SystemAct(SystemActType.REQUEST, ['participants', True])
self.DST.system_update(system_act)
return system_act
else:
@ -144,23 +138,23 @@ class DP:
return system_act
else:
if 'date' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['date'])
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
self.DST.system_update(system_act)
return system_act
elif 'time' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['time'])
system_act = SystemAct(SystemActType.REQUEST, ['time', True])
self.DST.system_update(system_act)
return system_act
elif 'place' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['place'])
system_act = SystemAct(SystemActType.REQUEST, ['place', True])
self.DST.system_update(system_act)
return system_act
elif 'description' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['description'])
system_act = SystemAct(SystemActType.REQUEST, ['description', True])
self.DST.system_update(system_act)
return system_act
elif 'participants' not in slots:
system_act = SystemAct(SystemActType.REQUEST, ['participants'])
system_act = SystemAct(SystemActType.REQUEST, ['participants', True])
self.DST.system_update(system_act)
return system_act
else:
@ -180,7 +174,7 @@ class DP:
if last_user_act == UserActType.CONFIRM:
self.meeting_to_update = True
self.DST.clear_slots()
system_act = SystemAct(SystemActType.REQUEST, ['date'])
system_act = SystemAct(SystemActType.REQUEST, ['date', True])
self.DST.system_update(system_act)
return system_act
elif last_user_act == UserActType.NEGATE:
@ -236,8 +230,7 @@ class DP:
return SystemAct(SystemActType.REQMORE, ['meeting_list'])
else:
if 'date' in slots:
system_act = SystemAct(SystemActType.MEETING_LIST, slots)
self.DST.clear()
system_act = SystemAct(SystemActType.MEETING_LIST, {'date': slots['date']})
return system_act
else:
system_act = SystemAct(SystemActType.REQUEST, ['date'])
@ -250,8 +243,7 @@ class DP:
return SystemAct(SystemActType.REQMORE, ['free_time'])
else:
if 'date' in slots:
system_act = SystemAct(SystemActType.FREE_TIME, slots)
self.DST.clear()
system_act = SystemAct(SystemActType.FREE_TIME, {'date': slots['date']})
return system_act
else:
system_act = SystemAct(SystemActType.REQUEST, ['date'])

View File

@ -4,12 +4,6 @@ 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

View File

@ -1,154 +1,144 @@
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 generateResponse(self, systemAct: SystemAct) -> str:
dialogue_state, last_user_act, _ = self.DST.get_dialogue_state()
slots = self.DST.get_dialogue_slots()
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()
print(f'Stacja dialogowa: {dialogue_state}')
if dialogue_state == UserActType.CREATE_MEETING:
if systemAct.getActType() == SystemActType.REQUEST:
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:
date = slots['date']
time = slots['time']
place = slots['place']
part_list = slots['participants']
part = ""
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}'
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}'])
# TODO: nie sprawdzone - trudno wejść do tego stanu
elif dialogue_state == UserActType.UPDATE_MEETING:
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 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 systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
date = slots['date']
time = slots['time']
place = slots['place']
part_list = slots['participants']
part = ""
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}'
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}'
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}'])
elif dialogue_state == UserActType.CANCEL_MEETING:
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?"
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 systemAct.getActType() == SystemActType.CONFIRM_DOMAIN:
date = slots['date']
time = slots['time']
# place = slots['place']
# part_list = slots['participants']
# part = ""
# for p in part_list:
# part += p
# part += ", "
# part = part[:-2]
# desc = slots['description']
return f'Spotkanie:\n' \
f'Dzień: {date}\nCzas: {time}'
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}'
elif dialogue_state == UserActType.MEETING_LIST:
if systemAct.getActType() == SystemActType.REQUEST:
if "date" in systemAct.getActParams():
return "Z jakiego okresu chcesz przejrzeć spotkania?"
# TODO: dopracować po dodaniu DB
if systemAct.getActType() == SystemActType.MEETING_LIST:
response = ""
for s in slots:
date = s['date']
time = s['time']
place = s['place']
part_list = s['participants']
part = ""
for p in part_list:
part += p
part += ", "
part = part[:-2]
desc = s['description']
response += f'Spotkanie:\nDzień: {date}\nCzas: {time}\nMiejsce: {place}\nUczestnicy: {part}\nOpis: {desc}\n'
response += "--------------------"
return response
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)
self.DST.clear()
return f'{response}\n{meetings}'
elif dialogue_state == UserActType.FREE_TIME:
if systemAct.getActType() == SystemActType.REQUEST:
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
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}'
elif systemAct.getActType() == SystemActType.AFFIRM:
if "create_meeting" in systemAct.getActParams():
return "Spotkanie zostało dodane"
if "update_meeting" in systemAct.getActParams():
return "Spotkanie zostało zaktualizowane"
if "cancel_meeting" in systemAct.getActParams():
return "Spotkanie zostało odwołane"
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.'])
elif systemAct.getActType() == SystemActType.REQMORE:
if "create_meeting" in systemAct.getActParams():
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?"
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ć?'])
else:
if systemAct.getActType() == SystemActType.WELCOME_MSG:
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"
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}'])
raise Exception("SystemAct:{} not recognized".format(systemAct))

View File

@ -23,7 +23,7 @@
# text: cześć
# intent: hello
# slots:
1 siema hello NoLabel
1 cześć hello NoLabel
# text: do widzenia
# intent: bye
@ -484,6 +484,18 @@
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:
@ -641,6 +653,22 @@
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:
@ -650,7 +678,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

@ -20,7 +20,7 @@ if __name__ == "__main__":
dst.user_update(user_frame)
state, last_user_act, last_system_act = dst.get_dialogue_state()
slots = dst.get_dialogue_slots()
system_act = dp.chooseTactic()
system_act = dp.choose_tactic()
print('------ stan ------')
print(state, last_user_act, last_system_act)
@ -28,7 +28,7 @@ if __name__ == "__main__":
print(slots)
print('------ wybrana akcja systemu ------')
print(system_act)
system_response = nlg.generateResponse(system_act)
system_response = nlg.generate_response(system_act)
print('------ wygenerowana odpowiedź systemu ------')
print(system_response)
print('-----------------------------------')