12 KiB
Systemy Dialogowe
11. Generowanie odpowiedzi [laboratoria]
Marek Kubis (2021)
Generowanie odpowiedzi
W systemie dialogowym taktyka prowadzenia dialogu odpowiada za wyznaczanie aktów systemowych, czyli wskazanie tego co ma zostać przez system wypowiedziane i/lub wykonane. Zadaniem modułu generowania odpowiedzi jest zamiana aktów dialogowych na wypowiedzi w języku naturalnym, czyli wskazanie tego w jaki sposób ma zostać wypowiedziane to co ma zostać wypowiedziane.
Generowanie odpowiedzi przy użyciu szablonów
Podstawowe narzędzie wykorzystywane w modułach generowania odpowiedzi stanowią szablony tekstowe interpolujące zmienne. W Pythonie mechanizm ten jest dostępny za pośrednictwem f-stringów, metody format oraz zewnętrznych bibliotek takich, jak Jinja2.
O ile podejście wykorzystujące wbudowane mechanizmy języka Python sprawdza się w prostych przypadkach...
def nlg(system_act):
domain, intent, slot, value = system_act
if intent == 'Inform' and slot == 'Phone':
return f'Numer telefonu to {value}'
nlg(['Hotel', 'Inform', 'Phone', '1234567890'])
... to trzeba mieć świadomość, że w toku prac nad agentem dialogowym może być konieczne uwzględnienie m.in.:
- szablonów zależnych od wartości slotów
def nlg(system_act):
domain, intent, slot, value = system_act
if domain == 'Restaurant' and intent == 'Inform' and slot == 'Count':
if value == 0:
return f'Nie znalazłem restauracji spełniających podane kryteria.'
elif value == 1:
return f'Znalazłem jedną restaurację spełniającą podane kryteria.'
elif value <= 4:
return f'Znalazłem {value} restauracje spełniające podane kryteria.'
elif value <= 9:
return f'Znalazłem {value} restauracji spełniających podane kryteria.'
else:
return f'Znalazłem wiele restauracji spełniających podane kryteria.'
nlg(['Restaurant', 'Inform', 'Count', 0])
nlg(['Restaurant', 'Inform', 'Count', 1])
nlg(['Restaurant', 'Inform', 'Count', 2])
nlg(['Restaurant', 'Inform', 'Count', 6])
nlg(['Restaurant', 'Inform', 'Count', 100])
- wielu wariantów tej samej wypowiedzi
import random
def nlg(system_act):
domain, intent, slot, value = system_act
if intent == 'Affirm':
r = random.randint(1, 3)
if r == 1:
return 'Tak'
elif r == 2:
return 'Zgadza się'
else:
return 'Potwierdzam'
nlg(['Hotel', 'Affirm', '', ''])
- wielojęzycznego interfejsu użytkownika
def nlg_en(system_act):
domain, intent, slot, value = system_act
if domain == 'Hotel' and intent == 'Request' and slot == 'CreditCardNo':
return 'What is your credit card number?'
nlg_en(['Hotel', 'Request', 'CreditCardNo', '?'])
Generowanie odpowiedzi z wykorzystaniem uczenia maszynowego
Obok mechanizmu szablonów do generowania odpowiedzi można również stosować techniki uczenia maszynowego. Zagadnienie to stanowiło przedmiot konkursu E2E NLG Challenge (Novikova i in., 2017). Przyjrzyjmy się danym, jakie udostępnili organizatorzy.
!mkdir -p l10
!curl -L -C - https://github.com/tuetschek/e2e-dataset/releases/download/v1.0.0/e2e-dataset.zip -o l10/e2e-dataset.zip
!unzip l10/e2e-dataset.zip -d l10
import pandas as pd
trainset = pd.read_csv('l10/e2e-dataset/trainset.csv')
trainset
Zadanie
Zaimplementować moduł generowania odpowiedzi obejmujący akty systemowe występujące w zgromadzonym korpusie.
Termin: 1.06.2022, godz. 23:59.
Literatura
- Jekaterina Novikova, Ondřej Dušek, Verena Rieser, The E2E Dataset: New Challenges For End-to-End Generation, Proceedings of the SIGDIAL 2017 Conference, pages 201-206, Saarbrücken, Germany https://arxiv.org/pdf/1706.09254.pdf
import pandas as pd
df = pd.read_csv('../data/dialog-17-04-03.tsv', sep='\t', header=None)
df.columns = ['user','text','data']
df= df[df.user=='system']
df.drop(axis=1, labels=['user'], inplace=True)
df
user | text | data | |
---|---|---|---|
1 | system | Witamy w internetowym systemie rezerwacji Nach... | welcomemsg() |
3 | system | System Nachos obsługuje następujące kina: Mult... | select(location) |
def nlg(system_act):
intent, slot, value = system_act
if intent=='welcomemsg':
return 'Witamy w internetowym systemie rezerwacji Nachos, w czym mogę pomóc?'
elif intent=='inform':
if domain == 'Restaurant' and intent == 'Inform' and slot == 'Count':
if value == 0:
return f'Nie znalazłem restauracji spełniających podane kryteria.'
elif value == 1:
return f'Znalazłem jedną restaurację spełniającą podane kryteria.'
elif value <= 4:
return f'Znalazłem {value} restauracje spełniające podane kryteria.'
elif value <= 9:
return f'Znalazłem {value} restauracji spełniających podane kryteria.'
else:
return f'Znalazłem wiele restauracji spełniających podane kryteria.'
inform(quantity=2) AND inform(time=12:00)
['inform','quantity','2']