Compare commits
No commits in common. "main" and "restart" have entirely different histories.
@ -80,7 +80,7 @@ public <platnosc> = [zaplace | poprosze] <metoda_platnosci> {payment_method};
|
||||
|
||||
<help_with> = menu | (jakie posilki moge zjesc z tego menu) | (A jaka to <potrawa>) ;
|
||||
|
||||
<potrawa> = tatara | tatar | poledwica | poledwice | pizza | pizze | tiramisu | zrazy [wolowe] | pyzy | placki | makaron | picia | zupa | danie_glowne | deser | napoj | ryba | rybe | cole | tiramisu | zupe grzybowa | stek | soki | kebaba;
|
||||
<potrawa> = tatara | tatar | poledwica | poledwice | pizza | pizze | tiramisu | zrazy [wolowe] | pyzy | placki | makaron | picia | zupa | danie_glowne | deser | napoj | ryba | rybe | cole | tiramisu | zupe grzybowa | stek | soki;
|
||||
|
||||
|
||||
|
||||
|
@ -1,363 +0,0 @@
|
||||
import string
|
||||
from typing import Any, List, Tuple
|
||||
import os
|
||||
|
||||
import jsgf
|
||||
from unidecode import unidecode
|
||||
import random
|
||||
from convlab.dst import dst
|
||||
|
||||
from transformers import (
|
||||
AutoModelForSeq2SeqLM,
|
||||
AutoTokenizer,
|
||||
pipeline,
|
||||
)
|
||||
|
||||
from transformers.utils import logging
|
||||
|
||||
logging.set_verbosity_error()
|
||||
|
||||
|
||||
def default_state():
|
||||
return dict(
|
||||
user_action=[],
|
||||
system_action=[],
|
||||
belief_state={
|
||||
'address': '',
|
||||
'payment_method': '',
|
||||
'dish': [],
|
||||
'time': ''
|
||||
},
|
||||
booked={},
|
||||
request_state=[],
|
||||
terminated=False,
|
||||
history=[]
|
||||
)
|
||||
|
||||
|
||||
class Model:
|
||||
def __init__(self):
|
||||
self.state = default_state()
|
||||
self.nlu = NLU()
|
||||
self.dst = DST(self.state)
|
||||
self.dp = DP(self.state)
|
||||
self.nlg = NLG(self.state)
|
||||
|
||||
def __call__(self, prompt, debug=True) -> Any:
|
||||
if debug:
|
||||
print(prompt)
|
||||
msg = prompt.lower()
|
||||
|
||||
r = self.nlu(msg)
|
||||
slots = r['slots']
|
||||
# print(r)
|
||||
r = self.dst(r)
|
||||
# print(r)
|
||||
r = self.dp()
|
||||
# print(r)
|
||||
r = self.nlg(r, slots)
|
||||
if debug:
|
||||
print(r)
|
||||
else:
|
||||
print(f"JARVIS: {r}")
|
||||
|
||||
return r
|
||||
|
||||
|
||||
class NLU():
|
||||
def __init__(self):
|
||||
self.book_grammar = jsgf.parse_grammar_file('book.jsgf')
|
||||
|
||||
def get_dialog_act(self, rule):
|
||||
slots = []
|
||||
self.get_slots(rule.expansion, slots)
|
||||
return {'act': rule.name, 'slots': slots}
|
||||
|
||||
def get_slots(self, expansion, slots):
|
||||
if expansion.tag != '':
|
||||
slots.append((expansion.tag, expansion.current_match))
|
||||
return
|
||||
|
||||
for child in expansion.children:
|
||||
self.get_slots(child, slots)
|
||||
|
||||
if not expansion.children and isinstance(expansion, jsgf.NamedRuleRef):
|
||||
self.get_slots(expansion.referenced_rule.expansion, slots)
|
||||
|
||||
def __call__(self, prompt) -> Any:
|
||||
book_grammar = jsgf.parse_grammar_file('book.jsgf')
|
||||
|
||||
prompt = unidecode(prompt)
|
||||
translator = str.maketrans('', '', string.punctuation)
|
||||
prompt = prompt.translate(translator)
|
||||
|
||||
matched = book_grammar.find_matching_rules(prompt)
|
||||
|
||||
if matched:
|
||||
return self.get_dialog_act(matched[0])
|
||||
else:
|
||||
return {'act': 'null', 'slots': []}
|
||||
|
||||
|
||||
class DST(dst.DST):
|
||||
|
||||
def __init__(self, state):
|
||||
dst.DST.__init__(self)
|
||||
self.state = state
|
||||
|
||||
def __call__(self, user_act) -> Any:
|
||||
if len(user_act['slots']) == 0:
|
||||
user_act = [(user_act['act'], None, None)]
|
||||
else:
|
||||
user_act = [(user_act['act'], k, v) for k, v in user_act['slots'] if v is not None]
|
||||
|
||||
self.state['request_state'] = {}
|
||||
for act, slot, value in user_act:
|
||||
self.state['user_action'].append(act)
|
||||
|
||||
if act == "platnosc":
|
||||
self.state['belief_state']['payment_method'] = value
|
||||
self.state['request_state'] = ['payment_method']
|
||||
|
||||
elif act == "offer":
|
||||
self.state['request_state'] = ['menu']
|
||||
|
||||
elif act == 'select':
|
||||
if slot == 'dish':
|
||||
self.state['belief_state']['dish'].append(value)
|
||||
else:
|
||||
self.state['belief_state'][slot] = value
|
||||
self.state['request_state'] = [slot]
|
||||
|
||||
elif act == 'inform':
|
||||
pass
|
||||
|
||||
elif act == 'request':
|
||||
pass
|
||||
elif act == 'restart':
|
||||
self.state["belief_state"] = default_state()["belief_state"]
|
||||
self.state["booked"] = {}
|
||||
self.state["request_state"] = []
|
||||
self.state["terminated"] = False
|
||||
self.state["history"] = []
|
||||
return self.state
|
||||
|
||||
|
||||
class DP():
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def __call__(self) -> Any:
|
||||
system_action = None
|
||||
|
||||
if self.state['user_action'][-1] == 'hello':
|
||||
system_action = 'welcomemsg'
|
||||
# przywitaj uzytkownika (i pokaz menu)
|
||||
|
||||
elif self.state['user_action'][-1] == 'select':
|
||||
system_action = 'inform'
|
||||
# poinformuj o wybranych slotach z "request_state"
|
||||
|
||||
elif (self.state['user_action'][-1] == 'help'
|
||||
or self.state['user_action'][-1] == 'offer'
|
||||
or self.state['user_action'][-1] == 'reqmore'
|
||||
or (self.state['user_action'][-1] == 'request' and len(self.state['request_state']) == 0)
|
||||
):
|
||||
system_action = 'offer'
|
||||
# zaoferuj cale menu
|
||||
|
||||
elif self.state['user_action'][-1] == 'ack':
|
||||
address = self.state["belief_state"]["address"]
|
||||
payment_method = self.state["belief_state"]["payment_method"]
|
||||
dish = self.state["belief_state"]["dish"]
|
||||
# W przypadku braku szczegolnej informacji o czasie zamówienia zamawiamy natychmiast
|
||||
|
||||
if address and payment_method and dish:
|
||||
system_action = 'bye'
|
||||
self.state['terminated'] = True
|
||||
# potwierdz i zakoncz, podsumuj zamowienie
|
||||
else:
|
||||
system_action = 'canthelp.missing_slot_value'
|
||||
elif self.state['user_action'][-1] == 'restart':
|
||||
system_action = 'welcomemsg'
|
||||
# zachowaj sie jak na poczatku rozmowy
|
||||
else:
|
||||
system_action = 'inform'
|
||||
# poinformuj o wybranych slotach z "request_state"
|
||||
# lub o wszystkich jezeli nic nie ma w request state
|
||||
|
||||
self.state['system_action'].append(system_action)
|
||||
return system_action
|
||||
|
||||
|
||||
class NLG():
|
||||
def __init__(self, state):
|
||||
self.model = AutoModelForSeq2SeqLM.from_pretrained("filnow/nlg-umt5-pol")
|
||||
self.tokenizer = AutoTokenizer.from_pretrained("google/umt5-small")
|
||||
self.nlg_pipeline = pipeline('summarization', model=self.model, tokenizer=self.tokenizer)
|
||||
|
||||
self.messages = {
|
||||
"welcomemsg": [
|
||||
"Witaj w naszej restauracji! Jak mogę Ci pomóc?",
|
||||
"Witaj! W czym mogę pomóc?",
|
||||
"Hej! Co mogę dla Ciebie zrobić?"
|
||||
],
|
||||
"canthelp": [
|
||||
"Przepraszam, nie mogę pomóc w tej chwili.",
|
||||
"Nie jestem w stanie pomóc.",
|
||||
"Przepraszam, nie rozumiem."
|
||||
],
|
||||
"bye": [
|
||||
"Dziękujemy za zamówienie! Smacznego!",
|
||||
"Smacznego! Do zobaczenia!",
|
||||
"Dziękujemy za skorzystanie z naszych usług!"
|
||||
],
|
||||
"affirm": [
|
||||
"Zamówienie zostało złożone!",
|
||||
"Potwierdzam zamówienie!",
|
||||
"Skladam zamówienie!"
|
||||
],
|
||||
"repeat": [
|
||||
"Możesz powtórzyć?",
|
||||
"Nie zrozumiałem, możesz powtórzyć?",
|
||||
"Nie zrozumiałem, możesz powtórzyć jeszcze raz?"
|
||||
],
|
||||
"reqmore": [
|
||||
"Potrzebujesz więcej informacji?",
|
||||
"Czy mogę pomóc w czymś jeszcze?",
|
||||
"Czy mogę zaoferować coś jeszcze?"
|
||||
]
|
||||
}
|
||||
|
||||
def __call__(self, act: str, slots: List[Tuple[str, str]]) -> str:
|
||||
if act == 'welcomemsg':
|
||||
return random.choice(self.messages["welcomemsg"])
|
||||
|
||||
elif act in ["inform", "request", "select"]:
|
||||
if slots == []:
|
||||
return "Przepraszam nie rozumiem. Podaj więcej informacji."
|
||||
else:
|
||||
text = [f"{slot[0]}[{slot[1]}]" for slot in slots if slot[1] is not None]
|
||||
return self.nlg_pipeline(f'generate text: {", ".join(text)}')[0]['summary_text']
|
||||
|
||||
elif act == "canthelp.missing_slot_value" or act == "canthelp":
|
||||
return random.choice(self.messages["canthelp"])
|
||||
|
||||
elif act == "bye":
|
||||
return random.choice(self.messages["bye"])
|
||||
|
||||
elif act == 'affirm':
|
||||
return random.choice(self.messages["affirm"])
|
||||
|
||||
elif act == "repeat":
|
||||
return random.choice(self.messages["repeat"])
|
||||
|
||||
elif act == "reqmore":
|
||||
return random.choice(self.messages["reqmore"])
|
||||
|
||||
elif act == "offer":
|
||||
return "Oto nasze menu: tatar, poledwica, pizza, tiramisu, zrazy [wolowe], pyzy, placki, makaron, picia, zupa, ryba, zupe grzybowa, stek \n Pragniemy zaznaczyć, że nie które dania mogą być niedostępne"
|
||||
|
||||
|
||||
def ascii_jarvis():
|
||||
print(''''
|
||||
____. _____ ______________ ____.___ _________
|
||||
| | / _ ______ \ \ / /| |/ _____/
|
||||
| |/ /_\ \| _/\ Y / | |\_____ \
|
||||
/\__| / | \ | \ \ / | |/ |
|
||||
\________\____|__ /____|_ / \___/ |___/_______ /
|
||||
\/ \/ \/ ' ''')
|
||||
|
||||
def clear_console():
|
||||
operating_system = os.name
|
||||
if operating_system == 'nt':
|
||||
os.system('cls')
|
||||
else:
|
||||
os.system('clear')
|
||||
|
||||
def dialogue_test():
|
||||
model = Model()
|
||||
|
||||
# jezeli sie przywita to przywitaj uzytkownika (i pokaz menu)
|
||||
# response = model("Cześć")
|
||||
# response = model("Witam")
|
||||
# response = model("Witam system")
|
||||
# response = model("Hej, jakim botem jesteś?")
|
||||
# response = model("Hej, czym się zajmujesz?")
|
||||
# response = model("Hej, w czym mi możesz pomóc?")
|
||||
print()
|
||||
response = model("Siema, w czym możesz mi pomóc?")
|
||||
print()
|
||||
# jezeli prosi o pomoc lub po prostu o menu to zaoferuj cale menu
|
||||
# response = model("Pokaz menu")
|
||||
# response = model("A co do picia proponujesz?")
|
||||
# response = model("Jakie inne desery oferujesz?")
|
||||
response = model("Interesują mnie dania kuchni włoskiej oraz meksykanskiej.")
|
||||
print()
|
||||
# jezeli wybierze danie to zapisz wybor i poinformuj o nim
|
||||
# response = model("Poproszę tatara")
|
||||
response = model("Chciałbym zjesc tatara")
|
||||
print()
|
||||
# jezeli poda adres to zapisze wybor i poinformuj o nim
|
||||
# response = model('Poproszę na poznańską 2')
|
||||
response = model("uniwersytetu poznanskiego 4 61-614 poznan")
|
||||
print()
|
||||
# jezeli sprobuje dokonac zamowienia bez podania potrzebnych informacji prosimy o nie
|
||||
# response = model("Dobrze, nie mogę się już doczekać.")
|
||||
response = model("Super, to zatem wszystko!")
|
||||
print()
|
||||
# jezeli wybierze rodzaj platnosci to zapisz wybor i poinformuj o nim
|
||||
# response = model("karta")
|
||||
# response = model("Poproszę blikiem z góry")
|
||||
response = model("Zapłacę kartą przy odbiorze")
|
||||
print()
|
||||
# jezeli potwiedzi zamowienie to zakoncz zamawianie sukcesem i wypisz calosc
|
||||
# response = model("Potwierdzam!")
|
||||
# response = model("Tak!")
|
||||
# response = model("Tak to wszystko!")
|
||||
# response = model("Super, to zatem wszystko!")
|
||||
response = model("Dobrze, nie mogę się już doczekać.")
|
||||
print()
|
||||
|
||||
print("----Konwersacja z restartem-------")
|
||||
|
||||
model = Model()
|
||||
response = model("Siema, w czym możesz mi pomóc?")
|
||||
print()
|
||||
response = model("Interesują mnie dania kuchni włoskiej oraz meksykanskiej.")
|
||||
print()
|
||||
response = model("Chciałbym zjesc tatara")
|
||||
print()
|
||||
response = model("uniwersytetu poznanskiego 4 61-614 poznan")
|
||||
print()
|
||||
response = model("od nowa")
|
||||
print()
|
||||
response = model("Interesują mnie dania kuchni włoskiej oraz meksykanskiej.")
|
||||
print()
|
||||
response = model("Chciałbym zjesc tatara")
|
||||
print()
|
||||
response = model("uniwersytetu poznanskiego 4 61-614 poznan")
|
||||
print()
|
||||
response = model("Zapłacę kartą przy odbiorze")
|
||||
print()
|
||||
response = model("Dobrze, nie mogę się już doczekać.")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
model = Model()
|
||||
ascii_jarvis()
|
||||
print("Chatbot Jarvis\n--------------")
|
||||
print("Dostępe komendy: \n\n- SYSTEM_FINISH - zakończenie rozmowy\n- Pokaz menu - wyświetlenie menu\n")
|
||||
while True:
|
||||
print("\nUżytkownik: ")
|
||||
user_input = input()
|
||||
while user_input == "SYSTEM_FINISH":
|
||||
clear_console()
|
||||
model = Model()
|
||||
ascii_jarvis()
|
||||
print("Chatbot Jarvis\n--------------")
|
||||
print("Dostępe komendy: \n- SYSTEM_FINISH - zakończenie rozmowy\n- Pokaz menu - wyświetlenie menu\n")
|
||||
print("\nUżytkownik: ")
|
||||
user_input = input()
|
||||
response = model(user_input, debug=False)
|
20628
nlg_data.csv
20628
nlg_data.csv
File diff suppressed because it is too large
Load Diff
@ -1,111 +0,0 @@
|
||||
import pandas as pd
|
||||
import random
|
||||
|
||||
|
||||
addresses = ["ulica Zielona 15", "ulica Czerwona 20", "ulica Niebieska 30", "ulica Biala 5", "ulica Czarna 10", "ulica Fioletowa 25", "ulica Pomaranczowa 35", "ulica Zolta 40", "ulica Różowa 45", "ulica Szara 50", "ulica Brązowa 55", "ulica Srebrna 60", "ulica Złota 65", "ulica Platynowa 70", "ulica Miedziana 75", "ulica Niklowa 80", "ulica Aluminium 85", "ulica Stalowa 90", "ulica Żelazna 95", "ulica Miedziana 100"]
|
||||
payment_methods = ["karta kredytowa", "gotowka", "blik", "przelew", "google pay"]
|
||||
dishes = ["spaghetti", "pierogi", "schabowy", "pizza", "burger", "tatar", "poledwica", "tiramisu", "zrazy", "pyzy", "placki", "makaron", "zupa", "ryba", "cole", "tiramisu", "zupa grzybowa", "stek", "soki", "napoj"]
|
||||
times = ["8:00", "12:00", "18:00", "20:00", "10:00", "dziesiata", "dziewiata", "osma", "siodma", "szosta", "czwarta", "trzecia", "druga", "pierwsza", "poludnie", "polnoc", "wschod", "zachod", "poludniowy wschod", "poludniowy zachod", "polnocny wschod", "polnocny zachod", "rano", "wieczor", "noc", "popoludnie", "przedpoludnie", "po poludniu", "po polnocy", "przed polnoca", "przed poludniem"]
|
||||
portion_sizes = ["mała", "średnia", "duża", "gigantyczna", "mini"]
|
||||
price = ["10", "50", "100", "150", "tanio", "drogo"]
|
||||
ingredient = ["mięso", "mleko", "jajka", "mąka", "cukier", "sól", "pieprz", "oliwa", "masło", "ser", "warzywa", "owoce", "ryż", "makaron", "zupa", "ryba", "sos", "przyprawy", "soki", "napoje", "alkohol", "kawa", "herbata", "deser", "ciasto", "chleb", "pasta", "sos", "danie", "potrawa", "zupa", "sałatka", "kanapka", "tost", "jajecznica", "omlet", "placki", "pierogi", "schabowy", "kotlet", "kotlet schabowy", "kotlet mielony", "kotlet z kurczaka", "kotlet z indyka", "kotlet z ryby", "kotlet z warzyw", "kotlet ziemniaczany", "kotlet z kaszy", "kotlet z makaronu", "kotlet z ziemniaków", "kotlet z ryżu"]
|
||||
allergy = ["gluten", "laktoza", "jajka", "orzechy", "soja", "ryby", "skorupiaki", "mleko", "seler", "gorczyca", "sezam", "siarczyny", "łubin", "migdały", "orzechy laskowe", "orzechy włoskie", "orzechy nerkowca", "orzechy ziemne", "orzechy brazylijskie", "orzechy makadamia", "orzechy pecan", "orzechy pistacjowe", "orzechy kasztanowe", "orzechy pinii", "orzechy arachidowe", "orzechy ziemne", "orzechy brazylijskie", "orzechy makadamia", "orzechy pecan", "orzechy pistacjowe", "orzechy kasztanowe", "orzechy pinii", "orzechy arachidowe", "orzechy ziemne", "orzechy brazylijskie", "orzechy makadamia", "orzechy pecan", "orzechy pistacjowe"]
|
||||
|
||||
def create_ref(slot, value):
|
||||
ref_templates = {
|
||||
"address": [
|
||||
f"Zamówienie zostanie dostarczone na {value}.",
|
||||
f"Niestety nie dostarczamy na {value}.",
|
||||
f"Oczywiście, dostarczymy na {value}.",
|
||||
f"Dostawa możliwa na {value}.",
|
||||
f"Nie dostarczamy na {value}."
|
||||
],
|
||||
"payment_method": [
|
||||
f"Akceptujemy płatność {value}.",
|
||||
f"Nie akceptujemy płatności {value}.",
|
||||
f"Możesz płacić {value}.",
|
||||
f"Płatność {value} jest możliwa.",
|
||||
f"Nie obsługujemy płatności {value}."
|
||||
],
|
||||
"dish": [
|
||||
f"Specjalnością jest {value}.",
|
||||
f"Nie mamy w ofercie {value}.",
|
||||
f"Zapraszamy na {value}.",
|
||||
f"{value} jest dostępne.",
|
||||
f"Nie mamy {value} w menu."
|
||||
],
|
||||
"time": [
|
||||
f"Godzina otwarcia to {value}.",
|
||||
f"Nieczynne o {value}.",
|
||||
f"Zapraszamy o {value}.",
|
||||
f"Otwarte od {value}.",
|
||||
f"Zamknięte o {value}."
|
||||
],
|
||||
"portion_size": [
|
||||
f"Dostępne porcje: {value}.",
|
||||
f"Brak porcji {value}.",
|
||||
f"Dostępne porcje: {value}.",
|
||||
f"Porcja {value} jest dostępna.",
|
||||
f"Nie mamy porcji {value}."
|
||||
],
|
||||
"price": [
|
||||
f"Cena to {value}.",
|
||||
f"Nie mamy ceny {value}.",
|
||||
f"Możesz kupić za {value}.",
|
||||
f"Cena wynosi {value}.",
|
||||
],
|
||||
"ingredient": [
|
||||
f"Składnik to {value}.",
|
||||
f"Nie mamy składnika {value}.",
|
||||
f"Zawiera {value}.",
|
||||
f"Składnik {value} jest dostępny.",
|
||||
],
|
||||
"allergy": [
|
||||
f"Zawiera alergen {value}.",
|
||||
f"Nie zawiera alergenu {value}.",
|
||||
f"Ostrzeżenie: alergen {value}.",
|
||||
f"Produkt wolny od alergenu {value}.",
|
||||
f"Nie mamy informacji o alergenie {value}."
|
||||
]
|
||||
}
|
||||
return ref_templates[slot]
|
||||
|
||||
slots_data = {
|
||||
"address": addresses,
|
||||
"payment_method": payment_methods,
|
||||
"dish": dishes,
|
||||
"time": times,
|
||||
"portion_size": portion_sizes,
|
||||
"price": price,
|
||||
"ingredient": ingredient,
|
||||
"allergy": allergy
|
||||
}
|
||||
|
||||
data = []
|
||||
|
||||
def remove_duplicates(list_of_dicts):
|
||||
list_of_tuples = [tuple(sorted(d.items())) for d in list_of_dicts]
|
||||
unique_tuples = set(list_of_tuples)
|
||||
unique_dicts = [dict(t) for t in unique_tuples]
|
||||
|
||||
return unique_dicts
|
||||
|
||||
def generate_sample(num_slots):
|
||||
selected_slots = random.sample(slots_data.keys(), num_slots)
|
||||
mr_list = []
|
||||
ref_list = []
|
||||
for slot in selected_slots:
|
||||
value = random.choice(slots_data[slot])
|
||||
mr_list.append(f"{slot}[{value}]")
|
||||
ref_list.append(random.choice(create_ref(slot, value)))
|
||||
if len(mr_list) == 1:
|
||||
return {"mr": repr(mr_list[0]), "ref": " ".join(ref_list)}
|
||||
else:
|
||||
return {"mr": ", ".join(mr_list), "ref": " ".join(ref_list)}
|
||||
|
||||
for num_slots in range(0, 6):
|
||||
for _ in range(5000):
|
||||
data.append(generate_sample(num_slots))
|
||||
|
||||
df = pd.DataFrame(remove_duplicates(data))
|
||||
df.to_csv('abc.csv', index=False)
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user