Compare commits

..

5 Commits

Author SHA1 Message Date
f039d6462b Merge pull request 'grammars-jsfg' (#2) from grammars-jsfg into master
Reviewed-on: #2
2024-05-07 19:25:55 +02:00
6acdea3310 evaluation 2024-05-07 19:25:33 +02:00
43b80ffa36 grammars 2024-05-07 18:19:32 +02:00
b114f1b833 Merge branch 'master' into grammars-jsfg 2024-05-07 16:10:09 +02:00
09abd92605 tmp 2024-05-07 16:09:18 +02:00
9 changed files with 152 additions and 2 deletions

42
chatbot/modules/nlu.py Normal file
View File

@ -0,0 +1,42 @@
import copy
from copy import deepcopy
import json
import os
import jsgf
class NLU:
def __init__(self):
self.grammars = [
jsgf.parse_grammar_file(f"grammars/{file_name}")
for file_name in os.listdir("grammars")
]
def get_dialog_act(self, rule):
slots = []
self.get_slots(rule.expansion, slots)
return {"act": rule.grammar.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 match(self, utterance):
list_of_illegal_character = [",", ".", "'", "?", "!", ":", "-", "/"]
for illegal_character in list_of_illegal_character[:-2]:
utterance = utterance.replace(f"{illegal_character}", "")
for illegal_character in list_of_illegal_character[-2:]:
utterance = utterance.replace(f"{illegal_character}", " ")
for grammar in self.grammars:
matched = grammar.find_matching_rules(utterance.lower())
if matched:
return self.get_dialog_act(matched[0])
return {"act": "null", "slots": []}

View File

@ -1,5 +1,5 @@
system Witamy w sklepie internetowym XYZ. W czym mogę pomóc? welcomemsg()
user Potrzbuje nowego biurka, czy jest cos specjalnego w ofercie, oczekuje biurka 3 metry na 1 metr request(items=biurka, size=3m x 1m)
user Potrzebuje nowego biurka, czy jest cos specjalnego w ofercie, oczekuje biurka 3 metry na 1 metr request(items=biurka, size=3m x 1m)
system Obecne modele biurek o długości 3m: Biurko WMI 3m x 1m; Biurko ABCD 3m x 70cm. Uprzejmie informujemy, iż dodatkowo na promocji znajduje się obecnie biurko Ania 2.70m x 1m inform(models=[Biurko WMI 3m x 1m, Biurko ABCD 3m x 70cm])&offer(promotion=Biurko Ania 2.70m x 1m)
user Z czego wykonane są te biurka i jakie są ceny request(material, price)
system Biurko WMI - 2000ZL, drewno debowe premium; Biurko ABCD - 1000ZL sklejka; BIurko Ania - 900ZL z 1200ZL, metal; inform(items= {model= Biurko WMI, material=drewno debowe premium, price=2000ZL}, {model=Biurko ABCD, material=sklejka, price=1000ZL}, {model=Biurko Ania, material=metal, price=900ZL (z 1200ZL)})

1 system Witamy w sklepie internetowym XYZ. W czym mogę pomóc? welcomemsg()
2 user Potrzbuje nowego biurka, czy jest cos specjalnego w ofercie, oczekuje biurka 3 metry na 1 metr Potrzebuje nowego biurka, czy jest cos specjalnego w ofercie, oczekuje biurka 3 metry na 1 metr request(items=biurka, size=3m x 1m)
3 system Obecne modele biurek o długości 3m: Biurko WMI 3m x 1m; Biurko ABCD 3m x 70cm. Uprzejmie informujemy, iż dodatkowo na promocji znajduje się obecnie biurko Ania 2.70m x 1m inform(models=[Biurko WMI 3m x 1m, Biurko ABCD 3m x 70cm])&offer(promotion=Biurko Ania 2.70m x 1m)
4 user Z czego wykonane są te biurka i jakie są ceny request(material, price)
5 system Biurko WMI - 2000ZL, drewno debowe premium; Biurko ABCD - 1000ZL sklejka; BIurko Ania - 900ZL z 1200ZL, metal; inform(items= {model= Biurko WMI, material=drewno debowe premium, price=2000ZL}, {model=Biurko ABCD, material=sklejka, price=1000ZL}, {model=Biurko Ania, material=metal, price=900ZL (z 1200ZL)})

26
evaluate.py Normal file
View File

@ -0,0 +1,26 @@
import os
import re
import pandas as pd
import numpy as np
from chatbot.modules.nlu import NLU
rows = 0
hits = 0
nlu = NLU()
for file_name in os.listdir("data"):
df = pd.read_csv(f"data/{file_name}", sep="\t", names=["user", "sentence", "acts"])
df = df[df.user == "user"]
data = np.array(df)
for row in data:
rows += 1
sentence = row[1]
cleaned_text = re.sub(r'\([^)]*\)', '', row[2])
user_acts = cleaned_text.split("&")
nlu_match = nlu.match(sentence)
if nlu_match["act"] in user_acts:
hits += 1
print(f"Accuracy: {(hits / rows) * 100}")

7
grammars/affirm.jsgf Normal file
View File

@ -0,0 +1,7 @@
#JSGF V1.0 UTF-8 pl;
grammar affirm;
public <affirm> = <affirms>;
<affirms> = Tak zdecydowanie | Tak | Tak to brzmi świetnie | Potwierdzam;

7
grammars/bye.jsgf Normal file
View File

@ -0,0 +1,7 @@
#JSGF V1.0 UTF-8 pl;
grammar bye;
public <bye> = <byes>;
<byes> = Do widzenia | (Nie | Tak) to wszystko Dziękuję | Dziękujemy za zakupy Miłego dnia | Dziekujemy za zakupy w sklepie XYZ Milego dnia | Dziękuję Życzę miłego dnia | To wszystko;

26
grammars/inform.jsgf Normal file
View File

@ -0,0 +1,26 @@
#JSGF V1.0 UTF-8 pl;
grammar inform;
public <zapytanie_cena> = Jaka jest cena produktu {produkt}*;
public <zapytanie_adres> = Jaki jest adres dostawy;
public <zapytanie_platnosc> = Jakie są dostępne metody płatności;
public <status_zap> = dostępne | niedostępne;
public <odpowiedz_cena> = Cena produktu {produkt}* wynosi <cena>*;
public <odpowiedz_adres> = Adres dostawy to <adres>;
public <odpowiedz_platnosc> = Dostępne metody płatności to <metody_platnosc>*;
public <cena> = <liczba> zł;
public <liczba> = jeden | dwie | trzy | cztery | pięć | sześć | siedem | osiem | dziewięć | dziesięć;
public <adres> = ulica <ulica> miasto <miasto> kod pocztowy <kod_pocztowy>;
public <ulica> = ul <nazwa_ulicy>;
public <miasto> = <nazwa_miasta>;
public <kod_pocztowy> = <cyfra><cyfra>-<cyfra><cyfra><cyfra>;
public <nazwa_ulicy> = XYZ;
public <nazwa_miasta> = XYZ;
public <cyfra> = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0;
public <metody_platnosc> = karta kredytowa | przelew bankowy | płatność przy odbiorze;

29
grammars/request.jsgf Normal file
View File

@ -0,0 +1,29 @@
#JSGF V1.0 UTF-8 pl;
grammar request;
public <kategorie> = kosmetyki | leżaki ogrodowe | artykuły spożywcze;
public <produkt> = szminka | krem do twarzy | szampon | balsam do ciała | maskara | leżak plażowy | leżak ogrodowy | parasol ogrodowy | grill | owoce | warzywa | mleko | jajka | pieczywo | ryby | mięso | woda mineralna | przekąski;
public <zapytanie1> = Czy macie w ofercie <produkt> {produkt}*;
public <zapytanie2> = Interesuje mnie zakup <produkt> {produkt}*;
public <zapytanie3> = Interesuje mnie zakup <produkt> {produkt} <kategorie> {kategorie}*;
public <zapytanie4> = Chciałbym kupić <produkt> {produkt}*;
public <zapytanie5> = Chciałbym kupić <produkt> {produkt} <kategorie> {kategorie}*;
public <zapytanie6> = Chciałabym kupić <produkt> {produkt}*;
public <zapytanie7> = Chciałabym kupić <produkt> {produkt} <kategorie> {kategorie}*;
public <zapytanie8> = Czy w sklepie dostępne są <produkt> {produkt}*;
public <zapytanie9> = Czy w sklepie dostępne są <produkt> {produkt} <kategorie> {kategorie}*;
public <status_zap> = dostępne | niedostępne;
public <odpowiedz1> = Tak mamy <produkt> {produkt}*;
public <odpowiedz2> = Tak mamy <produkt> {produkt} <kategorie> {kategorie}*;
public <odpowiedz3> = Niestety aktualnie nie mamy <produkt> {produkt}*;
public <odpowiedz4> = Niestety aktualnie nie mamy <produkt> {produkt} <kategorie> {kategorie}*;
public <odpowiedz5> = Tak w sklepie są <produkt> {produkt}*;
public <odpowiedz6> = Tak w sklepie są <produkt> {produkt} <kategorie> {kategorie}*;
public <odpowiedz7> = Niestety aktualnie nie ma <produkt> {produkt}*;
public <odpowiedz8> = Niestety aktualnie nie ma <produkt> {produkt} <kategorie> {kategorie}*;

6
grammars/welcomemsg.jsgf Normal file
View File

@ -0,0 +1,6 @@
#JSGF V1.0 UTF-8 pl;
grammar welcomemsg;
public <welcomemsg> = <welcomemsgs>;
<welcomemsgs> = Witamy w sklepie internetowym XYZ W czym mogę pomóc | Witaj W czym mogę Ci dzisiaj pomóc | Witamy w sklepie internetowym XYZ W swojej ofercie mamy artykuły ogrodowe meblowe oraz kosmetyki | Witam tutaj sklep wielobranzowy w czym moge pomoc | cześć chciałbym kupić {product};

View File

@ -1,5 +1,12 @@
import jsgf
request_grammar = jsgf.parse_grammar_file('./grammars/request.jsgf')
def main():
pass
utterance = 'Czy macie w ofercie balsam do ciała'
matched = request_grammar.find_matching_rules(utterance)
print(matched)
if __name__ == '__main__':