diff --git a/conllu_generator.py b/conllu_generator.py index 28f2d06..df86cd5 100644 --- a/conllu_generator.py +++ b/conllu_generator.py @@ -1,15 +1,15 @@ -print("Script to automatically append data to data/dialog.conllu") -print("Start typing now. Press Ctrl+C to stop.") - -while True: - with open("data/train_dialog.conllu", "a") as f: - text = input("Text: ") - act = input("Intent: ") - slots = text.split(" ") - f.write( - f"\n# text: {text}\n# intent: {act}\n# slots:\n" - ) - for i, slot in enumerate(slots): - label = input(f"{i}/{slot} label: ") - f.write(f"{i+1}\t{slot}\t{act}\t{label}\n") - print("---") +print("Script to automatically append data to data/dialog.conllu") +print("Start typing now. Press Ctrl+C to stop.") + +while True: + with open("data/train_dialog.conllu", "a") as f: + text = input("Text: ") + act = input("Intent: ") + slots = text.split(" ") + f.write( + f"\n# text: {text}\n# intent: {act}\n# slots:\n" + ) + for i, slot in enumerate(slots): + label = input(f"{i}/{slot} label: ") + f.write(f"{i+1}\t{slot}\t{act}\t{label}\n") + print("---") diff --git a/data/test_dialog_46.conllu b/data/test_dialog_46.conllu index 08cfb9c..ea97222 100644 --- a/data/test_dialog_46.conllu +++ b/data/test_dialog_46.conllu @@ -1,641 +1,641 @@ -# text: Jakim systemem jesteś, co oferujesz? -# intent: welcomemsg -# slots: -1 Jakim welcomemsg NoLabel -2 systemem welcomemsg NoLabel -3 jesteś, welcomemsg NoLabel -4 co welcomemsg NoLabel -5 oferujesz? welcomemsg NoLabel - -# text: Chcialbym zamowic pizze peperoni -# intent: inform/order -# slots: -1 Chcialbym inform/order NoLabel -2 zamowic inform/order NoLabel -3 pizze inform/order B-food -4 peperoni inform/order B-pizza - -# text: A jest cos z salami? -# intent: inform/order -# slots: -1 A inform/order NoLabel -2 jest inform/order NoLabel -3 cos inform/order NoLabel -4 z inform/order NoLabel -5 salami? inform/order B-ingredient - -# text: To poproszę margharite -# intent: inform/order -# slots: -1 To inform/order NoLabel -2 poproszę inform/order NoLabel -3 margharite, inform/order B-pizza - -# text: czy jest mozliwosc podmiany sosu pomidorowego na smietanowy? -# intent: inform/order -# slots: -1 jest inform/order NoLabel -2 mozliwosc inform/order NoLabel -3 podmiany inform/order NoLabel -8 sosu inform/order NoLabel -4 pomidorowego inform/order I-sauce -5 na inform/order NoLabel -6 smietanowy? inform/order B-sauce -# text: To poproszę margharite zwykla -# intent: inform/order -# slots: -1 To inform/order NoLabel -2 poproszę inform/order NoLabel -3 margharite inform/order B-pizza -4 zwykla inform/order B-size - -# text: tak -# intent: affirm -# slots: -1 tak affirm NoLabel - -# text: Czy istnieje darmowa dostawa? -# intent: request/delivery-price -# slots: -1 Czy request/delivery-price NoLabel -2 istnieje request/delivery-price NoLabel -3 darmowa request/delivery-price NoLabel -4 dostawa? request/delivery-price NoLabel - -# text: To proszę o realizację zamówienia -# intent: inform/order-complete -# slots: -1 To inform/order-complete NoLabel -2 proszę inform/order-complete NoLabel -3 o inform/order-complete NoLabel -4 realizację inform/order-complete NoLabel -5 zamówienia inform/order-complete NoLabel - -# text: Kasztanowa 13/123, Toruń -# intent: inform/address -# slots: -1 Kasztanowa inform/address B-address -2 13/123, inform/address I-address -3 Toruń inform/address I-address - -# text: Proszę aby kurier zadzwonił na mój numer jak przyjedzie: nr: 213 532 212 -# intent: inform/phone -# slots: -1 Proszę inform/phone NoLabel -2 aby inform/phone NoLabel -3 kurier inform/phone NoLabel -4 zadzwonił inform/phone NoLabel -5 na inform/phone NoLabel -6 mój inform/phone NoLabel -7 numer inform/phone NoLabel -8 jak inform/phone NoLabel -9 przyjedzie: inform/phone NoLabel -10 nr: inform/phone NoLabel -11 213 inform/phone B-phone -12 532 inform/phone I-phone -13 212 inform/phone I-phone - -# text: Jestem głodny chciałbym zamówić kebaba -# intent: inform/order -# slots: -1 Jestem inform/order NoLabel -2 głodny inform/order NoLabel -3 chciałbym inform/order NoLabel -4 zamówić inform/order NoLabel -5 kebaba inform/order B-food - -# text: a jakie rodzaje pizzy? jakie kompozycje składników? -# intent: request/menu -# slots: -1 a request/menu NoLabel -2 jakie request/menu NoLabel -3 rodzaje request/menu NoLabel -4 pizzy? request/menu NoLabel -5 jakie request/menu NoLabel -6 kompozycje request/menu NoLabel -7 składników? request/menu NoLabel - -# text: jak duża jest pizza L?\? -# intent: request/size -# slots: -1 jak request/size NoLabel -2 duża request/size NoLabel -3 jest request/size NoLabel -4 pizza request/size B-food -5 L?\? request/size B-size - -# text: chciałbym taką z ananasem pizze -# intent: inform/order -# slots: -1 chciałbym inform/order NoLabel -2 taką inform/order NoLabel -3 z inform/order NoLabel -4 ananasem inform/order B-ingredient -5 pizze inform/order B-food - -# text: a czy można bez szynki? -# intent: inform/order -# slots: -1 a inform/order NoLabel -2 czy inform/order NoLabel -3 można inform/order NoLabel -4 bez inform/order B-ingredient/neg -5 szynki? inform/order I-ingredient/neg - -# text: Jaka cena? -# intent: request/price -# slots: -1 Jaka request/price NoLabel -2 cena? request/price NoLabel - -# text: a jaka cena dowozu? -# intent: request/delivery-price -# slots: -1 a request/delivery-price NoLabel -2 jaka request/delivery-price NoLabel -3 cena request/delivery-price NoLabel -4 dowozu? request/delivery-price NoLabel - -# text: okej to poproszę -# intent: affirm -# slots: -1 okej affirm NoLabel -2 to affirm NoLabel -3 poproszę affirm NoLabel - -# text: czy są dostępne jakieś sosy? -# intent: request/sauce -# slots: -1 czy request/sauce NoLabel -2 są request/sauce NoLabel -3 dostępne request/sauce NoLabel -4 jakieś request/sauce NoLabel -5 sosy? request/sauce NoLabel - -# text: czy sos dodatkowo kosztuje? -# intent: request/price -# slots: -1 czy request/price NoLabel -2 sos request/price NoLabel -3 dodatkowo request/price NoLabel -4 kosztuje? request/price NoLabel - -# text: a są do tego jakieś napoje? -# intent: request/drinks -# slots: -1 a request/drinks NoLabel -2 są request/drinks NoLabel -3 do request/drinks NoLabel -4 tego request/drinks NoLabel -5 jakieś request/drinks NoLabel -6 napoje? request/drinks NoLabel - -# text: jaka cena coli? -# intent: request(price) -# slots: -1 jaka request(price) NoLabel -2 cena request(price) NoLabel -3 coli? request(price) B-drink - -# text: to poproszę. Potwierdzam zamowienie -# intent: inform/order-complete -# slots: -1 to inform/order-complete NoLabel -2 poproszę. inform/order-complete NoLabel -3 Potwierdzam inform/order-complete NoLabel -4 zamowienie inform/order-complete NoLabel - -# text: 62-200 Gniezno, osiedle Grunwaldzkie 21/3117 -# intent: inform/address -# slots: -1 62-200 inform/address B-address -2 Gniezno, inform/address I-address -3 osiedle inform/address I-address -4 Grunwaldzkie inform/address I-address -5 21/3117 inform/address I-address - -# text: jaki czas oczekiwania? -# intent: request/time -# slots: -1 jaki request/time NoLabel -2 czas request/time NoLabel -3 oczekiwania? request/time NoLabel - -# text: Dziekuje -# intent: bye -# slots: -1 Dziekuje bye NoLabel - -# text: Dzień dobry, chciałbym zamówić pizzę -# intent: welcomemsg -# slots: -1 Dzień welcomemsg NoLabel -2 dobry, welcomemsg NoLabel -3 chciałbym welcomemsg NoLabel -4 zamówić welcomemsg NoLabel -5 pizzę welcomemsg NoLabel - -# text: W jakich rozmiarach są pizze? -# intent: request/size -# slots: -1 W request/size NoLabel -2 jakich request/size NoLabel -3 rozmiarach request/size NoLabel -4 są request/size NoLabel -5 pizze? request/size B-food - -# text: Poprosiłbym Tuna XL -# intent: inform/order -# slots: -1 Poprosiłbym inform/order NoLabel -2 Tuna inform/order B-pizza -3 XL inform/order B-size - -# text: Nie, to wszystko -# intent: inform/order-complete -# slots: -1 Nie, inform/order-complete NoLabel -2 to inform/order-complete NoLabel -3 wszystko inform/order-complete NoLabel - -# text: Głogowska 0/4 -# intent: inform/address -# slots: -1 Głogowska inform/address B-address -2 0/4 inform/address I-address - -# text: Kiedy mogę się spodziewać dostawy? -# intent: request/time -# slots: -1 Kiedy request/time NoLabel -2 mogę request/time NoLabel -3 się request/time NoLabel -4 spodziewać request/time NoLabel -5 dostawy? request/time NoLabel - -# text: Dzień dobry -# intent: welcomemsg -# slots: -1 Dzień welcomemsg NoLabel -2 dobry welcomemsg NoLabel - -# text: Chciałbym zamówić pizzę -# intent: request/menu -# slots: -1 Chciałbym request/menu NoLabel -2 zamówić request/menu NoLabel -3 pizzę request/menu B-food - -# text: Chciałbym pizzę z mięsem -# intent: inform/order -# slots: -1 Chciałbym inform/order NoLabel -2 pizzę inform/order B-food -3 z inform/order NoLabel -4 mięsem inform/order B-ingredient - -# text: w takim razie poproszę pizzę barcelona w rozmiarze XL -# intent: inform/order -# slots: -1 w inform/order NoLabel -2 takim inform/order NoLabel -3 razie inform/order NoLabel -4 poproszę inform/order NoLabel -5 pizzę inform/order B-food -6 barcelona inform/order B-pizza -7 w inform/order NoLabel -8 rozmiarze inform/order NoLabel -9 XL inform/order B-size - -# text: Napój typu pepsi cola w puszczce, ale żeby była zimna i bez cukru -# intent: inform/order -# slots: -1 Napój inform/order NoLabel -2 typu inform/order NoLabel -3 pepsi inform/order B-drink -4 cola inform/order B-drink -5 w inform/order NoLabel -6 puszczce, inform/order NoLabel -7 ale inform/order NoLabel -8 żeby inform/order NoLabel -9 była inform/order NoLabel -10 zimna inform/order B-temp -11 i inform/order NoLabel -12 bez inform/order B-sugar/neg -13 cukru inform/order I-sugar/neg - -# text: ulica niebieska 230/2 -# intent: inform/address -# slots: -1 ulica inform/address B-address -2 niebieska inform/address I-address -3 230/2 inform/address I-address - -# text: dziękuję -# intent: bye -# slots: -1 dziękuję bye NoLabel - -# text: Cześć, jakim systemem jesteś? -# intent: welcomemsg -# slots: -1 Cześć, welcomemsg NoLabel -2 jakim welcomemsg NoLabel -3 systemem welcomemsg NoLabel -4 jesteś? welcomemsg NoLabel - -# text: Czy jest możliwość zamówienia pizzy pół na pół? -# intent: inform/order -# slots: -1 Czy inform/order NoLabel -2 jest inform/order NoLabel -3 możliwość inform/order NoLabel -4 zamówienia inform/order NoLabel -5 pizzy inform/order B-food -6 pół inform/order B-pizza -7 na inform/order I-pizza -8 pół? inform/order I-pizza - -# text: jakie pizze są w menu? -# intent: request/menu -# slots: -1 jakie request/menu NoLabel -2 pizze request/menu NoLabel -3 są request/menu NoLabel -4 w request/menu NoLabel -5 menu? request/menu NoLabel - -# text: w takim razie poproszę 4x margarite XL -# intent: inform/order -# slots: -1 w inform/order NoLabel -2 takim inform/order NoLabel -3 razie inform/order NoLabel -4 poproszę inform/order NoLabel -5 4x inform/order B-quantity -6 margarite inform/order B-pizza -7 XL inform/order B-size - -# text: Lipinki Łużyckie, Łączna 46 -# intent: inform/address -# slots: -1 Lipinki inform/address B-address -2 Łużyckie, inform/address I-address -3 Łączna inform/address I-address -4 46 inform/address I-address - -# text: Dzięki! -# intent: bye -# slots: -1 Dzięki! bye NoLabel - -# text: ile kosztuje dostawa? -# intent: request/delivery-price -# slots: -1 ile request/delivery-price NoLabel -2 kosztuje request/delivery-price NoLabel -3 dostawa? request/delivery-price NoLabel - -# text: a jakie są dostępne pizze? -# intent: request/menu -# slots: -1 a request/menu NoLabel -2 jakie request/menu NoLabel -3 są request/menu NoLabel -4 dostępne request/menu NoLabel -5 pizze? request/menu B-food - -# text: świetnie, w takim razie poproszę dwie duże pizze diavola oraz margaritę -# intent: inform/order -# slots: -1 świetnie, inform/order NoLabel -2 w inform/order NoLabel -3 takim inform/order NoLabel -4 razie inform/order NoLabel -5 poproszę inform/order NoLabel -6 dwie inform/order B-quantity -7 duże inform/order B-size -8 pizze inform/order B-food -9 diavola inform/order B-pizza -10 oraz inform/order NoLabel -11 margaritę inform/order B-pizza - -# text: tak, poproszę jeden -# intent: affirm -# slots: -1 tak, affirm NoLabel -2 poproszę affirm NoLabel -3 jeden affirm B-quantity - -# text: ze Szczebrzeszyna, powiat Łękołody -# intent: inform/name -# slots: -1 ze inform/name NoLabel -2 Szczebrzeszyna, inform/name B-address -3 powiat inform/name I-address -4 Łękołody inform/name I-address - -# text: Grzegorz Brzęczyszczykiewicz -# intent: inform/name -# slots: -1 Grzegorz inform/name B-name -2 Brzęczyszczykiewicz, inform/name I-name - -# text: a jakie są dostępne pizze? -# intent: request/menu -# slots: -1 a request/menu NoLabel -2 jakie request/menu NoLabel -3 są request/menu NoLabel -4 dostępne request/menu NoLabel -5 pizze? request/menu B-food - -# text: świetnie, w takim razie poproszę dwie duże pizze diavola oraz margaritę -# intent: inform/order -# slots: -1 świetnie, inform/order NoLabel -2 w inform/order NoLabel -3 takim inform/order NoLabel -4 razie inform/order NoLabel -5 poproszę inform/order NoLabel -6 dwie inform/order B-quantity -7 duże inform/order B-size -8 pizze inform/order B-food -9 diavola inform/order B-pizza -10 oraz inform/order NoLabel -11 margaritę inform/order B-pizza - -# text: tak, poproszę jeden -# intent: inform/order -# slots: -1 tak, inform/order NoLabel -2 poproszę inform/order NoLabel -3 jeden inform/order B-quantity - -# text: zapłacę kartą przy dostawie -# intent: inform/order -# slots: -1 zapłacę inform/order NoLabel -2 kartą inform/order B-payment-method -3 przy inform/order NoLabel -4 dostawie inform/order B-delivery - -# text: chciałbym zamówić pizzę wegetariańską w średnim rozmiarze -# intent: inform/order -# slots: -1 chciałbym inform/order NoLabel -2 zamówić inform/order NoLabel -3 pizzę inform/order B-food -4 wegetariańską inform/order B-pizza -5 w inform/order NoLabel -6 średnim inform/order B-size -7 rozmiarze inform/order NoLabel - -# text: a co znajduje się domyślnie na takiej pizzy? -# intent: request/ingredients -# slots: -1 a request/ingredients NoLabel -2 co request/ingredients NoLabel -3 znajduje request/ingredients NoLabel -4 się request/ingredients NoLabel -5 domyślnie request/ingredients NoLabel -6 na request/ingredients NoLabel -7 takiej request/ingredients NoLabel -8 pizzy? request/ingredients B-food - -# text: Poproszę wersję klasyczną średnią -# intent: inform/order -# slots: -1 Poproszę inform/order NoLabel -2 wersję inform/order NoLabel -3 klasyczną inform/order B-type -4 średnią inform/order B-size - -# text: Ile będzie ona kosztować? -# intent: request/price -# slots: -1 Ile request/price NoLabel -2 będzie request/price NoLabel -3 ona request/price NoLabel -4 kosztować? request/price NoLabel - -# text: Okej, to poproszę tą pizzę -# intent: inform/order -# slots: -1 Okej, inform/order NoLabel -2 to inform/order NoLabel -3 poproszę inform/order NoLabel -4 tą inform/order NoLabel -5 pizzę inform/order B-food - -# text: Na wynos -# intent: inform/delivery -# slots: -1 Na inform/delivery NoLabel -2 wynos inform/delivery B-delivery - -# text: płatność gotówką -# intent: inform/payment -# slots: -1 płatność inform/payment NoLabel -2 gotówką inform/payment B-payment-method - -# text: Dzień dobry -# intent: welcomemsg -# slots: -1 Dzień welcomemsg NoLabel -2 dobry welcomemsg NoLabel - -# text: a rozmiar średni o ile jest mniejszy od dużego? -# intent: request/size -# slots: -1 a request/size NoLabel -2 rozmiar request/size NoLabel -3 średni request/size B-size -4 o request/size NoLabel -5 ile request/size NoLabel -6 jest request/size NoLabel -7 mniejszy request/size NoLabel -8 od request/size NoLabel -9 dużego? request/size B-size - -# text: dużą colę poproszę, jednakże bez cukru -# intent: inform/order -# slots: -1 dużą inform/order B-size -2 colę inform/order B-drink -3 poproszę, inform/order NoLabel -4 jednakże inform/order NoLabel -5 bez inform/order B-option -6 cukru inform/order I-option - -# text: Płatność będzie kartą. -# intent: inform/payment -# slots: -1 Płatność inform/payment NoLabel -2 będzie inform/payment NoLabel -3 kartą. inform/payment B-payment-method - -# text: Zamówienie na wynos, ale odbiorę osobiście -# intent: inform/delivery -# slots: -1 Zamówienie inform/delivery NoLabel -2 na inform/delivery NoLabel -3 wynos, inform/delivery B-delivery -4 ale inform/delivery NoLabel -5 odbiorę inform/delivery NoLabel -6 osobiście inform/delivery B-delivery - -# text: poproszę jedynie podać przybliżony czas przygotowywania dania -# intent: request/time -# slots: -1 poproszę request/time NoLabel -2 jedynie request/time NoLabel -3 podać request/time NoLabel -4 przybliżony request/time NoLabel -5 czas request/time NoLabel -6 przygotowywania request/time NoLabel -7 dania request/time NoLabel - -# text: świetnie, w takim razie poproszę dwie duże pizzę ananasową, jedną dużą diavola oraz jako tą w gratisie margarite -# intent: inform/order -# slots: -1 świetnie, inform/order NoLabel -2 w inform/order NoLabel -3 takim inform/order NoLabel -4 razie inform/order NoLabel -5 poproszę inform/order NoLabel -6 dwie inform/order B-quantity -7 duże inform/order B-size -8 pizzę inform/order B-food -9 ananasową, inform/order B-pizza -10 jedną inform/order B-quantity -11 dużą inform/order B-size -12 diavola inform/order B-pizza -13 oraz inform/order NoLabel -14 jako inform/order NoLabel -15 tą inform/order NoLabel -16 w inform/order NoLabel -17 gratisie inform/order NoLabel -18 margarite inform/order B-pizza - -# text: w takim razie poproszę jeden -# intent: inform/order -# slots: -1 w inform/order NoLabel -2 takim inform/order NoLabel -3 razie inform/order NoLabel -4 poproszę inform/order NoLabel -5 jeden inform/order B-quantity - -# text: zapłacę kartą -# intent: inform/payment -# slots: -1 zapłacę inform/payment NoLabel -2 kartą inform/payment B-payment-method - -# text: dziękuję bardzo -# intent: bye -# slots: -1 dziękuję bye NoLabel -2 bardzo bye NoLabel +# text: Jakim systemem jesteś, co oferujesz? +# intent: welcomemsg +# slots: +1 Jakim welcomemsg NoLabel +2 systemem welcomemsg NoLabel +3 jesteś, welcomemsg NoLabel +4 co welcomemsg NoLabel +5 oferujesz? welcomemsg NoLabel + +# text: Chcialbym zamowic pizze peperoni +# intent: inform/order +# slots: +1 Chcialbym inform/order NoLabel +2 zamowic inform/order NoLabel +3 pizze inform/order B-food +4 peperoni inform/order B-pizza + +# text: A jest cos z salami? +# intent: inform/order +# slots: +1 A inform/order NoLabel +2 jest inform/order NoLabel +3 cos inform/order NoLabel +4 z inform/order NoLabel +5 salami? inform/order B-ingredient + +# text: To poproszę margharite +# intent: inform/order +# slots: +1 To inform/order NoLabel +2 poproszę inform/order NoLabel +3 margharite, inform/order B-pizza + +# text: czy jest mozliwosc podmiany sosu pomidorowego na smietanowy? +# intent: inform/order +# slots: +1 jest inform/order NoLabel +2 mozliwosc inform/order NoLabel +3 podmiany inform/order NoLabel +8 sosu inform/order NoLabel +4 pomidorowego inform/order I-sauce +5 na inform/order NoLabel +6 smietanowy? inform/order B-sauce +# text: To poproszę margharite zwykla +# intent: inform/order +# slots: +1 To inform/order NoLabel +2 poproszę inform/order NoLabel +3 margharite inform/order B-pizza +4 zwykla inform/order B-size + +# text: tak +# intent: affirm +# slots: +1 tak affirm NoLabel + +# text: Czy istnieje darmowa dostawa? +# intent: request/delivery-price +# slots: +1 Czy request/delivery-price NoLabel +2 istnieje request/delivery-price NoLabel +3 darmowa request/delivery-price NoLabel +4 dostawa? request/delivery-price NoLabel + +# text: To proszę o realizację zamówienia +# intent: inform/order-complete +# slots: +1 To inform/order-complete NoLabel +2 proszę inform/order-complete NoLabel +3 o inform/order-complete NoLabel +4 realizację inform/order-complete NoLabel +5 zamówienia inform/order-complete NoLabel + +# text: Kasztanowa 13/123, Toruń +# intent: inform/address +# slots: +1 Kasztanowa inform/address B-address +2 13/123, inform/address I-address +3 Toruń inform/address I-address + +# text: Proszę aby kurier zadzwonił na mój numer jak przyjedzie: nr: 213 532 212 +# intent: inform/phone +# slots: +1 Proszę inform/phone NoLabel +2 aby inform/phone NoLabel +3 kurier inform/phone NoLabel +4 zadzwonił inform/phone NoLabel +5 na inform/phone NoLabel +6 mój inform/phone NoLabel +7 numer inform/phone NoLabel +8 jak inform/phone NoLabel +9 przyjedzie: inform/phone NoLabel +10 nr: inform/phone NoLabel +11 213 inform/phone B-phone +12 532 inform/phone I-phone +13 212 inform/phone I-phone + +# text: Jestem głodny chciałbym zamówić kebaba +# intent: inform/order +# slots: +1 Jestem inform/order NoLabel +2 głodny inform/order NoLabel +3 chciałbym inform/order NoLabel +4 zamówić inform/order NoLabel +5 kebaba inform/order B-food + +# text: a jakie rodzaje pizzy? jakie kompozycje składników? +# intent: request/menu +# slots: +1 a request/menu NoLabel +2 jakie request/menu NoLabel +3 rodzaje request/menu NoLabel +4 pizzy? request/menu NoLabel +5 jakie request/menu NoLabel +6 kompozycje request/menu NoLabel +7 składników? request/menu NoLabel + +# text: jak duża jest pizza L?\? +# intent: request/size +# slots: +1 jak request/size NoLabel +2 duża request/size NoLabel +3 jest request/size NoLabel +4 pizza request/size B-food +5 L?\? request/size B-size + +# text: chciałbym taką z ananasem pizze +# intent: inform/order +# slots: +1 chciałbym inform/order NoLabel +2 taką inform/order NoLabel +3 z inform/order NoLabel +4 ananasem inform/order B-ingredient +5 pizze inform/order B-food + +# text: a czy można bez szynki? +# intent: inform/order +# slots: +1 a inform/order NoLabel +2 czy inform/order NoLabel +3 można inform/order NoLabel +4 bez inform/order B-ingredient/neg +5 szynki? inform/order I-ingredient/neg + +# text: Jaka cena? +# intent: request/price +# slots: +1 Jaka request/price NoLabel +2 cena? request/price NoLabel + +# text: a jaka cena dowozu? +# intent: request/delivery-price +# slots: +1 a request/delivery-price NoLabel +2 jaka request/delivery-price NoLabel +3 cena request/delivery-price NoLabel +4 dowozu? request/delivery-price NoLabel + +# text: okej to poproszę +# intent: affirm +# slots: +1 okej affirm NoLabel +2 to affirm NoLabel +3 poproszę affirm NoLabel + +# text: czy są dostępne jakieś sosy? +# intent: request/sauce +# slots: +1 czy request/sauce NoLabel +2 są request/sauce NoLabel +3 dostępne request/sauce NoLabel +4 jakieś request/sauce NoLabel +5 sosy? request/sauce NoLabel + +# text: czy sos dodatkowo kosztuje? +# intent: request/price +# slots: +1 czy request/price NoLabel +2 sos request/price NoLabel +3 dodatkowo request/price NoLabel +4 kosztuje? request/price NoLabel + +# text: a są do tego jakieś napoje? +# intent: request/drinks +# slots: +1 a request/drinks NoLabel +2 są request/drinks NoLabel +3 do request/drinks NoLabel +4 tego request/drinks NoLabel +5 jakieś request/drinks NoLabel +6 napoje? request/drinks NoLabel + +# text: jaka cena coli? +# intent: request/price +# slots: +1 jaka request/price NoLabel +2 cena request/price NoLabel +3 coli? request/price B-drink + +# text: to poproszę. Potwierdzam zamowienie +# intent: inform/order-complete +# slots: +1 to inform/order-complete NoLabel +2 poproszę. inform/order-complete NoLabel +3 Potwierdzam inform/order-complete NoLabel +4 zamowienie inform/order-complete NoLabel + +# text: 62-200 Gniezno, osiedle Grunwaldzkie 21/3117 +# intent: inform/address +# slots: +1 62-200 inform/address B-address +2 Gniezno, inform/address I-address +3 osiedle inform/address I-address +4 Grunwaldzkie inform/address I-address +5 21/3117 inform/address I-address + +# text: jaki czas oczekiwania? +# intent: request/time +# slots: +1 jaki request/time NoLabel +2 czas request/time NoLabel +3 oczekiwania? request/time NoLabel + +# text: Dziekuje +# intent: bye +# slots: +1 Dziekuje bye NoLabel + +# text: Dzień dobry, chciałbym zamówić pizzę +# intent: welcomemsg +# slots: +1 Dzień welcomemsg NoLabel +2 dobry, welcomemsg NoLabel +3 chciałbym welcomemsg NoLabel +4 zamówić welcomemsg NoLabel +5 pizzę welcomemsg NoLabel + +# text: W jakich rozmiarach są pizze? +# intent: request/size +# slots: +1 W request/size NoLabel +2 jakich request/size NoLabel +3 rozmiarach request/size NoLabel +4 są request/size NoLabel +5 pizze? request/size B-food + +# text: Poprosiłbym Tuna XL +# intent: inform/order +# slots: +1 Poprosiłbym inform/order NoLabel +2 Tuna inform/order B-pizza +3 XL inform/order B-size + +# text: Nie, to wszystko +# intent: inform/order-complete +# slots: +1 Nie, inform/order-complete NoLabel +2 to inform/order-complete NoLabel +3 wszystko inform/order-complete NoLabel + +# text: Głogowska 0/4 +# intent: inform/address +# slots: +1 Głogowska inform/address B-address +2 0/4 inform/address I-address + +# text: Kiedy mogę się spodziewać dostawy? +# intent: request/time +# slots: +1 Kiedy request/time NoLabel +2 mogę request/time NoLabel +3 się request/time NoLabel +4 spodziewać request/time NoLabel +5 dostawy? request/time NoLabel + +# text: Dzień dobry +# intent: welcomemsg +# slots: +1 Dzień welcomemsg NoLabel +2 dobry welcomemsg NoLabel + +# text: Chciałbym zamówić pizzę +# intent: request/menu +# slots: +1 Chciałbym request/menu NoLabel +2 zamówić request/menu NoLabel +3 pizzę request/menu B-food + +# text: Chciałbym pizzę z mięsem +# intent: inform/order +# slots: +1 Chciałbym inform/order NoLabel +2 pizzę inform/order B-food +3 z inform/order NoLabel +4 mięsem inform/order B-ingredient + +# text: w takim razie poproszę pizzę barcelona w rozmiarze XL +# intent: inform/order +# slots: +1 w inform/order NoLabel +2 takim inform/order NoLabel +3 razie inform/order NoLabel +4 poproszę inform/order NoLabel +5 pizzę inform/order B-food +6 barcelona inform/order B-pizza +7 w inform/order NoLabel +8 rozmiarze inform/order NoLabel +9 XL inform/order B-size + +# text: Napój typu pepsi cola w puszczce, ale żeby była zimna i bez cukru +# intent: inform/order +# slots: +1 Napój inform/order NoLabel +2 typu inform/order NoLabel +3 pepsi inform/order B-drink +4 cola inform/order B-drink +5 w inform/order NoLabel +6 puszczce, inform/order NoLabel +7 ale inform/order NoLabel +8 żeby inform/order NoLabel +9 była inform/order NoLabel +10 zimna inform/order NoLabel +11 i inform/order NoLabel +12 bez inform/order NoLabel +13 cukru inform/order NoLabel + +# text: ulica niebieska 230/2 +# intent: inform/address +# slots: +1 ulica inform/address B-address +2 niebieska inform/address I-address +3 230/2 inform/address I-address + +# text: dziękuję +# intent: bye +# slots: +1 dziękuję bye NoLabel + +# text: Cześć, jakim systemem jesteś? +# intent: welcomemsg +# slots: +1 Cześć, welcomemsg NoLabel +2 jakim welcomemsg NoLabel +3 systemem welcomemsg NoLabel +4 jesteś? welcomemsg NoLabel + +# text: Czy jest możliwość zamówienia pizzy pół na pół? +# intent: inform/order +# slots: +1 Czy inform/order NoLabel +2 jest inform/order NoLabel +3 możliwość inform/order NoLabel +4 zamówienia inform/order NoLabel +5 pizzy inform/order B-food +6 pół inform/order B-pizza +7 na inform/order I-pizza +8 pół? inform/order I-pizza + +# text: jakie pizze są w menu? +# intent: request/menu +# slots: +1 jakie request/menu NoLabel +2 pizze request/menu NoLabel +3 są request/menu NoLabel +4 w request/menu NoLabel +5 menu? request/menu NoLabel + +# text: w takim razie poproszę 4x margarite XL +# intent: inform/order +# slots: +1 w inform/order NoLabel +2 takim inform/order NoLabel +3 razie inform/order NoLabel +4 poproszę inform/order NoLabel +5 4x inform/order B-quantity +6 margarite inform/order B-pizza +7 XL inform/order B-size + +# text: Lipinki Łużyckie, Łączna 46 +# intent: inform/address +# slots: +1 Lipinki inform/address B-address +2 Łużyckie, inform/address I-address +3 Łączna inform/address I-address +4 46 inform/address I-address + +# text: Dzięki! +# intent: bye +# slots: +1 Dzięki! bye NoLabel + +# text: ile kosztuje dostawa? +# intent: request/delivery-price +# slots: +1 ile request/delivery-price NoLabel +2 kosztuje request/delivery-price NoLabel +3 dostawa? request/delivery-price NoLabel + +# text: a jakie są dostępne pizze? +# intent: request/menu +# slots: +1 a request/menu NoLabel +2 jakie request/menu NoLabel +3 są request/menu NoLabel +4 dostępne request/menu NoLabel +5 pizze? request/menu B-food + +# text: świetnie, w takim razie poproszę trzy duże pizze diavola oraz margaritę +# intent: inform/order +# slots: +1 świetnie, inform/order NoLabel +2 w inform/order NoLabel +3 takim inform/order NoLabel +4 razie inform/order NoLabel +5 poproszę inform/order NoLabel +6 trzy inform/order B-quantity +7 duże inform/order B-size +8 pizze inform/order B-food +9 diavola inform/order B-pizza +10 oraz inform/order NoLabel +11 margaritę inform/order B-pizza + +# text: tak, poproszę jeden +# intent: affirm +# slots: +1 tak, affirm NoLabel +2 poproszę affirm NoLabel +3 jeden affirm B-quantity + +# text: ze Szczebrzeszyna, powiat Łękołody +# intent: inform/address +# slots: +1 ze inform/address NoLabel +2 Szczebrzeszyna, inform/address B-address +3 powiat inform/address I-address +4 Łękołody inform/address I-address + +# text: Grzegorz Brzęczyszczykiewicz +# intent: inform/name +# slots: +1 Grzegorz inform/name B-name +2 Brzęczyszczykiewicz, inform/name I-name + +# text: a jakie są dostępne pizze? +# intent: request/menu +# slots: +1 a request/menu NoLabel +2 jakie request/menu NoLabel +3 są request/menu NoLabel +4 dostępne request/menu NoLabel +5 pizze? request/menu B-food + +# text: świetnie, w takim razie poproszę dwie duże pizze diavola oraz margaritę +# intent: inform/order +# slots: +1 świetnie, inform/order NoLabel +2 w inform/order NoLabel +3 takim inform/order NoLabel +4 razie inform/order NoLabel +5 poproszę inform/order NoLabel +6 dwie inform/order B-quantity +7 duże inform/order B-size +8 pizze inform/order B-food +9 diavola inform/order B-pizza +10 oraz inform/order NoLabel +11 margaritę inform/order B-pizza + +# text: tak, poproszę jeden +# intent: inform/order +# slots: +1 tak, inform/order NoLabel +2 poproszę inform/order NoLabel +3 jeden inform/order B-quantity + +# text: zapłacę kartą przy dostawie +# intent: inform/order +# slots: +1 zapłacę inform/order NoLabel +2 kartą inform/order B-payment-method +3 przy inform/order NoLabel +4 dostawie inform/order B-delivery + +# text: chciałbym zamówić pizzę wegetariańską w średnim rozmiarze +# intent: inform/order +# slots: +1 chciałbym inform/order NoLabel +2 zamówić inform/order NoLabel +3 pizzę inform/order B-food +4 wegetariańską inform/order B-pizza +5 w inform/order NoLabel +6 średnim inform/order B-size +7 rozmiarze inform/order NoLabel + +# text: a co znajduje się domyślnie na takiej pizzy? +# intent: request/ingredients +# slots: +1 a request/ingredients NoLabel +2 co request/ingredients NoLabel +3 znajduje request/ingredients NoLabel +4 się request/ingredients NoLabel +5 domyślnie request/ingredients NoLabel +6 na request/ingredients NoLabel +7 takiej request/ingredients NoLabel +8 pizzy? request/ingredients B-food + +# text: Poproszę wersję klasyczną średnią +# intent: inform/order +# slots: +1 Poproszę inform/order NoLabel +2 wersję inform/order NoLabel +3 klasyczną inform/order NoLabel +4 średnią inform/order B-size + +# text: Ile będzie ona kosztować? +# intent: request/price +# slots: +1 Ile request/price NoLabel +2 będzie request/price NoLabel +3 ona request/price NoLabel +4 kosztować? request/price NoLabel + +# text: Okej, to poproszę tą pizzę +# intent: inform/order +# slots: +1 Okej, inform/order NoLabel +2 to inform/order NoLabel +3 poproszę inform/order NoLabel +4 tą inform/order NoLabel +5 pizzę inform/order B-food + +# text: Na wynos +# intent: inform/delivery +# slots: +1 Na inform/delivery NoLabel +2 wynos inform/delivery B-delivery + +# text: płatność gotówką +# intent: inform/payment +# slots: +1 płatność inform/payment NoLabel +2 gotówką inform/payment B-payment-method + +# text: Dzień dobry +# intent: welcomemsg +# slots: +1 Dzień welcomemsg NoLabel +2 dobry welcomemsg NoLabel + +# text: a rozmiar średni o ile jest mniejszy od dużego? +# intent: request/size +# slots: +1 a request/size NoLabel +2 rozmiar request/size NoLabel +3 średni request/size B-size +4 o request/size NoLabel +5 ile request/size NoLabel +6 jest request/size NoLabel +7 mniejszy request/size NoLabel +8 od request/size NoLabel +9 dużego? request/size B-size + +# text: dużą colę poproszę, jednakże bez cukru +# intent: inform/order +# slots: +1 dużą inform/order B-size +2 colę inform/order B-drink +3 poproszę, inform/order NoLabel +4 jednakże inform/order NoLabel +5 bez inform/order NoLabel +6 cukru inform/order NoLabel + +# text: Płatność będzie kartą. +# intent: inform/payment +# slots: +1 Płatność inform/payment NoLabel +2 będzie inform/payment NoLabel +3 kartą. inform/payment B-payment-method + +# text: Zamówienie na wynos, ale odbiorę osobiście +# intent: inform/delivery +# slots: +1 Zamówienie inform/delivery NoLabel +2 na inform/delivery NoLabel +3 wynos, inform/delivery B-delivery +4 ale inform/delivery NoLabel +5 odbiorę inform/delivery NoLabel +6 osobiście inform/delivery B-delivery + +# text: poproszę jedynie podać przybliżony czas przygotowywania dania +# intent: request/time +# slots: +1 poproszę request/time NoLabel +2 jedynie request/time NoLabel +3 podać request/time NoLabel +4 przybliżony request/time NoLabel +5 czas request/time NoLabel +6 przygotowywania request/time NoLabel +7 dania request/time NoLabel + +# text: świetnie, w takim razie poproszę dwie duże pizzę ananasową, jedną dużą diavola oraz jako tą w gratisie margarite +# intent: inform/order +# slots: +1 świetnie, inform/order NoLabel +2 w inform/order NoLabel +3 takim inform/order NoLabel +4 razie inform/order NoLabel +5 poproszę inform/order NoLabel +6 dwie inform/order B-quantity +7 duże inform/order B-size +8 pizzę inform/order B-food +9 ananasową, inform/order B-pizza +10 jedną inform/order B-quantity +11 dużą inform/order B-size +12 diavola inform/order B-pizza +13 oraz inform/order NoLabel +14 jako inform/order NoLabel +15 tą inform/order NoLabel +16 w inform/order NoLabel +17 gratisie inform/order NoLabel +18 margarite inform/order B-pizza + +# text: w takim razie poproszę jeden +# intent: inform/order +# slots: +1 w inform/order NoLabel +2 takim inform/order NoLabel +3 razie inform/order NoLabel +4 poproszę inform/order NoLabel +5 jeden inform/order B-quantity + +# text: zapłacę kartą +# intent: inform/payment +# slots: +1 zapłacę inform/payment NoLabel +2 kartą inform/payment B-payment-method + +# text: dziękuję bardzo +# intent: bye +# slots: +1 dziękuję bye NoLabel +2 bardzo bye NoLabel diff --git a/data/train_dialog.conllu b/data/train_dialog.conllu index 06ab923..7ed665d 100644 --- a/data/train_dialog.conllu +++ b/data/train_dialog.conllu @@ -332,11 +332,11 @@ 3 w request/menu NoLabel 4 ofercie request/menu NoLabel -# text: chciałbym 3 pizze, hawajskie duże +# text: chciałbym trzy pizze, hawajskie duże # intent: inform/order # slots: 1 chciałbym inform/order NoLabel -2 3 inform/order B-quantity +2 trzy inform/order B-quantity 3 pizze, inform/order B-food 4 hawajskie inform/order B-pizza 5 duże inform/order B-size @@ -585,11 +585,11 @@ 4 tuna inform/order B-pizza 5 XL inform/order B-size -# text: wezmę 3 pizze tuna, średnią, dużą i bardzo dużą +# text: wezmę 3x pizze tuna, średnią, dużą i bardzo dużą # intent: inform/order # slots: 1 wezmę inform/order NoLabel -2 3 inform/order B-quantity +2 3x inform/order B-quantity 3 pizze inform/order B-food 4 tuna, inform/order B-pizza 5 średnią, inform/order B-size @@ -825,6 +825,14 @@ 1 jakie request/ingredients NoLabel 2 składniki request/ingredients NoLabel +# text: co jest na pizzy +# intent: request/ingredients +# slots: +1 co request/ingredients NoLabel +2 jest request/ingredients NoLabel +3 na request/ingredients NoLabel +4 pizzy request/ingredients NoLabel + # text: jakie są napoje # intent: request/drinks # slots: @@ -850,3 +858,54 @@ 2 macie request/drinks NoLabel 3 do request/drinks NoLabel 4 picia request/drinks NoLabel + +# text: czy są dostępne jakieś sosy? +# intent: request/sauce +# slots: +1 czy request/sauce NoLabel +2 są request/sauce NoLabel +3 dostępne request/sauce NoLabel +4 jakieś request/sauce NoLabel +5 sosy? request/sauce NoLabel + +# text: Grzegorz Pieczarski +# intent: inform/name +# slots: +1 Grzegorz inform/name B-name +2 Pieczarski inform/name I-name + +# text: Sergiusz Kaczmarek +# intent: inform/name +# slots: +1 Sergiusz inform/name B-name +2 Kaczmarek inform/name I-name + +# text: jaki koszt dowozu +# intent: request/delivery-price +# slots: +1 jaki request/delivery-price NoLabel +2 koszt request/delivery-price NoLabel +3 dowozu request/delivery-price NoLabel + +# text: jakie sosy w menu? +# intent: request/sauce +# slots: +1 jakie request/sauce NoLabel +2 sosy request/sauce NoLabel +3 w request/sauce NoLabel +4 menu? request/sauce NoLabel + +# text: Napój pepsi i cola +# intent: inform/order +# slots: +1 Napój inform/order NoLabel +2 pepsi inform/order B-drink +3 i inform/order NoLabel +4 cola inform/order B-drink + +# text: woda i sok +# intent: inform/order +# slots: +1 woda inform/order B-drink +2 i inform/order NoLabel +3 sok inform/order B-drink \ No newline at end of file diff --git a/evaluate.py b/evaluate.py index 67e849d..989fa18 100644 --- a/evaluate.py +++ b/evaluate.py @@ -1,45 +1,63 @@ -import re -import os -import pandas as pd -import numpy as np -from nlu_utils import predict_multiple -from flair.models import SequenceTagger - -def __parse_acts(acts): - acts_split = acts.split('&') - remove_slot_regex = "[\(\[].*?[\)\]]" - return set(re.sub(remove_slot_regex, "", act) for act in acts_split) - -def __parse_predictions(predictions): - return set(prediction.split('/')[0] for prediction in predictions) - -# Exploratory tests -frame_model = SequenceTagger.load('frame-model-prod/best-model.pt') -# slot_model = SequenceTagger.load('slot-model-prod/final-model.pt') - -total_acts = 0 -act_correct_predictions = 0 -slot_correct_predictions = 0 - -for file_name in os.listdir('data'): - if file_name.split('.')[-1] != 'tsv': - continue - - df = pd.read_csv(f'data/{file_name}', sep='\t', names=['kto', 'treść', 'akt']) - df = df[df.kto == 'user'] - all_data = np.array(df) - - for row in all_data: - sentence = row[1] - acts = __parse_acts(row[2]) - - predictions_raw = predict_multiple(frame_model, sentence.split(), 'frame') - predictions = __parse_predictions(predictions_raw) - - for act in acts: - total_acts += 1 - if act in predictions: - act_correct_predictions += 1 - - +import re +import os +import pandas as pd +import numpy as np +from nlu_utils import predict_multiple +from flair.models import SequenceTagger +from conllu import parse_incr +from flair.data import Corpus +from nlu_utils import conllu2flair, nolabel2o + +# Frame model evaluation +frame_model = SequenceTagger.load('frame-model-prod/best-model.pt') +with open('data/test_dialog_46.conllu', encoding='utf-8') as trainfile: + testset = list(parse_incr(trainfile, fields=['id', 'form', 'frame', 'slot'], field_parsers={})) + +corpus = Corpus(test=conllu2flair(testset, "frame")) +result = frame_model.evaluate(corpus.test, mini_batch_size=1, gold_label_type="frame") +print(result.detailed_results) + +# Slot model evaluation +slot_model = SequenceTagger.load('slot-model-prod/best-model.pt') + +with open('data/test_dialog_46.conllu', encoding='utf-8') as trainfile: + testset = list(parse_incr(trainfile, fields=['id', 'form', 'frame', 'slot'], field_parsers={'slot': nolabel2o})) + +corpus = Corpus(test=conllu2flair(testset, "slot")) +result = slot_model.evaluate(corpus.test, mini_batch_size=8, gold_label_type="slot") +print(result.detailed_results) + +# Custom evaluation +def __parse_acts(acts): + acts_split = acts.split('&') + remove_slot_regex = "[\(\[].*?[\)\]]" + return set(re.sub(remove_slot_regex, "", act) for act in acts_split) + +def __parse_predictions(predictions): + return set(prediction.split('/')[0] for prediction in predictions) + +total_acts = 0 +act_correct_predictions = 0 +slot_correct_predictions = 0 + +for file_name in os.listdir('data'): + if file_name.split('.')[-1] != 'tsv': + continue + + df = pd.read_csv(f'data/{file_name}', sep='\t', names=['kto', 'treść', 'akt']) + df = df[df.kto == 'user'] + all_data = np.array(df) + + for row in all_data: + sentence = row[1] + acts = __parse_acts(row[2]) + + predictions_raw = predict_multiple(frame_model, sentence.split(), 'frame') + predictions = __parse_predictions(predictions_raw) + + for act in acts: + total_acts += 1 + if act in predictions: + act_correct_predictions += 1 + print(f"Accuracy - predicting acts: {(act_correct_predictions / total_acts)*100} ({act_correct_predictions}/{total_acts})") \ No newline at end of file diff --git a/nlu_tests.py b/nlu_tests.py index a65da84..98b1c8e 100644 --- a/nlu_tests.py +++ b/nlu_tests.py @@ -1,30 +1,30 @@ -from flair.models import SequenceTagger -from nlu_utils import predict_single, predict_multiple, predict_and_annotate - -# Exploratory tests -frame_model = SequenceTagger.load('frame-model/best-model.pt') -tests = [ - 'chciałbym zamówić pizzę', - 'na godzinę 12', - 'prosiłbym o pizzę z pieczarkami', - 'to wszystko, jaka cena?', - 'ile kosztuje pizza', - 'do widzenia', - 'tak', - 'nie dziękuję', - 'dodatkowy ser', - 'pizzę barcelona bez cebuli', -] - -# print("=== Exploratory tests - frame model ===") -for test in tests: - print(f"Sentence: {test}") - print(f"Single prediction: {predict_single(frame_model, test.split(), 'frame')}") - print(f"Multiple predictions: {predict_multiple(frame_model, test.split(), 'frame')}") - print(f"Annotated sentence: {predict_and_annotate(frame_model, test.split(), 'frame')}") - -print("=== Exploratory tests - slot model ===") -slot_model = SequenceTagger.load('slot-model/final-model.pt') -for test in tests: - print(f"Sentence: {test}") +from flair.models import SequenceTagger +from nlu_utils import predict_single, predict_multiple, predict_and_annotate + +# Exploratory tests +frame_model = SequenceTagger.load('frame-model/best-model.pt') +tests = [ + 'chciałbym zamówić pizzę', + 'na godzinę 12', + 'prosiłbym o pizzę z pieczarkami', + 'to wszystko, jaka cena?', + 'ile kosztuje pizza', + 'do widzenia', + 'tak', + 'nie dziękuję', + 'dodatkowy ser', + 'pizzę barcelona bez cebuli', +] + +# print("=== Exploratory tests - frame model ===") +for test in tests: + print(f"Sentence: {test}") + print(f"Single prediction: {predict_single(frame_model, test.split(), 'frame')}") + print(f"Multiple predictions: {predict_multiple(frame_model, test.split(), 'frame')}") + print(f"Annotated sentence: {predict_and_annotate(frame_model, test.split(), 'frame')}") + +print("=== Exploratory tests - slot model ===") +slot_model = SequenceTagger.load('slot-model/final-model.pt') +for test in tests: + print(f"Sentence: {test}") print(f"Prediction: {predict_and_annotate(slot_model, test.split(), 'slot')}") \ No newline at end of file diff --git a/nlu_train.py b/nlu_train.py index 2018763..ba92a59 100644 --- a/nlu_train.py +++ b/nlu_train.py @@ -1,46 +1,42 @@ -from conllu import parse_incr -from flair.data import Corpus -from flair.embeddings import StackedEmbeddings -from flair.embeddings import WordEmbeddings -from flair.embeddings import CharacterEmbeddings -from flair.embeddings import FlairEmbeddings -from flair.models import SequenceTagger -from flair.trainers import ModelTrainer -from nlu_utils import conllu2flair, nolabel2o - -import random -import torch -random.seed(42) -torch.manual_seed(42) - -if torch.cuda.is_available(): - torch.cuda.manual_seed(0) - torch.cuda.manual_seed_all(0) - torch.backends.cudnn.enabled = False - torch.backends.cudnn.benchmark = False - torch.backends.cudnn.deterministic = True - - -def train_model(label_type, field_parsers = {}): - with open('data/train_dialog.conllu', encoding='utf-8') as trainfile: - trainset = list(parse_incr(trainfile, fields=['id', 'form', 'frame', 'slot'], field_parsers=field_parsers)) - - corpus = Corpus(train=conllu2flair(trainset, label_type), test=conllu2flair(trainset, label_type)) - label_dictionary = corpus.make_label_dictionary(label_type=label_type) - - embedding_types = [ - WordEmbeddings('pl'), - FlairEmbeddings('pl-forward'), - FlairEmbeddings('pl-backward'), - CharacterEmbeddings(), - ] - - embeddings = StackedEmbeddings(embeddings=embedding_types) - tagger = SequenceTagger(hidden_size=256, embeddings=embeddings, tag_dictionary=label_dictionary, tag_type=label_type, use_crf=True, tag_format="BIO") - - frame_trainer = ModelTrainer(tagger, corpus) - frame_trainer.train(f'{label_type}-model', learning_rate=0.1, mini_batch_size=32, max_epochs=75, train_with_dev=False) - -if __name__ == '__main__': - train_model("frame") - train_model('slot', field_parsers={'slot': nolabel2o}) \ No newline at end of file +from conllu import parse_incr +from flair.data import Corpus +from flair.embeddings import StackedEmbeddings +from flair.embeddings import WordEmbeddings +from flair.embeddings import CharacterEmbeddings +from flair.embeddings import FlairEmbeddings +from flair.models import SequenceTagger +from flair.trainers import ModelTrainer +from nlu_utils import conllu2flair, nolabel2o + +import torch +if torch.cuda.is_available(): + torch.backends.cudnn.enabled = False + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + +def train_model(label_type, field_parsers = {}): + with open('data/train_dialog.conllu', encoding='utf-8') as f: + trainset = list(parse_incr(f, fields=['id', 'form', 'frame', 'slot'], field_parsers=field_parsers)) + with open('data/test_dialog_46.conllu', encoding='utf-8') as f: + testset = list(parse_incr(f, fields=['id', 'form', 'frame', 'slot'], field_parsers=field_parsers)) + + breakpoint() + corpus = Corpus(train=conllu2flair(trainset, label_type), test=conllu2flair(testset, label_type)) + label_dictionary = corpus.make_label_dictionary(label_type=label_type) + + embedding_types = [ + WordEmbeddings('pl'), + FlairEmbeddings('pl-forward'), + FlairEmbeddings('pl-backward'), + CharacterEmbeddings(), + ] + + embeddings = StackedEmbeddings(embeddings=embedding_types) + tagger = SequenceTagger(hidden_size=256, embeddings=embeddings, tag_dictionary=label_dictionary, tag_type=label_type, use_crf=True, tag_format="BIO") + + frame_trainer = ModelTrainer(tagger, corpus) + frame_trainer.train(f'{label_type}-model', learning_rate=0.1, mini_batch_size=16, max_epochs=75, train_with_dev=False) + +if __name__ == '__main__': + train_model("frame") + # train_model('slot', field_parsers={'slot': nolabel2o}) \ No newline at end of file diff --git a/nlu_utils.py b/nlu_utils.py index ae5e51b..b8166a5 100644 --- a/nlu_utils.py +++ b/nlu_utils.py @@ -1,100 +1,101 @@ -from flair.data import Sentence -from flair.datasets import FlairDatapointDataset - -def nolabel2o(line, i): - return 'O' if line[i] == 'NoLabel' else line[i] - -def conllu2flair(sentences, label=None): - if label == "frame": - return conllu2flair_frame(sentences, label) - else: - return conllu2flair_slot(sentences, label) - -def conllu2flair_frame(sentences, label=None): - fsentences = [] - for sentence in sentences: - tokens = [token["form"] for token in sentence] - fsentence = Sentence(' '.join(tokens), use_tokenizer=False) - - for i in range(len(fsentence)): - fsentence[i:i+1].add_label(label, sentence[i][label]) - - fsentences.append(fsentence) - - return FlairDatapointDataset(fsentences) - -def conllu2flair_slot(sentences, label=None): - fsentences = [] - - for sentence in sentences: - fsentence = Sentence(' '.join(token['form'] for token in sentence), use_tokenizer=False) - start_idx = None - end_idx = None - tag = None - - if label: - for idx, (token, ftoken) in enumerate(zip(sentence, fsentence)): - if token[label].startswith('B-'): - start_idx = idx - end_idx = idx - tag = token[label][2:] - elif token[label].startswith('I-'): - end_idx = idx - elif token[label] == 'O': - if start_idx is not None: - fsentence[start_idx:end_idx+1].add_label(label, tag) - start_idx = None - end_idx = None - tag = None - - if start_idx is not None: - fsentence[start_idx:end_idx+1].add_label(label, tag) - - fsentences.append(fsentence) - return FlairDatapointDataset(fsentences) - -def __predict(model, csentence): - fsentence = conllu2flair([csentence])[0] - model.predict(fsentence) - return fsentence - -def __csentence(sentence, label_type): - if label_type == "frame": - return [{'form': word } for word in sentence] - else: - return [{'form': word, 'slot': 'O'} for word in sentence] - -def predict_single(model, sentence, label_type): - csentence = __csentence(sentence, label_type) - fsentence = __predict(model, csentence) - intent = {} - - for span in fsentence.get_spans(label_type): - tag = span.get_label(label_type).value - if tag in intent: - intent[tag] += 1 - else: - intent[tag] = 1 - - return max(intent, key=intent.get) - -def predict_multiple(model, sentence, label_type): - csentence = __csentence(sentence, label_type) - fsentence = __predict(model, csentence) - - return set(span.get_label(label_type).value for span in fsentence.get_spans(label_type)) - -def predict_and_annotate(model, sentence, label_type): - csentence = __csentence(sentence, label_type) - fsentence = __predict(model, csentence) - - for span in fsentence.get_spans(label_type): - tag = span.get_label(label_type).value - if label_type == "frame": - csentence[span.tokens[0].idx-1]['frame'] = tag - else: - csentence[span.tokens[0].idx - 1]['slot'] = f'B-{tag}' - for token in span.tokens[1:]: - csentence[token.idx - 1]['slot'] = f'I-{tag}' - +from flair.data import Sentence +from flair.datasets import FlairDatapointDataset + +def nolabel2o(line, i): + return 'O' if line[i] == 'NoLabel' else line[i] + +def conllu2flair(sentences, label=None): + if label == "frame": + return conllu2flair_frame(sentences, label) + else: + return conllu2flair_slot(sentences, label) + +def conllu2flair_frame(sentences, label=None): + fsentences = [] + for sentence in sentences: + tokens = [token["form"] for token in sentence] + fsentence = Sentence(' '.join(tokens), use_tokenizer=False) + + for i in range(len(fsentence)): + fsentence[i:i+1].add_label(label, sentence[i][label]) + + fsentences.append(fsentence) + + return FlairDatapointDataset(fsentences) + +def conllu2flair_slot(sentences, label=None): + fsentences = [] + for sentence in sentences: + fsentence = Sentence(' '.join(token['form'] for token in sentence), use_tokenizer=False) + start_idx = None + end_idx = None + tag = None + + if label: + for idx, (token, ftoken) in enumerate(zip(sentence, fsentence)): + if token[label].startswith('B-'): + if start_idx is not None: + fsentence[start_idx:end_idx+1].add_label(label, tag) + start_idx = idx + end_idx = idx + tag = token[label][2:] + elif token[label].startswith('I-'): + end_idx = idx + elif token[label] == 'O': + if start_idx is not None: + fsentence[start_idx:end_idx+1].add_label(label, tag) + start_idx = None + end_idx = None + tag = None + + if start_idx is not None: + fsentence[start_idx:end_idx+1].add_label(label, tag) + + fsentences.append(fsentence) + return FlairDatapointDataset(fsentences) + +def __predict(model, csentence): + fsentence = conllu2flair([csentence])[0] + model.predict(fsentence) + return fsentence + +def __csentence(sentence, label_type): + if label_type == "frame": + return [{'form': word } for word in sentence] + else: + return [{'form': word, 'slot': 'O'} for word in sentence] + +def predict_single(model, sentence, label_type): + csentence = __csentence(sentence, label_type) + fsentence = __predict(model, csentence) + intent = {} + + for span in fsentence.get_spans(label_type): + tag = span.get_label(label_type).value + if tag in intent: + intent[tag] += 1 + else: + intent[tag] = 1 + + return max(intent, key=intent.get) + +def predict_multiple(model, sentence, label_type): + csentence = __csentence(sentence, label_type) + fsentence = __predict(model, csentence) + + return set(span.get_label(label_type).value for span in fsentence.get_spans(label_type)) + +def predict_and_annotate(model, sentence, label_type): + csentence = __csentence(sentence, label_type) + fsentence = __predict(model, csentence) + + for span in fsentence.get_spans(label_type): + tag = span.get_label(label_type).value + if label_type == "frame": + csentence[span.tokens[0].idx-1]['frame'] = tag + else: + csentence[span.tokens[0].idx - 1]['slot'] = f'B-{tag}' + for token in span.tokens[1:]: + csentence[token.idx - 1]['slot'] = f'I-{tag}' + return csentence \ No newline at end of file