Merge pull request 'grammars-jsfg' (#2) from grammars-jsfg into master
Reviewed-on: #2
This commit is contained in:
commit
f039d6462b
42
chatbot/modules/nlu.py
Normal file
42
chatbot/modules/nlu.py
Normal 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": []}
|
@ -1,5 +1,5 @@
|
|||||||
system Witamy w sklepie internetowym XYZ. W czym mogę pomóc? welcomemsg()
|
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)
|
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)
|
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)})
|
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
26
evaluate.py
Normal 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
7
grammars/affirm.jsgf
Normal 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
7
grammars/bye.jsgf
Normal 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
26
grammars/inform.jsgf
Normal 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
29
grammars/request.jsgf
Normal 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
6
grammars/welcomemsg.jsgf
Normal 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};
|
9
main.py
9
main.py
@ -1,5 +1,12 @@
|
|||||||
|
import jsgf
|
||||||
|
|
||||||
|
request_grammar = jsgf.parse_grammar_file('./grammars/request.jsgf')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
pass
|
utterance = 'Czy macie w ofercie balsam do ciała'
|
||||||
|
matched = request_grammar.find_matching_rules(utterance)
|
||||||
|
print(matched)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user