diff --git a/.gitignore b/.gitignore
index 7ded952..374c3c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -213,4 +213,6 @@ fabric.properties
.idea
-slot-model
\ No newline at end of file
+slot-model
+
+ConvLab-2
\ No newline at end of file
diff --git a/README.md b/README.md
index acbe0ae..2ec0201 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-## Zadanie 7
+## Zadanie 7/8 NLU
- rozwiązanie zadania znajduje się w pliku **lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb**, ostatnia komórka zawiera skrypt ewaluujący model metrykami precision, recall i f1
@@ -10,4 +10,14 @@
- plik **src/dialogue_system.py** będzie łączył wszystkie moduły systemu dialogowego, narazie wykorzystuje tylko tagger NLU
-- aby porozmawiać z systemem należy uruchomić wszystkie komórki pliku **lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb**, w celu anuczenia modelu, po ich wykonaniu należy uruchomić pythonowy skrypt **src/dialogue_system.py**
+- aby porozmawiać z systemem należy uruchomić wszystkie komórki pliku **lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb**, w celu nauczenia modelu, po ich wykonaniu należy uruchomić pythonowy skrypt **src/dialogue_system.py**
+
+---
+
+## Zadanie 9/10 DST i DP
+
+- implementacja regułowego modułu DST: **src/components DST.py**
+
+- implementacja regułowego DP, tylko happy path: **src/components DP.py**
+
+- wykorzystanie w pliku **src/dialogue_system.py**
diff --git a/lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb b/lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb
index 068fd49..cb10ad7 100644
--- a/lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb
+++ b/lab/08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb
@@ -1,679 +1,682 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
- "
\n",
- "
Systemy Dialogowe
\n",
- " 8. Parsing semantyczny z wykorzystaniem technik uczenia maszynowego [laboratoria]
\n",
- " Marek Kubis (2021)
\n",
- "\n",
- "\n",
- "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Parsing semantyczny z wykorzystaniem technik uczenia maszynowego\n",
- "================================================================\n",
- "\n",
- "Wprowadzenie\n",
- "------------\n",
- "Problem wykrywania slotów i ich wartości w wypowiedziach użytkownika można sformułować jako zadanie\n",
- "polegające na przewidywaniu dla poszczególnych słów etykiet wskazujących na to czy i do jakiego\n",
- "slotu dane słowo należy.\n",
- "\n",
- "> chciałbym zarezerwować stolik na jutro**/day** na godzinę dwunastą**/hour** czterdzieści**/hour** pięć**/hour** na pięć**/size** osób\n",
- "\n",
- "Granice slotów oznacza się korzystając z wybranego schematu etykietowania.\n",
- "\n",
- "### Schemat IOB\n",
- "\n",
- "| Prefix | Znaczenie |\n",
- "|:------:|:---------------------------|\n",
- "| I | wnętrze slotu (inside) |\n",
- "| O | poza slotem (outside) |\n",
- "| B | początek slotu (beginning) |\n",
- "\n",
- "> chciałbym zarezerwować stolik na jutro**/B-day** na godzinę dwunastą**/B-hour** czterdzieści**/I-hour** pięć**/I-hour** na pięć**/B-size** osób\n",
- "\n",
- "### Schemat IOBES\n",
- "\n",
- "| Prefix | Znaczenie |\n",
- "|:------:|:---------------------------|\n",
- "| I | wnętrze slotu (inside) |\n",
- "| O | poza slotem (outside) |\n",
- "| B | początek slotu (beginning) |\n",
- "| E | koniec slotu (ending) |\n",
- "| S | pojedyncze słowo (single) |\n",
- "\n",
- "> chciałbym zarezerwować stolik na jutro**/S-day** na godzinę dwunastą**/B-hour** czterdzieści**/I-hour** pięć**/E-hour** na pięć**/S-size** osób\n",
- "\n",
- "Jeżeli dla tak sformułowanego zadania przygotujemy zbiór danych\n",
- "złożony z wypowiedzi użytkownika z oznaczonymi slotami (tzw. *zbiór uczący*),\n",
- "to możemy zastosować techniki (nadzorowanego) uczenia maszynowego w celu zbudowania modelu\n",
- "annotującego wypowiedzi użytkownika etykietami slotów.\n",
- "\n",
- "Do zbudowania takiego modelu można wykorzystać między innymi:\n",
- "\n",
- " 1. warunkowe pola losowe (Lafferty i in.; 2001),\n",
- "\n",
- " 2. rekurencyjne sieci neuronowe, np. sieci LSTM (Hochreiter i Schmidhuber; 1997),\n",
- "\n",
- " 3. transformery (Vaswani i in., 2017).\n",
- "\n",
- "Przykład\n",
- "--------\n",
- "Skorzystamy ze zbioru danych przygotowanego przez Schustera (2019)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Zbiór ten gromadzi wypowiedzi w trzech językach opisane slotami dla dwunastu ram należących do trzech dziedzin `Alarm`, `Reminder` oraz `Weather`. Dane wczytamy korzystając z biblioteki [conllu](https://pypi.org/project/conllu/)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "# text: halo\t\t\t\n",
- "\n",
- "# intent: hello\t\t\t\n",
- "\n",
- "# slots: \t\t\t\n",
- "\n",
- "1\thalo\thello\tNoLabel\n",
- "\n",
- "\t\t\t\n",
- "\n",
- "# text: chaciałbym pójść na premierę filmu jakie premiery są w tym tygodniu\t\t\t\n",
- "\n",
- "# intent: reqmore\t\t\t\n",
- "\n",
- "# slots: \t\t\t\n",
- "\n",
- "1\tchaciałbym\treqmore\tNoLabel\n",
- "\n",
- "2\tpójść\treqmore\tNoLabel\n",
- "\n",
- "3\tna\treqmore\tNoLabel\n",
- "\n",
- "4\tpremierę\treqmore\tNoLabel\n",
- "\n",
- "5\tfilmu\treqmore\tNoLabel\n",
- "\n",
- "6\tjakie\treqmore\tB-goal\n",
- "\n",
- "7\tpremiery\treqmore\tI-goal\n",
- "\n"
- ]
- }
- ],
- "source": [
- "from conllu import parse_incr\n",
- "fields = ['id', 'form', 'frame', 'slot']\n",
- "\n",
- "def nolabel2o(line, i):\n",
- " return 'O' if line[i] == 'NoLabel' else line[i]\n",
- "# pathTrain = '../tasks/zad8/en/train-en.conllu'\n",
- "# pathTest = '../tasks/zad8/en/test-en.conllu'\n",
- "\n",
- "pathTrain = '../tasks/zad8/pl/train.conllu'\n",
- "pathTest = '../tasks/zad8/pl/test.conllu'\n",
- "\n",
- "with open(pathTrain, encoding=\"UTF-8\") as trainfile:\n",
- " i=0\n",
- " for line in trainfile:\n",
- " print(line)\n",
- " i+=1\n",
- " if i==15: break \n",
- " trainset = list(parse_incr(trainfile, fields=fields, field_parsers={'slot': nolabel2o}))\n",
- "with open(pathTest, encoding=\"UTF-8\") as testfile:\n",
- " testset = list(parse_incr(testfile, fields=fields, field_parsers={'slot': nolabel2o}))\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Zobaczmy kilka przykładowych wypowiedzi z tego zbioru."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "1 | wybieram | inform | O |
\n",
- "2 | batmana | inform | B-title |
\n",
- "\n",
- "
"
- ],
- "text/plain": [
- "'\\n\\n1 | wybieram | inform | O |
\\n2 | batmana | inform | B-title |
\\n\\n
'"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from tabulate import tabulate\n",
- "tabulate(trainset[1], tablefmt='html')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "1 | chcę | inform | O |
\n",
- "2 | zarezerwować | inform | B-goal |
\n",
- "3 | bilety | inform | O |
\n",
- "\n",
- "
"
- ],
- "text/plain": [
- "'\\n\\n1 | chcę | inform | O |
\\n2 | zarezerwować | inform | B-goal |
\\n3 | bilety | inform | O |
\\n\\n
'"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tabulate(trainset[16], tablefmt='html')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "1 | chciałbym | inform | O |
\n",
- "2 | anulować | inform | O |
\n",
- "3 | rezerwację | inform | O |
\n",
- "4 | biletu | inform | O |
\n",
- "\n",
- "
"
- ],
- "text/plain": [
- "'\\n\\n1 | chciałbym | inform | O |
\\n2 | anulować | inform | O |
\\n3 | rezerwację | inform | O |
\\n4 | biletu | inform | O |
\\n\\n
'"
- ]
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tabulate(trainset[20], tablefmt='html')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Budując model skorzystamy z architektury opartej o rekurencyjne sieci neuronowe\n",
- "zaimplementowanej w bibliotece [flair](https://github.com/flairNLP/flair) (Akbik i in. 2018)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [],
- "source": [
- "from flair.data import Corpus, Sentence, Token\n",
- "from flair.datasets import SentenceDataset\n",
- "from flair.embeddings import StackedEmbeddings\n",
- "from flair.embeddings import WordEmbeddings\n",
- "from flair.embeddings import CharacterEmbeddings\n",
- "from flair.embeddings import FlairEmbeddings\n",
- "from flair.models import SequenceTagger\n",
- "from flair.trainers import ModelTrainer\n",
- "from flair.datasets import DataLoader\n",
- "\n",
- "# determinizacja obliczeń\n",
- "import random\n",
- "import torch\n",
- "random.seed(42)\n",
- "torch.manual_seed(42)\n",
- "\n",
- "if torch.cuda.is_available():\n",
- " torch.cuda.manual_seed(0)\n",
- " torch.cuda.manual_seed_all(0)\n",
- " torch.backends.cudnn.enabled = False\n",
- " torch.backends.cudnn.benchmark = False\n",
- " torch.backends.cudnn.deterministic = True"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dane skonwertujemy do formatu wykorzystywanego przez `flair`, korzystając z następującej funkcji."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Corpus: 345 train + 38 dev + 32 test sentences\n",
- "Dictionary with 20 tags: , O, B-interval, I-interval, B-title, B-date, I-date, B-time, B-quantity, B-area, I-area, B-goal, I-goal, I-title, I-time, I-quantity, B-seats, I-seats, , \n"
- ]
- }
- ],
- "source": [
- "def conllu2flair(sentences, label=None):\n",
- " fsentences = []\n",
- "\n",
- " for sentence in sentences:\n",
- " fsentence = Sentence()\n",
- "\n",
- " for token in sentence:\n",
- " ftoken = Token(token['form'])\n",
- "\n",
- " if label:\n",
- " ftoken.add_tag(label, token[label])\n",
- "\n",
- " fsentence.add_token(ftoken)\n",
- "\n",
- " fsentences.append(fsentence)\n",
- "\n",
- " return SentenceDataset(fsentences)\n",
- "\n",
- "corpus = Corpus(train=conllu2flair(trainset, 'slot'), test=conllu2flair(testset, 'slot'))\n",
- "print(corpus)\n",
- "tag_dictionary = corpus.make_tag_dictionary(tag_type='slot')\n",
- "print(tag_dictionary)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Nasz model będzie wykorzystywał wektorowe reprezentacje słów (zob. [Word Embeddings](https://github.com/flairNLP/flair/blob/master/resources/docs/TUTORIAL_3_WORD_EMBEDDING.md))."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [],
- "source": [
- "embedding_types = [\n",
- " WordEmbeddings('pl'),\n",
- " FlairEmbeddings('polish-forward'),\n",
- " FlairEmbeddings('polish-backward'),\n",
- " CharacterEmbeddings(),\n",
- "]\n",
- "\n",
- "embeddings = StackedEmbeddings(embeddings=embedding_types)\n",
- "tagger = SequenceTagger(hidden_size=256, embeddings=embeddings,\n",
- " tag_dictionary=tag_dictionary,\n",
- " tag_type='slot', use_crf=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Zobaczmy jak wygląda architektura sieci neuronowej, która będzie odpowiedzialna za przewidywanie\n",
- "slotów w wypowiedziach."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "SequenceTagger(\n",
- " (embeddings): StackedEmbeddings(\n",
- " (list_embedding_0): WordEmbeddings('pl')\n",
- " (list_embedding_1): FlairEmbeddings(\n",
- " (lm): LanguageModel(\n",
- " (drop): Dropout(p=0.25, inplace=False)\n",
- " (encoder): Embedding(1602, 100)\n",
- " (rnn): LSTM(100, 2048)\n",
- " (decoder): Linear(in_features=2048, out_features=1602, bias=True)\n",
- " )\n",
- " )\n",
- " (list_embedding_2): FlairEmbeddings(\n",
- " (lm): LanguageModel(\n",
- " (drop): Dropout(p=0.25, inplace=False)\n",
- " (encoder): Embedding(1602, 100)\n",
- " (rnn): LSTM(100, 2048)\n",
- " (decoder): Linear(in_features=2048, out_features=1602, bias=True)\n",
- " )\n",
- " )\n",
- " (list_embedding_3): CharacterEmbeddings(\n",
- " (char_embedding): Embedding(275, 25)\n",
- " (char_rnn): LSTM(25, 25, bidirectional=True)\n",
- " )\n",
- " )\n",
- " (word_dropout): WordDropout(p=0.05)\n",
- " (locked_dropout): LockedDropout(p=0.5)\n",
- " (embedding2nn): Linear(in_features=4446, out_features=4446, bias=True)\n",
- " (rnn): LSTM(4446, 256, batch_first=True, bidirectional=True)\n",
- " (linear): Linear(in_features=512, out_features=20, bias=True)\n",
- " (beta): 1.0\n",
- " (weights): None\n",
- " (weight_tensor) None\n",
- ")\n"
- ]
- }
- ],
- "source": [
- "print(tagger)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Wykonamy dziesięć iteracji (epok) uczenia a wynikowy model zapiszemy w katalogu `slot-model`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [],
- "source": [
- "modelPath = 'slot-model/final-model.pt'\n",
- "\n",
- "from os.path import exists\n",
- "\n",
- "fileExists = exists(modelPath)\n",
- "\n",
- "if(not fileExists):\n",
- " trainer = ModelTrainer(tagger, corpus)\n",
- " trainer.train('slot-model',\n",
- " learning_rate=0.1,\n",
- " mini_batch_size=32,\n",
- " max_epochs=10,\n",
- " train_with_dev=False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jakość wyuczonego modelu możemy ocenić, korzystając z zaraportowanych powyżej metryk, tj.:\n",
- "\n",
- " - *tp (true positives)*\n",
- "\n",
- " > liczba słów oznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
- "\n",
- " - *fp (false positives)*\n",
- "\n",
- " > liczba słów nieoznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
- "\n",
- " - *fn (false negatives)*\n",
- "\n",
- " > liczba słów oznaczonych w zbiorze testowym etykietą $e$, którym model nie nadał etykiety $e$\n",
- "\n",
- " - *precision*\n",
- "\n",
- " > $$\\frac{tp}{tp + fp}$$\n",
- "\n",
- " - *recall*\n",
- "\n",
- " > $$\\frac{tp}{tp + fn}$$\n",
- "\n",
- " - $F_1$\n",
- "\n",
- " > $$\\frac{2 \\cdot precision \\cdot recall}{precision + recall}$$\n",
- "\n",
- " - *micro* $F_1$\n",
- "\n",
- " > $F_1$ w którym $tp$, $fp$ i $fn$ są liczone łącznie dla wszystkich etykiet, tj. $tp = \\sum_{e}{{tp}_e}$, $fn = \\sum_{e}{{fn}_e}$, $fp = \\sum_{e}{{fp}_e}$\n",
- "\n",
- " - *macro* $F_1$\n",
- "\n",
- " > średnia arytmetyczna z $F_1$ obliczonych dla poszczególnych etykiet z osobna.\n",
- "\n",
- "Wyuczony model możemy wczytać z pliku korzystając z metody `load`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2022-05-05 17:34:34,767 loading file slot-model/final-model.pt\n"
- ]
- }
- ],
- "source": [
- "model = SequenceTagger.load(modelPath)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Wczytany model możemy wykorzystać do przewidywania slotów w wypowiedziach użytkownika, korzystając\n",
- "z przedstawionej poniżej funkcji `predict`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[('kiedy', 'O'), ('gracie', 'O'), ('film', 'O'), ('zorro', 'B-title')]"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def predict(model, sentence):\n",
- " csentence = [{'form': word} for word in sentence]\n",
- " fsentence = conllu2flair([csentence])[0]\n",
- " model.predict(fsentence)\n",
- " return [(token, ftoken.get_tag('slot').value) for token, ftoken in zip(sentence, fsentence)]\n",
- "\n",
- "predict(model, 'kiedy gracie film zorro'.split())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jak pokazuje przykład poniżej model wyuczony tylko na 100 przykładach popełnia w dosyć prostej\n",
- "wypowiedzi błąd etykietując słowo `alarm` tagiem `B-weather/noun`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "kiedy | O |
\n",
- "gracie | O |
\n",
- "film | O |
\n",
- "zorro | B-title |
\n",
- "\n",
- "
"
- ],
- "text/plain": [
- "'\\n\\nkiedy | O |
\\ngracie | O |
\\nfilm | O |
\\nzorro | B-title |
\\n\\n
'"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tabulate(predict(model, 'kiedy gracie film zorro'.split()), tablefmt='html')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 82,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "stats: \n",
- "precision: 0.8076923076923077\n",
- "recall: 0.4117647058823529\n",
- "f1: 0.5454545454545454\n"
- ]
- }
- ],
- "source": [
- "# evaluation\n",
- "\n",
- "def precision(tpScore, fpScore):\n",
- " return float(tpScore) / (tpScore + fpScore)\n",
- "\n",
- "def recall(tpScore, fnScore):\n",
- " return float(tpScore) / (tpScore + fnScore)\n",
- "\n",
- "def f1(precision, recall):\n",
- " return 2 * precision * recall/(precision + recall)\n",
- "\n",
- "def eval():\n",
- " tp = 0\n",
- " fp = 0\n",
- " fn = 0\n",
- " sentences = [sentence for sentence in testset]\n",
- " for sentence in sentences:\n",
- " # get sentence as terms list\n",
- " termsList = [w[\"form\"] for w in sentence]\n",
- " # predict tags\n",
- " predTags = [tag[1] for tag in predict(model, termsList)]\n",
- " \n",
- " expTags = [token[\"slot\"] for token in sentence]\n",
- " for i in range(len(predTags)):\n",
- " if (expTags[i] == \"O\" and expTags[i] != predTags[i]):\n",
- " fp += 1\n",
- " elif ((expTags[i] != \"O\") & (predTags[i] == \"O\")):\n",
- " fn += 1\n",
- " elif ((expTags[i] != \"O\") & (predTags[i] == expTags[i])):\n",
- " tp += 1\n",
- "\n",
- " precisionScore = precision(tp, fp)\n",
- " recallScore = recall(tp, fn)\n",
- " f1Score = f1(precisionScore, recallScore)\n",
- " print(\"stats: \")\n",
- " print(\"precision: \", precisionScore)\n",
- " print(\"recall: \", recallScore)\n",
- " print(\"f1: \", f1Score)\n",
- "\n",
- "eval()\n",
- "\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Literatura\n",
- "----------\n",
- " 1. Sebastian Schuster, Sonal Gupta, Rushin Shah, Mike Lewis, Cross-lingual Transfer Learning for Multilingual Task Oriented Dialog. NAACL-HLT (1) 2019, pp. 3795-3805\n",
- " 2. John D. Lafferty, Andrew McCallum, and Fernando C. N. Pereira. 2001. Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data. In Proceedings of the Eighteenth International Conference on Machine Learning (ICML '01). Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 282–289, https://repository.upenn.edu/cgi/viewcontent.cgi?article=1162&context=cis_papers\n",
- " 3. Sepp Hochreiter and Jürgen Schmidhuber. 1997. Long Short-Term Memory. Neural Comput. 9, 8 (November 15, 1997), 1735–1780, https://doi.org/10.1162/neco.1997.9.8.1735\n",
- " 4. Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin, Attention is All you Need, NIPS 2017, pp. 5998-6008, https://arxiv.org/abs/1706.03762\n",
- " 5. Alan Akbik, Duncan Blythe, Roland Vollgraf, Contextual String Embeddings for Sequence Labeling, Proceedings of the 27th International Conference on Computational Linguistics, pp. 1638–1649, https://www.aclweb.org/anthology/C18-1139.pdf\n"
- ]
- }
- ],
- "metadata": {
- "author": "Marek Kubis",
- "email": "mkubis@amu.edu.pl",
- "interpreter": {
- "hash": "2be5faf79681da6f2a61fdfdd5405d65d042280f7fba6178067603e3a2925119"
- },
- "jupytext": {
- "cell_metadata_filter": "-all",
- "main_language": "python",
- "notebook_metadata_filter": "-all"
- },
- "kernelspec": {
- "display_name": "Python 3.10.4 64-bit",
- "language": "python",
- "name": "python3"
- },
- "lang": "pl",
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.3"
- },
- "subtitle": "8.Parsing semantyczny z wykorzystaniem technik uczenia maszynowego[laboratoria]",
- "title": "Systemy Dialogowe",
- "year": "2021"
- },
- "nbformat": 4,
- "nbformat_minor": 4
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
+ "\n",
+ "
Systemy Dialogowe
\n",
+ " 8. Parsing semantyczny z wykorzystaniem technik uczenia maszynowego [laboratoria]
\n",
+ " Marek Kubis (2021)
\n",
+ "\n",
+ "\n",
+ "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Parsing semantyczny z wykorzystaniem technik uczenia maszynowego\n",
+ "================================================================\n",
+ "\n",
+ "Wprowadzenie\n",
+ "------------\n",
+ "Problem wykrywania slotów i ich wartości w wypowiedziach użytkownika można sformułować jako zadanie\n",
+ "polegające na przewidywaniu dla poszczególnych słów etykiet wskazujących na to czy i do jakiego\n",
+ "slotu dane słowo należy.\n",
+ "\n",
+ "> chciałbym zarezerwować stolik na jutro**/day** na godzinę dwunastą**/hour** czterdzieści**/hour** pięć**/hour** na pięć**/size** osób\n",
+ "\n",
+ "Granice slotów oznacza się korzystając z wybranego schematu etykietowania.\n",
+ "\n",
+ "### Schemat IOB\n",
+ "\n",
+ "| Prefix | Znaczenie |\n",
+ "|:------:|:---------------------------|\n",
+ "| I | wnętrze slotu (inside) |\n",
+ "| O | poza slotem (outside) |\n",
+ "| B | początek slotu (beginning) |\n",
+ "\n",
+ "> chciałbym zarezerwować stolik na jutro**/B-day** na godzinę dwunastą**/B-hour** czterdzieści**/I-hour** pięć**/I-hour** na pięć**/B-size** osób\n",
+ "\n",
+ "### Schemat IOBES\n",
+ "\n",
+ "| Prefix | Znaczenie |\n",
+ "|:------:|:---------------------------|\n",
+ "| I | wnętrze slotu (inside) |\n",
+ "| O | poza slotem (outside) |\n",
+ "| B | początek slotu (beginning) |\n",
+ "| E | koniec slotu (ending) |\n",
+ "| S | pojedyncze słowo (single) |\n",
+ "\n",
+ "> chciałbym zarezerwować stolik na jutro**/S-day** na godzinę dwunastą**/B-hour** czterdzieści**/I-hour** pięć**/E-hour** na pięć**/S-size** osób\n",
+ "\n",
+ "Jeżeli dla tak sformułowanego zadania przygotujemy zbiór danych\n",
+ "złożony z wypowiedzi użytkownika z oznaczonymi slotami (tzw. *zbiór uczący*),\n",
+ "to możemy zastosować techniki (nadzorowanego) uczenia maszynowego w celu zbudowania modelu\n",
+ "annotującego wypowiedzi użytkownika etykietami slotów.\n",
+ "\n",
+ "Do zbudowania takiego modelu można wykorzystać między innymi:\n",
+ "\n",
+ " 1. warunkowe pola losowe (Lafferty i in.; 2001),\n",
+ "\n",
+ " 2. rekurencyjne sieci neuronowe, np. sieci LSTM (Hochreiter i Schmidhuber; 1997),\n",
+ "\n",
+ " 3. transformery (Vaswani i in., 2017).\n",
+ "\n",
+ "Przykład\n",
+ "--------\n",
+ "Skorzystamy ze zbioru danych przygotowanego przez Schustera (2019)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zbiór ten gromadzi wypowiedzi w trzech językach opisane slotami dla dwunastu ram należących do trzech dziedzin `Alarm`, `Reminder` oraz `Weather`. Dane wczytamy korzystając z biblioteki [conllu](https://pypi.org/project/conllu/)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "# text: halo\t\t\t\n",
+ "\n",
+ "# intent: hello\t\t\t\n",
+ "\n",
+ "# slots: \t\t\t\n",
+ "\n",
+ "1\thalo\thello\tNoLabel\n",
+ "\n",
+ "\t\t\t\n",
+ "\n",
+ "# text: chaciałbym pójść na premierę filmu jakie premiery są w tym tygodniu\t\t\t\n",
+ "\n",
+ "# intent: reqmore\t\t\t\n",
+ "\n",
+ "# slots: \t\t\t\n",
+ "\n",
+ "1\tchaciałbym\treqmore\tNoLabel\n",
+ "\n",
+ "2\tpójść\treqmore\tNoLabel\n",
+ "\n",
+ "3\tna\treqmore\tNoLabel\n",
+ "\n",
+ "4\tpremierę\treqmore\tNoLabel\n",
+ "\n",
+ "5\tfilmu\treqmore\tNoLabel\n",
+ "\n",
+ "6\tjakie\treqmore\tB-goal\n",
+ "\n",
+ "7\tpremiery\treqmore\tI-goal\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "from conllu import parse_incr\n",
+ "fields = ['id', 'form', 'frame', 'slot']\n",
+ "\n",
+ "def nolabel2o(line, i):\n",
+ " return 'O' if line[i] == 'NoLabel' else line[i]\n",
+ "# pathTrain = '../tasks/zad8/en/train-en.conllu'\n",
+ "# pathTest = '../tasks/zad8/en/test-en.conllu'\n",
+ "\n",
+ "pathTrain = '../tasks/zad8/pl/train.conllu'\n",
+ "pathTest = '../tasks/zad8/pl/test.conllu'\n",
+ "\n",
+ "with open(pathTrain, encoding=\"UTF-8\") as trainfile:\n",
+ " i=0\n",
+ " for line in trainfile:\n",
+ " print(line)\n",
+ " i+=1\n",
+ " if i==15: break \n",
+ " trainset = list(parse_incr(trainfile, fields=fields, field_parsers={'slot': nolabel2o}))\n",
+ "with open(pathTest, encoding=\"UTF-8\") as testfile:\n",
+ " testset = list(parse_incr(testfile, fields=fields, field_parsers={'slot': nolabel2o}))\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zobaczmy kilka przykładowych wypowiedzi z tego zbioru."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "1 | wybieram | inform | O |
\n",
+ "2 | batmana | inform | B-title |
\n",
+ "\n",
+ "
"
+ ],
+ "text/plain": [
+ "'\\n\\n1 | wybieram | inform | O |
\\n2 | batmana | inform | B-title |
\\n\\n
'"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from tabulate import tabulate\n",
+ "tabulate(trainset[1], tablefmt='html')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "1 | chcę | inform | O |
\n",
+ "2 | zarezerwować | inform | B-goal |
\n",
+ "3 | bilety | inform | O |
\n",
+ "\n",
+ "
"
+ ],
+ "text/plain": [
+ "'\\n\\n1 | chcę | inform | O |
\\n2 | zarezerwować | inform | B-goal |
\\n3 | bilety | inform | O |
\\n\\n
'"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tabulate(trainset[16], tablefmt='html')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "1 | chciałbym | inform | O |
\n",
+ "2 | anulować | inform | O |
\n",
+ "3 | rezerwację | inform | O |
\n",
+ "4 | biletu | inform | O |
\n",
+ "\n",
+ "
"
+ ],
+ "text/plain": [
+ "'\\n\\n1 | chciałbym | inform | O |
\\n2 | anulować | inform | O |
\\n3 | rezerwację | inform | O |
\\n4 | biletu | inform | O |
\\n\\n
'"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tabulate(trainset[20], tablefmt='html')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Budując model skorzystamy z architektury opartej o rekurencyjne sieci neuronowe\n",
+ "zaimplementowanej w bibliotece [flair](https://github.com/flairNLP/flair) (Akbik i in. 2018)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from flair.data import Corpus, Sentence, Token\n",
+ "from flair.datasets import SentenceDataset\n",
+ "from flair.embeddings import StackedEmbeddings\n",
+ "from flair.embeddings import WordEmbeddings\n",
+ "from flair.embeddings import CharacterEmbeddings\n",
+ "from flair.embeddings import FlairEmbeddings\n",
+ "from flair.models import SequenceTagger\n",
+ "from flair.trainers import ModelTrainer\n",
+ "from flair.datasets import DataLoader\n",
+ "\n",
+ "# determinizacja obliczeń\n",
+ "import random\n",
+ "import torch\n",
+ "random.seed(42)\n",
+ "torch.manual_seed(42)\n",
+ "\n",
+ "if torch.cuda.is_available():\n",
+ " torch.cuda.manual_seed(0)\n",
+ " torch.cuda.manual_seed_all(0)\n",
+ " torch.backends.cudnn.enabled = False\n",
+ " torch.backends.cudnn.benchmark = False\n",
+ " torch.backends.cudnn.deterministic = True"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Dane skonwertujemy do formatu wykorzystywanego przez `flair`, korzystając z następującej funkcji."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Corpus: 346 train + 38 dev + 32 test sentences\n",
+ "Dictionary with 78 tags: , O, O/reqmore, B-interval/reqmore, I-interval/reqmore, O/inform, B-title/inform, B-date/inform, I-date/inform, B-time/inform, B-quantity/inform, B-area/inform, I-area/inform, B-goal/inform, O/bye, O/hello, O/reqmore inform, B-goal/reqmore inform, I-goal/reqmore inform, B-date/reqmore inform, B-interval/reqmore inform, O/null, O/help, B-goal/reqmore, I-goal/reqmore, B-title/reqmore, B-title/reqmore inform, I-title/reqmore inform, O/ack, O/reqalts\n"
+ ]
+ }
+ ],
+ "source": [
+ "def conllu2flair(sentences, label1=None, label2=None):\n",
+ " fsentences = []\n",
+ "\n",
+ " for sentence in sentences:\n",
+ " fsentence = Sentence()\n",
+ "\n",
+ " for token in sentence:\n",
+ " ftoken = Token(token['form'])\n",
+ "\n",
+ " if label1:\n",
+ " if label2:\n",
+ " ftoken.add_tag(label1, token[label1] + \"/\" + token[label2])\n",
+ " else:\n",
+ " ftoken.add_tag(label1, token[label1])\n",
+ " \n",
+ " fsentence.add_token(ftoken)\n",
+ "\n",
+ " fsentences.append(fsentence)\n",
+ "\n",
+ " return SentenceDataset(fsentences)\n",
+ "\n",
+ "corpus = Corpus(train=conllu2flair(trainset, 'slot', \"frame\"), test=conllu2flair(testset, 'slot', \"frame\"))\n",
+ "print(corpus)\n",
+ "tag_dictionary = corpus.make_tag_dictionary(tag_type='slot')\n",
+ "print(tag_dictionary)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Nasz model będzie wykorzystywał wektorowe reprezentacje słów (zob. [Word Embeddings](https://github.com/flairNLP/flair/blob/master/resources/docs/TUTORIAL_3_WORD_EMBEDDING.md))."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "embedding_types = [\n",
+ " WordEmbeddings('pl'),\n",
+ " FlairEmbeddings('polish-forward'),\n",
+ " FlairEmbeddings('polish-backward'),\n",
+ " CharacterEmbeddings(),\n",
+ "]\n",
+ "\n",
+ "embeddings = StackedEmbeddings(embeddings=embedding_types)\n",
+ "tagger = SequenceTagger(hidden_size=256, embeddings=embeddings,\n",
+ " tag_dictionary=tag_dictionary,\n",
+ " tag_type='slot', use_crf=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zobaczmy jak wygląda architektura sieci neuronowej, która będzie odpowiedzialna za przewidywanie\n",
+ "slotów w wypowiedziach."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "SequenceTagger(\n",
+ " (embeddings): StackedEmbeddings(\n",
+ " (list_embedding_0): WordEmbeddings('pl')\n",
+ " (list_embedding_1): FlairEmbeddings(\n",
+ " (lm): LanguageModel(\n",
+ " (drop): Dropout(p=0.25, inplace=False)\n",
+ " (encoder): Embedding(1602, 100)\n",
+ " (rnn): LSTM(100, 2048)\n",
+ " (decoder): Linear(in_features=2048, out_features=1602, bias=True)\n",
+ " )\n",
+ " )\n",
+ " (list_embedding_2): FlairEmbeddings(\n",
+ " (lm): LanguageModel(\n",
+ " (drop): Dropout(p=0.25, inplace=False)\n",
+ " (encoder): Embedding(1602, 100)\n",
+ " (rnn): LSTM(100, 2048)\n",
+ " (decoder): Linear(in_features=2048, out_features=1602, bias=True)\n",
+ " )\n",
+ " )\n",
+ " (list_embedding_3): CharacterEmbeddings(\n",
+ " (char_embedding): Embedding(275, 25)\n",
+ " (char_rnn): LSTM(25, 25, bidirectional=True)\n",
+ " )\n",
+ " )\n",
+ " (word_dropout): WordDropout(p=0.05)\n",
+ " (locked_dropout): LockedDropout(p=0.5)\n",
+ " (embedding2nn): Linear(in_features=4446, out_features=4446, bias=True)\n",
+ " (rnn): LSTM(4446, 256, batch_first=True, bidirectional=True)\n",
+ " (linear): Linear(in_features=512, out_features=78, bias=True)\n",
+ " (beta): 1.0\n",
+ " (weights): None\n",
+ " (weight_tensor) None\n",
+ ")\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(tagger)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wykonamy dziesięć iteracji (epok) uczenia a wynikowy model zapiszemy w katalogu `slot-model`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "modelPath = 'slot-model/final-model.pt'\n",
+ "\n",
+ "from os.path import exists\n",
+ "\n",
+ "fileExists = exists(modelPath)\n",
+ "\n",
+ "if(not fileExists):\n",
+ " trainer = ModelTrainer(tagger, corpus)\n",
+ " trainer.train('slot-model',\n",
+ " learning_rate=0.1,\n",
+ " mini_batch_size=32,\n",
+ " max_epochs=10,\n",
+ " train_with_dev=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jakość wyuczonego modelu możemy ocenić, korzystając z zaraportowanych powyżej metryk, tj.:\n",
+ "\n",
+ " - *tp (true positives)*\n",
+ "\n",
+ " > liczba słów oznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
+ "\n",
+ " - *fp (false positives)*\n",
+ "\n",
+ " > liczba słów nieoznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
+ "\n",
+ " - *fn (false negatives)*\n",
+ "\n",
+ " > liczba słów oznaczonych w zbiorze testowym etykietą $e$, którym model nie nadał etykiety $e$\n",
+ "\n",
+ " - *precision*\n",
+ "\n",
+ " > $$\\frac{tp}{tp + fp}$$\n",
+ "\n",
+ " - *recall*\n",
+ "\n",
+ " > $$\\frac{tp}{tp + fn}$$\n",
+ "\n",
+ " - $F_1$\n",
+ "\n",
+ " > $$\\frac{2 \\cdot precision \\cdot recall}{precision + recall}$$\n",
+ "\n",
+ " - *micro* $F_1$\n",
+ "\n",
+ " > $F_1$ w którym $tp$, $fp$ i $fn$ są liczone łącznie dla wszystkich etykiet, tj. $tp = \\sum_{e}{{tp}_e}$, $fn = \\sum_{e}{{fn}_e}$, $fp = \\sum_{e}{{fp}_e}$\n",
+ "\n",
+ " - *macro* $F_1$\n",
+ "\n",
+ " > średnia arytmetyczna z $F_1$ obliczonych dla poszczególnych etykiet z osobna.\n",
+ "\n",
+ "Wyuczony model możemy wczytać z pliku korzystając z metody `load`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2022-05-22 15:25:19,970 loading file slot-model/final-model.pt\n"
+ ]
+ }
+ ],
+ "source": [
+ "model = SequenceTagger.load(modelPath)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wczytany model możemy wykorzystać do przewidywania slotów w wypowiedziach użytkownika, korzystając\n",
+ "z przedstawionej poniżej funkcji `predict`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[('co', 'O/reqmore'), ('gracie', 'O/reqmore'), ('obecnie', 'O/reqmore')]"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def predict(model, sentence):\n",
+ " csentence = [{'form': word} for word in sentence]\n",
+ " fsentence = conllu2flair([csentence])[0]\n",
+ " model.predict(fsentence)\n",
+ " return [(token, ftoken.get_tag('slot').value) for token, ftoken in zip(sentence, fsentence)]\n",
+ "\n",
+ "predict(model, 'co gracie obecnie'.split())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jak pokazuje przykład poniżej model wyuczony tylko na 100 przykładach popełnia w dosyć prostej\n",
+ "wypowiedzi błąd etykietując słowo `alarm` tagiem `B-weather/noun`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "kiedy | O/reqmore |
\n",
+ "gracie | O/reqmore |
\n",
+ "film | O/reqmore |
\n",
+ "zorro | O/reqmore |
\n",
+ "\n",
+ "
"
+ ],
+ "text/plain": [
+ "'\\n\\nkiedy | O/reqmore |
\\ngracie | O/reqmore |
\\nfilm | O/reqmore |
\\nzorro | O/reqmore |
\\n\\n
'"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tabulate(predict(model, 'kiedy gracie film zorro'.split()), tablefmt='html')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'testset' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb Cell 25'\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 37\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39mrecall: \u001b[39m\u001b[39m\"\u001b[39m, recallScore)\n\u001b[0;32m 38\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m\"\u001b[39m\u001b[39mf1: \u001b[39m\u001b[39m\"\u001b[39m, f1Score)\n\u001b[1;32m---> 40\u001b[0m \u001b[39meval\u001b[39;49m()\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\08-parsing-semantyczny-uczenie(zmodyfikowany).ipynb Cell 25'\u001b[0m in \u001b[0;36meval\u001b[1;34m()\u001b[0m\n\u001b[0;32m 14\u001b[0m fp \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n\u001b[0;32m 15\u001b[0m fn \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n\u001b[1;32m---> 16\u001b[0m sentences \u001b[39m=\u001b[39m [sentence \u001b[39mfor\u001b[39;00m sentence \u001b[39min\u001b[39;00m testset]\n\u001b[0;32m 17\u001b[0m \u001b[39mfor\u001b[39;00m sentence \u001b[39min\u001b[39;00m sentences:\n\u001b[0;32m 18\u001b[0m \u001b[39m# get sentence as terms list\u001b[39;00m\n\u001b[0;32m 19\u001b[0m termsList \u001b[39m=\u001b[39m [w[\u001b[39m\"\u001b[39m\u001b[39mform\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39mfor\u001b[39;00m w \u001b[39min\u001b[39;00m sentence]\n",
+ "\u001b[1;31mNameError\u001b[0m: name 'testset' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "# evaluation\n",
+ "\n",
+ "def precision(tpScore, fpScore):\n",
+ " return float(tpScore) / (tpScore + fpScore)\n",
+ "\n",
+ "def recall(tpScore, fnScore):\n",
+ " return float(tpScore) / (tpScore + fnScore)\n",
+ "\n",
+ "def f1(precision, recall):\n",
+ " return 2 * precision * recall/(precision + recall)\n",
+ "\n",
+ "def eval():\n",
+ " tp = 0\n",
+ " fp = 0\n",
+ " fn = 0\n",
+ " sentences = [sentence for sentence in testset]\n",
+ " for sentence in sentences:\n",
+ " # get sentence as terms list\n",
+ " termsList = [w[\"form\"] for w in sentence]\n",
+ " # predict tags\n",
+ " predTags = [tag[1] for tag in predict(model, termsList)]\n",
+ " \n",
+ " expTags = [token[\"slot\"] + \"/\" + token[\"frame\"] for token in sentence]\n",
+ " for i in range(len(predTags)):\n",
+ " if (expTags[i][0] == \"O\" and expTags[i] != predTags[i]):\n",
+ " fp += 1\n",
+ " elif ((expTags[i][0] != \"O\") & (predTags[i][0] == \"O\")):\n",
+ " fn += 1\n",
+ " elif ((expTags[i][0] != \"O\") & (predTags[i] == expTags[i])):\n",
+ " tp += 1\n",
+ "\n",
+ " precisionScore = precision(tp, fp)\n",
+ " recallScore = recall(tp, fn)\n",
+ " f1Score = f1(precisionScore, recallScore)\n",
+ " print(\"stats: \")\n",
+ " print(\"precision: \", precisionScore)\n",
+ " print(\"recall: \", recallScore)\n",
+ " print(\"f1: \", f1Score)\n",
+ "\n",
+ "eval()\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Literatura\n",
+ "----------\n",
+ " 1. Sebastian Schuster, Sonal Gupta, Rushin Shah, Mike Lewis, Cross-lingual Transfer Learning for Multilingual Task Oriented Dialog. NAACL-HLT (1) 2019, pp. 3795-3805\n",
+ " 2. John D. Lafferty, Andrew McCallum, and Fernando C. N. Pereira. 2001. Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data. In Proceedings of the Eighteenth International Conference on Machine Learning (ICML '01). Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 282–289, https://repository.upenn.edu/cgi/viewcontent.cgi?article=1162&context=cis_papers\n",
+ " 3. Sepp Hochreiter and Jürgen Schmidhuber. 1997. Long Short-Term Memory. Neural Comput. 9, 8 (November 15, 1997), 1735–1780, https://doi.org/10.1162/neco.1997.9.8.1735\n",
+ " 4. Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin, Attention is All you Need, NIPS 2017, pp. 5998-6008, https://arxiv.org/abs/1706.03762\n",
+ " 5. Alan Akbik, Duncan Blythe, Roland Vollgraf, Contextual String Embeddings for Sequence Labeling, Proceedings of the 27th International Conference on Computational Linguistics, pp. 1638–1649, https://www.aclweb.org/anthology/C18-1139.pdf\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "author": "Marek Kubis",
+ "email": "mkubis@amu.edu.pl",
+ "interpreter": {
+ "hash": "2f9d6cf1e3d8195079a65c851de355134a77367bcd714b1a5d498c42d3c07114"
+ },
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "lang": "pl",
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.10"
+ },
+ "subtitle": "8.Parsing semantyczny z wykorzystaniem technik uczenia maszynowego[laboratoria]",
+ "title": "Systemy Dialogowe",
+ "year": "2021"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
}
diff --git a/lab/09-zarzadzanie-dialogiem-reguly(zmodyfikowany).ipynb b/lab/09-zarzadzanie-dialogiem-reguly(zmodyfikowany).ipynb
new file mode 100644
index 0000000..4032a32
--- /dev/null
+++ b/lab/09-zarzadzanie-dialogiem-reguly(zmodyfikowany).ipynb
@@ -0,0 +1,972 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": false
+ },
+ "source": [
+ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
+ " \n",
+ " Systemy Dialogowe \n",
+ " 9. Zarządzanie dialogiem z wykorzystaniem reguł [laboratoria] \n",
+ " Marek Kubis (2021)\n",
+ "\n",
+ "\n",
+ "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zarządzanie dialogiem z wykorzystaniem reguł\n",
+ "============================================\n",
+ "\n",
+ "Agent dialogowy wykorzystuje do zarządzanie dialogiem dwa moduły:\n",
+ "\n",
+ " - monitor stanu dialogu (dialogue state tracker, DST) — moduł odpowiedzialny za śledzenie stanu dialogu.\n",
+ "\n",
+ " - taktykę prowadzenia dialogu (dialogue policy) — moduł, który na podstawie stanu dialogu\n",
+ " podejmuje decyzję o tym jaką akcję (akt systemu) agent ma podjąć w kolejnej turze.\n",
+ "\n",
+ "Oba moduły mogą być realizowane zarówno z wykorzystaniem reguł jak i uczenia maszynowego.\n",
+ "Mogą one zostać również połączone w pojedynczy moduł zwany wówczas *menedżerem dialogu*.\n",
+ "\n",
+ "Przykład\n",
+ "--------\n",
+ "\n",
+ "Zaimplementujemy regułowe moduły monitora stanu dialogu oraz taktyki dialogowej a następnie\n",
+ "osadzimy je w środowisku *[ConvLab-2](https://github.com/thu-coai/ConvLab-2)*,\n",
+ "które służy do ewaluacji systemów dialogowych.\n",
+ "\n",
+ "**Uwaga:** Niektóre moduły środowiska *ConvLab-2* nie są zgodne z najnowszymi wersjami Pythona,\n",
+ "dlatego przed uruchomieniem poniższych przykładów należy się upewnić, że mają Państwo interpreter\n",
+ "Pythona w wersji 3.7. W przypadku nowszych wersji Ubuntu Pythona 3.7 można zainstalować z\n",
+ "repozytorium `deadsnakes`, wykonując polecenia przedstawione poniżej.\n",
+ "\n",
+ "```\n",
+ "sudo add-apt-repository ppa:deadsnakes/ppa\n",
+ "sudo apt update\n",
+ "sudo apt install python3.7 python3.7-dev python3.7-venv\n",
+ "```\n",
+ "\n",
+ "W przypadku innych systemów można skorzystać np. z narzędzia [pyenv](https://github.com/pyenv/pyenv) lub środowiska [conda](https://conda.io).\n",
+ "\n",
+ "Ze względu na to, że *ConvLab-2* ma wiele zależności zachęcam również do skorzystania ze środowiska\n",
+ "wirtualnego `venv`, w którym moduły zależne mogą zostać zainstalowane.\n",
+ "W tym celu należy wykonać następujące polecenia\n",
+ "\n",
+ "```\n",
+ "python3.7 -m venv convenv # utworzenie nowego środowiska o nazwie convenv\n",
+ "source convenv/bin/activate # aktywacja środowiska w bieżącej powłoce\n",
+ "pip install --ignore-installed jupyter # instalacja jupytera w środowisku convenv\n",
+ "```\n",
+ "\n",
+ "Po skonfigurowaniu środowiska można przystąpić do instalacji *ConvLab-2*, korzystając z\n",
+ "następujących poleceń\n",
+ "\n",
+ "```\n",
+ "mkdir -p l08\n",
+ "cd l08\n",
+ "git clone https://github.com/thu-coai/ConvLab-2.git\n",
+ "cd ConvLab-2\n",
+ "pip install -e .\n",
+ "python -m spacy download en_core_web_sm\n",
+ "cd ../..\n",
+ "```\n",
+ "\n",
+ "Po zakończeniu instalacji należy ponownie uruchomić notatnik w powłoce, w której aktywne jest\n",
+ "środowisko wirtualne *convenv*.\n",
+ "\n",
+ "```\n",
+ "jupyter notebook 08-zarzadzanie-dialogiem-reguly.ipynb\n",
+ "```\n",
+ "\n",
+ "Działanie zaimplementowanych modułów zilustrujemy, korzystając ze zbioru danych\n",
+ "[MultiWOZ](https://github.com/budzianowski/multiwoz) (Budzianowski i in., 2018), który zawiera\n",
+ "wypowiedzi dotyczące m.in. rezerwacji pokoi hotelowych, zamawiania biletów kolejowych oraz\n",
+ "rezerwacji stolików w restauracji.\n",
+ "\n",
+ "### Monitor Stanu Dialogu\n",
+ "\n",
+ "Do reprezentowania stanu dialogu użyjemy struktury danych wykorzystywanej w *ConvLab-2*."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'cinema': {'book': {'title': '',\n",
+ " 'date': '',\n",
+ " 'time': '',\n",
+ " 'quantity': '',\n",
+ " 'seats': '',\n",
+ " 'area': '',\n",
+ " 'interval': ''},\n",
+ " 'semi': {'goal': ''}}},\n",
+ " 'request_state': {},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# from convlab2.util.multiwoz.state import default_state\n",
+ "from utils.state import default_state\n",
+ "default_state()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Metoda `update` naszego monitora stanu dialogu będzie przyjmować akty użytkownika i odpowiednio\n",
+ "modyfikować stan dialogu.\n",
+ "W przypadku aktów typu `inform` wartości slotów zostaną zapamiętane w słownikach odpowiadających\n",
+ "poszczególnym dziedzinom pod kluczem `belief_state`.\n",
+ "W przypadku aktów typu `request` sloty, o które pyta użytkownik zostaną zapisane pod kluczem\n",
+ "`request_state`.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"\\nclass SimpleRuleDST(DST):\\n def __init__(self):\\n DST.__init__(self)\\n self.state = default_state()\\n self.value_dict = json.load(open('l08/ConvLab-2/data/multiwoz/value_dict.json'))\\n\\n def update(self, user_act=None):\\n for intent, domain, slot, value in user_act:\\n domain = domain.lower()\\n intent = intent.lower()\\n\\n if domain in ['unk', 'general', 'booking']:\\n continue\\n\\n if intent == 'inform':\\n k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\\n\\n if k is None:\\n continue\\n\\n domain_dic = self.state['belief_state'][domain]\\n\\n if k in domain_dic['semi']:\\n nvalue = normalize_value(self.value_dict, domain, k, value)\\n self.state['belief_state'][domain]['semi'][k] = nvalue\\n elif k in domain_dic['book']:\\n self.state['belief_state'][domain]['book'][k] = value\\n elif k.lower() in domain_dic['book']:\\n self.state['belief_state'][domain]['book'][k.lower()] = value\\n elif intent == 'request':\\n k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\\n\\n if domain not in self.state['request_state']:\\n self.state['request_state'][domain] = {}\\n if k not in self.state['request_state'][domain]:\\n self.state['request_state'][domain][k] = 0\\n\\n return self.state\\n\\n def init_session(self):\\n self.state = default_state()\\n\""
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "from convlab2.dst.dst import DST\n",
+ "from convlab2.dst.rule.multiwoz.dst_util import normalize_value\n",
+ "from convlab2.util.multiwoz.multiwoz_slot_trans import REF_SYS_DA\n",
+ "\n",
+ "class SimpleRuleDST(DST):\n",
+ " def __init__(self):\n",
+ " DST.__init__(self)\n",
+ " self.state = default_state()\n",
+ " self.value_dict = json.load(open('utils/value_dict.json'))\n",
+ "\n",
+ " def update(self, user_act=None):\n",
+ " for intent, domain, slot, value in user_act:\n",
+ " domain = domain.lower()\n",
+ " intent = intent.lower()\n",
+ " value = value.lower()\n",
+ "\n",
+ " # if domain in ['unk', 'cinema']:\n",
+ " # continue\n",
+ " k = slot\n",
+ "\n",
+ " if intent == 'inform':\n",
+ " # k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\n",
+ " # if k is None:\n",
+ " # continue\n",
+ "\n",
+ " domain_dic = self.state['belief_state'][domain]\n",
+ "\n",
+ " if k in domain_dic['semi']:\n",
+ " # nvalue = normalize_value(self.value_dict, domain, k, value)\n",
+ " self.state['belief_state'][domain]['semi'][k] = value\n",
+ " elif k in domain_dic['book']:\n",
+ " self.state['belief_state'][domain]['book'][k] = value\n",
+ " elif k.lower() in domain_dic['book']:\n",
+ " self.state['belief_state'][domain]['book'][k.lower()] = value\n",
+ " elif intent == 'request':\n",
+ " # k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\n",
+ "\n",
+ " if domain not in self.state['request_state']:\n",
+ " self.state['request_state'][domain] = {}\n",
+ " if k not in self.state['request_state'][domain]:\n",
+ " self.state['request_state'][domain][k] = 0\n",
+ "\n",
+ " return self.state\n",
+ "\n",
+ " def init_session(self):\n",
+ " self.state = default_state()\n",
+ "\n",
+ "'''\n",
+ "class SimpleRuleDST(DST):\n",
+ " def __init__(self):\n",
+ " DST.__init__(self)\n",
+ " self.state = default_state()\n",
+ " self.value_dict = json.load(open('l08/ConvLab-2/data/multiwoz/value_dict.json'))\n",
+ "\n",
+ " def update(self, user_act=None):\n",
+ " for intent, domain, slot, value in user_act:\n",
+ " domain = domain.lower()\n",
+ " intent = intent.lower()\n",
+ "\n",
+ " if domain in ['unk', 'general', 'booking']:\n",
+ " continue\n",
+ "\n",
+ " if intent == 'inform':\n",
+ " k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\n",
+ "\n",
+ " if k is None:\n",
+ " continue\n",
+ "\n",
+ " domain_dic = self.state['belief_state'][domain]\n",
+ "\n",
+ " if k in domain_dic['semi']:\n",
+ " nvalue = normalize_value(self.value_dict, domain, k, value)\n",
+ " self.state['belief_state'][domain]['semi'][k] = nvalue\n",
+ " elif k in domain_dic['book']:\n",
+ " self.state['belief_state'][domain]['book'][k] = value\n",
+ " elif k.lower() in domain_dic['book']:\n",
+ " self.state['belief_state'][domain]['book'][k.lower()] = value\n",
+ " elif intent == 'request':\n",
+ " k = REF_SYS_DA[domain.capitalize()].get(slot, slot)\n",
+ "\n",
+ " if domain not in self.state['request_state']:\n",
+ " self.state['request_state'][domain] = {}\n",
+ " if k not in self.state['request_state'][domain]:\n",
+ " self.state['request_state'][domain][k] = 0\n",
+ "\n",
+ " return self.state\n",
+ "\n",
+ " def init_session(self):\n",
+ " self.state = default_state()\n",
+ "'''\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "W definicji metody `update` zakładamy, że akty dialogowe przekazywane do monitora stanu dialogu z\n",
+ "modułu NLU są czteroelementowymi listami złożonymi z:\n",
+ "\n",
+ " - nazwy aktu użytkownika,\n",
+ " - nazwy dziedziny, której dotyczy wypowiedź,\n",
+ " - nazwy slotu,\n",
+ " - wartości slotu.\n",
+ "\n",
+ "Zobaczmy na kilku prostych przykładach jak stan dialogu zmienia się pod wpływem przekazanych aktów\n",
+ "użytkownika."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'cinema': {'book': {'title': '',\n",
+ " 'date': '',\n",
+ " 'time': '',\n",
+ " 'quantity': '',\n",
+ " 'seats': '',\n",
+ " 'area': '',\n",
+ " 'interval': ''},\n",
+ " 'semi': {'goal': ''}}},\n",
+ " 'request_state': {},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 35,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dst = SimpleRuleDST()\n",
+ "dst.state"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'book': {'title': 'batman',\n",
+ " 'date': '',\n",
+ " 'time': '15:00',\n",
+ " 'quantity': '',\n",
+ " 'seats': '',\n",
+ " 'area': '',\n",
+ " 'interval': ''},\n",
+ " 'semi': {'goal': ''}}"
+ ]
+ },
+ "execution_count": 36,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dst.update([['Inform', 'Cinema', 'time', '15:00'], ['Inform', 'Cinema', 'title', 'Batman']])\n",
+ "dst.state['belief_state']['cinema']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 37,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'book': {'title': 'batman',\n",
+ " 'date': '',\n",
+ " 'time': '15:00',\n",
+ " 'quantity': '',\n",
+ " 'seats': '',\n",
+ " 'area': 'na górze na środku',\n",
+ " 'interval': ''},\n",
+ " 'semi': {'goal': ''}}"
+ ]
+ },
+ "execution_count": 37,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dst.update([['Inform', 'Cinema', 'area', 'na górze na środku']])\n",
+ "dst.state['belief_state']['cinema']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'cinema': {'date': 0}}"
+ ]
+ },
+ "execution_count": 38,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dst.update([['Request', 'Cinema', 'date', '?']])\n",
+ "dst.state['request_state']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "dst.update([['Inform', 'Hotel', 'Day', 'tuesday'], ['Inform', 'Hotel', 'People', '2'], ['Inform', 'Hotel', 'Stay', '4']])\n",
+ "dst.state['belief_state']['hotel']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 39,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'cinema': {'book': {'title': 'batman',\n",
+ " 'date': '',\n",
+ " 'time': '15:00',\n",
+ " 'quantity': '',\n",
+ " 'seats': '',\n",
+ " 'area': 'na górze na środku',\n",
+ " 'interval': ''},\n",
+ " 'semi': {'goal': ''}}},\n",
+ " 'request_state': {'cinema': {'date': 0}},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 39,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dst.state"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Taktyka Prowadzenia Dialogu\n",
+ "\n",
+ "Prosta taktyka prowadzenia dialogu dla systemu rezerwacji pokoi hotelowych może składać się z następujących reguł:\n",
+ "\n",
+ " 1. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Request`, to udziel odpowiedzi na jego\n",
+ " pytanie.\n",
+ "\n",
+ " 2. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Inform`, to zaproponuj mu hotel\n",
+ " spełniający zdefiniowane przez niego kryteria.\n",
+ "\n",
+ " 3. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Inform` zawierający szczegóły\n",
+ " rezerwacji, to zarezerwuj pokój.\n",
+ "\n",
+ "Metoda `predict` taktyki `SimpleRulePolicy` realizuje reguły przedstawione powyżej."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "from collections import defaultdict\n",
+ "import copy\n",
+ "import json\n",
+ "from copy import deepcopy\n",
+ "\n",
+ "from convlab2.policy.policy import Policy\n",
+ "from convlab2.util.multiwoz.dbquery import Database\n",
+ "from convlab2.util.multiwoz.multiwoz_slot_trans import REF_SYS_DA, REF_USR_DA\n",
+ "\n",
+ "\n",
+ "class SimpleRulePolicy(Policy):\n",
+ " def __init__(self):\n",
+ " Policy.__init__(self)\n",
+ " self.db = Database()\n",
+ "\n",
+ " def predict(self, state):\n",
+ " self.results = []\n",
+ " system_action = defaultdict(list)\n",
+ " user_action = defaultdict(list)\n",
+ "\n",
+ " for intent, domain, slot, value in state['user_action']:\n",
+ " user_action[(domain, intent)].append((slot, value))\n",
+ "\n",
+ " for user_act in user_action:\n",
+ " self.update_system_action(user_act, user_action, state, system_action)\n",
+ "\n",
+ " # Reguła 3\n",
+ " if any(True for slots in user_action.values() for (slot, _) in slots if slot in ['Stay', 'Day', 'People']):\n",
+ " if self.results:\n",
+ " system_action = {('Booking', 'Book'): [[\"Ref\", self.results[0].get('Ref', 'N/A')]]}\n",
+ "\n",
+ " system_acts = [[intent, domain, slot, value] for (domain, intent), slots in system_action.items() for slot, value in slots]\n",
+ " state['system_action'] = system_acts\n",
+ " return system_acts\n",
+ "\n",
+ " def update_system_action(self, user_act, user_action, state, system_action):\n",
+ " domain, intent = user_act\n",
+ " constraints = [(slot, value) for slot, value in state['belief_state'][domain.lower()]['semi'].items() if value != '']\n",
+ " self.results = deepcopy(self.db.query(domain.lower(), constraints))\n",
+ "\n",
+ " # Reguła 1\n",
+ " if intent == 'Request':\n",
+ " if len(self.results) == 0:\n",
+ " system_action[(domain, 'NoOffer')] = []\n",
+ " else:\n",
+ " for slot in user_action[user_act]:\n",
+ " kb_slot_name = REF_SYS_DA[domain].get(slot[0], slot[0])\n",
+ "\n",
+ " if kb_slot_name in self.results[0]:\n",
+ " system_action[(domain, 'Inform')].append([slot[0], self.results[0].get(kb_slot_name, 'unknown')])\n",
+ "\n",
+ " # Reguła 2\n",
+ " elif intent == 'Inform':\n",
+ " if len(self.results) == 0:\n",
+ " system_action[(domain, 'NoOffer')] = []\n",
+ " else:\n",
+ " system_action[(domain, 'Inform')].append(['Choice', str(len(self.results))])\n",
+ " choice = self.results[0]\n",
+ "\n",
+ " if domain in [\"Hotel\", \"Attraction\", \"Police\", \"Restaurant\"]:\n",
+ " system_action[(domain, 'Recommend')].append(['Name', choice['name']])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Podobnie jak w przypadku aktów użytkownika akty systemowe przekazywane do modułu NLG są czteroelementowymi listami złożonymi z:\n",
+ "\n",
+ " - nazwy aktu systemowe,\n",
+ " - nazwy dziedziny, której dotyczy wypowiedź,\n",
+ " - nazwy slotu,\n",
+ " - wartości slotu.\n",
+ "\n",
+ "Sprawdźmy jakie akty systemowe zwraca taktyka `SimpleRulePolicy` w odpowiedzi na zmieniający się stan dialogu."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "from convlab2.dialog_agent import PipelineAgent\n",
+ "dst.init_session()\n",
+ "policy = SimpleRulePolicy()\n",
+ "agent = PipelineAgent(nlu=None, dst=dst, policy=policy, nlg=None, name='sys')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Price', 'cheap'], ['Inform', 'Hotel', 'Parking', 'yes']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Area', 'north']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response([['Request', 'Hotel', 'Area', '?']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Day', 'tuesday'], ['Inform', 'Hotel', 'People', '2'], ['Inform', 'Hotel', 'Stay', '4']])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Testy End-to-End\n",
+ "\n",
+ "Na koniec przeprowadźmy dialog łącząc w potok nasze moduły\n",
+ "z modułami NLU i NLG dostępnymi dla MultiWOZ w środowisku `ConvLab-2`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "from convlab2.nlu.svm.multiwoz import SVMNLU\n",
+ "from convlab2.nlg.template.multiwoz import TemplateNLG\n",
+ "\n",
+ "nlu = SVMNLU()\n",
+ "nlg = TemplateNLG(is_user=False)\n",
+ "agent = PipelineAgent(nlu=nlu, dst=dst, policy=policy, nlg=nlg, name='sys')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response(\"I need a cheap hotel with free parking .\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response(\"Where it is located ?\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response(\"I would prefer the hotel be in the north part of town .\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ },
+ {
+ "ename": "",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31mRunning cells with 'Python 3.6.15 ('sysdial')' requires ipykernel package.\n",
+ "Run the following command to install 'ipykernel' into the Python environment. \n",
+ "Command: 'conda install -n sysdial ipykernel --update-deps --force-reinstall'"
+ ]
+ }
+ ],
+ "source": [
+ "agent.response(\"Yeah , could you book me a room for 2 people for 4 nights starting Tuesday ?\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zauważmy, ze nasza prosta taktyka dialogowa zawiera wiele luk, do których należą m.in.:\n",
+ "\n",
+ " 1. Niezdolność do udzielenia odpowiedzi na przywitanie, prośbę o pomoc lub restart.\n",
+ "\n",
+ " 2. Brak reguł dopytujących użytkownika o szczegóły niezbędne do dokonania rezerwacji takie, jak długość pobytu czy liczba osób.\n",
+ "\n",
+ "Bardziej zaawansowane moduły zarządzania dialogiem zbudowane z wykorzystaniem reguł można znaleźć w\n",
+ "środowisku `ConvLab-2`. Należą do nich m.in. monitor [RuleDST](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/dst/rule/multiwoz/dst.py) oraz taktyka [RuleBasedMultiwozBot](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/policy/rule/multiwoz/rule_based_multiwoz_bot.py).\n",
+ "\n",
+ "Zadania\n",
+ "-------\n",
+ " 1. Zaimplementować w projekcie monitor stanu dialogu.\n",
+ "\n",
+ " 2. Zaimplementować w projekcie taktykę prowadzenia dialogu.\n",
+ "\n",
+ "Termin: 24.05.2021, godz. 23:59.\n",
+ "\n",
+ "Literatura\n",
+ "----------\n",
+ " 1. Pawel Budzianowski, Tsung-Hsien Wen, Bo-Hsiang Tseng, Iñigo Casanueva, Stefan Ultes, Osman Ramadan, Milica Gasic, MultiWOZ - A Large-Scale Multi-Domain Wizard-of-Oz Dataset for Task-Oriented Dialogue Modelling. EMNLP 2018, pp. 5016-5026\n",
+ " 2. Cathy Pearl, Basic principles for designing voice user interfaces, https://www.oreilly.com/content/basic-principles-for-designing-voice-user-interfaces/ data dostępu: 21 marca 2021\n",
+ " 3. Cathy Pearl, Designing Voice User Interfaces, Excerpts from Chapter 5: Advanced Voice User Interface Design, https://www.uxmatters.com/mt/archives/2018/01/designing-voice-user-interfaces.php data dostępu: 21 marca 2021"
+ ]
+ }
+ ],
+ "metadata": {
+ "author": "Marek Kubis",
+ "email": "mkubis@amu.edu.pl",
+ "interpreter": {
+ "hash": "91e2b0d1baa6ebb76863bdb1d11380bf032a6a1fc1b919194f041a5133852891"
+ },
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.7.9 ('venv': venv)",
+ "language": "python",
+ "name": "python3"
+ },
+ "lang": "pl",
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.9"
+ },
+ "subtitle": "9.Zarządzanie dialogiem z wykorzystaniem reguł[laboratoria]",
+ "title": "Systemy Dialogowe",
+ "year": "2021"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/lab/09-zarzadzanie-dialogiem-reguly.ipynb b/lab/09-zarzadzanie-dialogiem-reguly.ipynb
index 6d59ed6..bce9113 100644
--- a/lab/09-zarzadzanie-dialogiem-reguly.ipynb
+++ b/lab/09-zarzadzanie-dialogiem-reguly.ipynb
@@ -9,7 +9,7 @@
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
"\n",
" Systemy Dialogowe \n",
- " 9. Zarz\u0105dzanie dialogiem z wykorzystaniem regu\u0142 [laboratoria] \n",
+ " 9. Zarządzanie dialogiem z wykorzystaniem reguł [laboratoria] \n",
" Marek Kubis (2021)\n",
"\n",
"\n",
@@ -20,30 +20,30 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Zarz\u0105dzanie dialogiem z wykorzystaniem regu\u0142\n",
+ "Zarządzanie dialogiem z wykorzystaniem reguł\n",
"============================================\n",
"\n",
- "Agent dialogowy wykorzystuje do zarz\u0105dzanie dialogiem dwa modu\u0142y:\n",
+ "Agent dialogowy wykorzystuje do zarządzanie dialogiem dwa moduły:\n",
"\n",
- " - monitor stanu dialogu (dialogue state tracker, DST) \u2014 modu\u0142 odpowiedzialny za \u015bledzenie stanu dialogu.\n",
+ " - monitor stanu dialogu (dialogue state tracker, DST) — moduł odpowiedzialny za śledzenie stanu dialogu.\n",
"\n",
- " - taktyk\u0119 prowadzenia dialogu (dialogue policy) \u2014 modu\u0142, kt\u00f3ry na podstawie stanu dialogu\n",
- " podejmuje decyzj\u0119 o tym jak\u0105 akcj\u0119 (akt systemu) agent ma podj\u0105\u0107 w kolejnej turze.\n",
+ " - taktykę prowadzenia dialogu (dialogue policy) — moduł, który na podstawie stanu dialogu\n",
+ " podejmuje decyzję o tym jaką akcję (akt systemu) agent ma podjąć w kolejnej turze.\n",
"\n",
- "Oba modu\u0142y mog\u0105 by\u0107 realizowane zar\u00f3wno z wykorzystaniem regu\u0142 jak i uczenia maszynowego.\n",
- "Mog\u0105 one zosta\u0107 r\u00f3wnie\u017c po\u0142\u0105czone w pojedynczy modu\u0142 zwany w\u00f3wczas *mened\u017cerem dialogu*.\n",
+ "Oba moduły mogą być realizowane zarówno z wykorzystaniem reguł jak i uczenia maszynowego.\n",
+ "Mogą one zostać również połączone w pojedynczy moduł zwany wówczas *menedżerem dialogu*.\n",
"\n",
- "Przyk\u0142ad\n",
+ "Przykład\n",
"--------\n",
"\n",
- "Zaimplementujemy regu\u0142owe modu\u0142y monitora stanu dialogu oraz taktyki dialogowej a nast\u0119pnie\n",
- "osadzimy je w \u015brodowisku *[ConvLab-2](https://github.com/thu-coai/ConvLab-2)*,\n",
- "kt\u00f3re s\u0142u\u017cy do ewaluacji system\u00f3w dialogowych.\n",
+ "Zaimplementujemy regułowe moduły monitora stanu dialogu oraz taktyki dialogowej a następnie\n",
+ "osadzimy je w środowisku *[ConvLab-2](https://github.com/thu-coai/ConvLab-2)*,\n",
+ "które służy do ewaluacji systemów dialogowych.\n",
"\n",
- "**Uwaga:** Niekt\u00f3re modu\u0142y \u015brodowiska *ConvLab-2* nie s\u0105 zgodne z najnowszymi wersjami Pythona,\n",
- "dlatego przed uruchomieniem poni\u017cszych przyk\u0142ad\u00f3w nale\u017cy si\u0119 upewni\u0107, \u017ce maj\u0105 Pa\u0144stwo interpreter\n",
- "Pythona w wersji 3.7. W przypadku nowszych wersji Ubuntu Pythona 3.7 mo\u017cna zainstalowa\u0107 z\n",
- "repozytorium `deadsnakes`, wykonuj\u0105c polecenia przedstawione poni\u017cej.\n",
+ "**Uwaga:** Niektóre moduły środowiska *ConvLab-2* nie są zgodne z najnowszymi wersjami Pythona,\n",
+ "dlatego przed uruchomieniem poniższych przykładów należy się upewnić, że mają Państwo interpreter\n",
+ "Pythona w wersji 3.7. W przypadku nowszych wersji Ubuntu Pythona 3.7 można zainstalować z\n",
+ "repozytorium `deadsnakes`, wykonując polecenia przedstawione poniżej.\n",
"\n",
"```\n",
"sudo add-apt-repository ppa:deadsnakes/ppa\n",
@@ -51,20 +51,20 @@
"sudo apt install python3.7 python3.7-dev python3.7-venv\n",
"```\n",
"\n",
- "W przypadku innych system\u00f3w mo\u017cna skorzysta\u0107 np. z narz\u0119dzia [pyenv](https://github.com/pyenv/pyenv) lub \u015brodowiska [conda](https://conda.io).\n",
+ "W przypadku innych systemów można skorzystać np. z narzędzia [pyenv](https://github.com/pyenv/pyenv) lub środowiska [conda](https://conda.io).\n",
"\n",
- "Ze wzgl\u0119du na to, \u017ce *ConvLab-2* ma wiele zale\u017cno\u015bci zach\u0119cam r\u00f3wnie\u017c do skorzystania ze \u015brodowiska\n",
- "wirtualnego `venv`, w kt\u00f3rym modu\u0142y zale\u017cne mog\u0105 zosta\u0107 zainstalowane.\n",
- "W tym celu nale\u017cy wykona\u0107 nast\u0119puj\u0105ce polecenia\n",
+ "Ze względu na to, że *ConvLab-2* ma wiele zależności zachęcam również do skorzystania ze środowiska\n",
+ "wirtualnego `venv`, w którym moduły zależne mogą zostać zainstalowane.\n",
+ "W tym celu należy wykonać następujące polecenia\n",
"\n",
"```\n",
- "python3.7 -m venv convenv # utworzenie nowego \u015brodowiska o nazwie convenv\n",
- "source convenv/bin/activate # aktywacja \u015brodowiska w bie\u017c\u0105cej pow\u0142oce\n",
- "pip install --ignore-installed jupyter # instalacja jupytera w \u015brodowisku convenv\n",
+ "python3.7 -m venv convenv # utworzenie nowego środowiska o nazwie convenv\n",
+ "source convenv/bin/activate # aktywacja środowiska w bieżącej powłoce\n",
+ "pip install --ignore-installed jupyter # instalacja jupytera w środowisku convenv\n",
"```\n",
"\n",
- "Po skonfigurowaniu \u015brodowiska mo\u017cna przyst\u0105pi\u0107 do instalacji *ConvLab-2*, korzystaj\u0105c z\n",
- "nast\u0119puj\u0105cych polece\u0144\n",
+ "Po skonfigurowaniu środowiska można przystąpić do instalacji *ConvLab-2*, korzystając z\n",
+ "następujących poleceń\n",
"\n",
"```\n",
"mkdir -p l08\n",
@@ -76,28 +76,68 @@
"cd ../..\n",
"```\n",
"\n",
- "Po zako\u0144czeniu instalacji nale\u017cy ponownie uruchomi\u0107 notatnik w pow\u0142oce, w kt\u00f3rej aktywne jest\n",
- "\u015brodowisko wirtualne *convenv*.\n",
+ "Po zakończeniu instalacji należy ponownie uruchomić notatnik w powłoce, w której aktywne jest\n",
+ "środowisko wirtualne *convenv*.\n",
"\n",
"```\n",
"jupyter notebook 08-zarzadzanie-dialogiem-reguly.ipynb\n",
"```\n",
"\n",
- "Dzia\u0142anie zaimplementowanych modu\u0142\u00f3w zilustrujemy, korzystaj\u0105c ze zbioru danych\n",
- "[MultiWOZ](https://github.com/budzianowski/multiwoz) (Budzianowski i in., 2018), kt\u00f3ry zawiera\n",
- "wypowiedzi dotycz\u0105ce m.in. rezerwacji pokoi hotelowych, zamawiania bilet\u00f3w kolejowych oraz\n",
- "rezerwacji stolik\u00f3w w restauracji.\n",
+ "Działanie zaimplementowanych modułów zilustrujemy, korzystając ze zbioru danych\n",
+ "[MultiWOZ](https://github.com/budzianowski/multiwoz) (Budzianowski i in., 2018), który zawiera\n",
+ "wypowiedzi dotyczące m.in. rezerwacji pokoi hotelowych, zamawiania biletów kolejowych oraz\n",
+ "rezerwacji stolików w restauracji.\n",
"\n",
"### Monitor Stanu Dialogu\n",
"\n",
- "Do reprezentowania stanu dialogu u\u017cyjemy struktury danych wykorzystywanej w *ConvLab-2*."
+ "Do reprezentowania stanu dialogu użyjemy struktury danych wykorzystywanej w *ConvLab-2*."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'police': {'book': {'booked': []}, 'semi': {}},\n",
+ " 'hotel': {'book': {'booked': [], 'people': '', 'day': '', 'stay': ''},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': '',\n",
+ " 'parking': '',\n",
+ " 'pricerange': '',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}},\n",
+ " 'attraction': {'book': {'booked': []},\n",
+ " 'semi': {'type': '', 'name': '', 'area': ''}},\n",
+ " 'restaurant': {'book': {'booked': [], 'people': '', 'day': '', 'time': ''},\n",
+ " 'semi': {'food': '', 'pricerange': '', 'name': '', 'area': ''}},\n",
+ " 'hospital': {'book': {'booked': []}, 'semi': {'department': ''}},\n",
+ " 'taxi': {'book': {'booked': []},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'departure': '',\n",
+ " 'arriveBy': ''}},\n",
+ " 'train': {'book': {'booked': [], 'people': ''},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'day': '',\n",
+ " 'arriveBy': '',\n",
+ " 'departure': ''}}},\n",
+ " 'request_state': {},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 1,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"from convlab2.util.multiwoz.state import default_state\n",
"default_state()"
@@ -107,17 +147,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Metoda `update` naszego monitora stanu dialogu b\u0119dzie przyjmowa\u0107 akty u\u017cytkownika i odpowiednio\n",
- "modyfikowa\u0107 stan dialogu.\n",
- "W przypadku akt\u00f3w typu `inform` warto\u015bci slot\u00f3w zostan\u0105 zapami\u0119tane w s\u0142ownikach odpowiadaj\u0105cych\n",
- "poszczeg\u00f3lnym dziedzinom pod kluczem `belief_state`.\n",
- "W przypadku akt\u00f3w typu `request` sloty, o kt\u00f3re pyta u\u017cytkownik zostan\u0105 zapisane pod kluczem\n",
+ "Metoda `update` naszego monitora stanu dialogu będzie przyjmować akty użytkownika i odpowiednio\n",
+ "modyfikować stan dialogu.\n",
+ "W przypadku aktów typu `inform` wartości slotów zostaną zapamiętane w słownikach odpowiadających\n",
+ "poszczególnym dziedzinom pod kluczem `belief_state`.\n",
+ "W przypadku aktów typu `request` sloty, o które pyta użytkownik zostaną zapisane pod kluczem\n",
"`request_state`.\n"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -132,7 +172,7 @@
" def __init__(self):\n",
" DST.__init__(self)\n",
" self.state = default_state()\n",
- " self.value_dict = json.load(open('l08/ConvLab-2/data/multiwoz/value_dict.json'))\n",
+ " self.value_dict = json.load(open('ConvLab-2/data/multiwoz/value_dict.json'))\n",
"\n",
" def update(self, user_act=None):\n",
" for intent, domain, slot, value in user_act:\n",
@@ -175,25 +215,65 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "W definicji metody `update` zak\u0142adamy, \u017ce akty dialogowe przekazywane do monitora stanu dialogu z\n",
- "modu\u0142u NLU s\u0105 czteroelementowymi listami z\u0142o\u017conymi z:\n",
+ "W definicji metody `update` zakładamy, że akty dialogowe przekazywane do monitora stanu dialogu z\n",
+ "modułu NLU są czteroelementowymi listami złożonymi z:\n",
"\n",
- " - nazwy aktu u\u017cytkownika,\n",
- " - nazwy dziedziny, kt\u00f3rej dotyczy wypowied\u017a,\n",
+ " - nazwy aktu użytkownika,\n",
+ " - nazwy dziedziny, której dotyczy wypowiedź,\n",
" - nazwy slotu,\n",
- " - warto\u015bci slotu.\n",
+ " - wartości slotu.\n",
"\n",
- "Zobaczmy na kilku prostych przyk\u0142adach jak stan dialogu zmienia si\u0119 pod wp\u0142ywem przekazanych akt\u00f3w\n",
- "u\u017cytkownika."
+ "Zobaczmy na kilku prostych przykładach jak stan dialogu zmienia się pod wpływem przekazanych aktów\n",
+ "użytkownika."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'police': {'book': {'booked': []}, 'semi': {}},\n",
+ " 'hotel': {'book': {'booked': [], 'people': '', 'day': '', 'stay': ''},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': '',\n",
+ " 'parking': '',\n",
+ " 'pricerange': '',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}},\n",
+ " 'attraction': {'book': {'booked': []},\n",
+ " 'semi': {'type': '', 'name': '', 'area': ''}},\n",
+ " 'restaurant': {'book': {'booked': [], 'people': '', 'day': '', 'time': ''},\n",
+ " 'semi': {'food': '', 'pricerange': '', 'name': '', 'area': ''}},\n",
+ " 'hospital': {'book': {'booked': []}, 'semi': {'department': ''}},\n",
+ " 'taxi': {'book': {'booked': []},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'departure': '',\n",
+ " 'arriveBy': ''}},\n",
+ " 'train': {'book': {'booked': [], 'people': ''},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'day': '',\n",
+ " 'arriveBy': '',\n",
+ " 'departure': ''}}},\n",
+ " 'request_state': {},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst = SimpleRuleDST()\n",
"dst.state"
@@ -201,11 +281,29 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'book': {'booked': [], 'people': '', 'day': '', 'stay': ''},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': '',\n",
+ " 'parking': 'yes',\n",
+ " 'pricerange': 'cheap',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}}"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst.update([['Inform', 'Hotel', 'Price', 'cheap'], ['Inform', 'Hotel', 'Parking', 'yes']])\n",
"dst.state['belief_state']['hotel']"
@@ -213,11 +311,29 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'book': {'booked': [], 'people': '', 'day': '', 'stay': ''},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': 'north',\n",
+ " 'parking': 'yes',\n",
+ " 'pricerange': 'cheap',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}}"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst.update([['Inform', 'Hotel', 'Area', 'north']])\n",
"dst.state['belief_state']['hotel']"
@@ -225,11 +341,22 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'hotel': {'area': 0}}"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst.update([['Request', 'Hotel', 'Area', '?']])\n",
"dst.state['request_state']"
@@ -237,11 +364,29 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'book': {'booked': [], 'people': '2', 'day': 'tuesday', 'stay': '4'},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': 'north',\n",
+ " 'parking': 'yes',\n",
+ " 'pricerange': 'cheap',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}}"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst.update([['Inform', 'Hotel', 'Day', 'tuesday'], ['Inform', 'Hotel', 'People', '2'], ['Inform', 'Hotel', 'Stay', '4']])\n",
"dst.state['belief_state']['hotel']"
@@ -249,9 +394,52 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'user_action': [],\n",
+ " 'system_action': [],\n",
+ " 'belief_state': {'police': {'book': {'booked': []}, 'semi': {}},\n",
+ " 'hotel': {'book': {'booked': [],\n",
+ " 'people': '2',\n",
+ " 'day': 'tuesday',\n",
+ " 'stay': '4'},\n",
+ " 'semi': {'name': '',\n",
+ " 'area': 'north',\n",
+ " 'parking': 'yes',\n",
+ " 'pricerange': 'cheap',\n",
+ " 'stars': '',\n",
+ " 'internet': '',\n",
+ " 'type': ''}},\n",
+ " 'attraction': {'book': {'booked': []},\n",
+ " 'semi': {'type': '', 'name': '', 'area': ''}},\n",
+ " 'restaurant': {'book': {'booked': [], 'people': '', 'day': '', 'time': ''},\n",
+ " 'semi': {'food': '', 'pricerange': '', 'name': '', 'area': ''}},\n",
+ " 'hospital': {'book': {'booked': []}, 'semi': {'department': ''}},\n",
+ " 'taxi': {'book': {'booked': []},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'departure': '',\n",
+ " 'arriveBy': ''}},\n",
+ " 'train': {'book': {'booked': [], 'people': ''},\n",
+ " 'semi': {'leaveAt': '',\n",
+ " 'destination': '',\n",
+ " 'day': '',\n",
+ " 'arriveBy': '',\n",
+ " 'departure': ''}}},\n",
+ " 'request_state': {'hotel': {'area': 0}},\n",
+ " 'terminated': False,\n",
+ " 'history': []}"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"dst.state"
]
@@ -262,23 +450,23 @@
"source": [
"### Taktyka Prowadzenia Dialogu\n",
"\n",
- "Prosta taktyka prowadzenia dialogu dla systemu rezerwacji pokoi hotelowych mo\u017ce sk\u0142ada\u0107 si\u0119 z nast\u0119puj\u0105cych regu\u0142:\n",
+ "Prosta taktyka prowadzenia dialogu dla systemu rezerwacji pokoi hotelowych może składać się z następujących reguł:\n",
"\n",
- " 1. Je\u017celi u\u017cytkownik przekaza\u0142 w ostatniej turze akt typu `Request`, to udziel odpowiedzi na jego\n",
+ " 1. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Request`, to udziel odpowiedzi na jego\n",
" pytanie.\n",
"\n",
- " 2. Je\u017celi u\u017cytkownik przekaza\u0142 w ostatniej turze akt typu `Inform`, to zaproponuj mu hotel\n",
- " spe\u0142niaj\u0105cy zdefiniowane przez niego kryteria.\n",
+ " 2. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Inform`, to zaproponuj mu hotel\n",
+ " spełniający zdefiniowane przez niego kryteria.\n",
"\n",
- " 3. Je\u017celi u\u017cytkownik przekaza\u0142 w ostatniej turze akt typu `Inform` zawieraj\u0105cy szczeg\u00f3\u0142y\n",
- " rezerwacji, to zarezerwuj pok\u00f3j.\n",
+ " 3. Jeżeli użytkownik przekazał w ostatniej turze akt typu `Inform` zawierający szczegóły\n",
+ " rezerwacji, to zarezerwuj pokój.\n",
"\n",
- "Metoda `predict` taktyki `SimpleRulePolicy` realizuje regu\u0142y przedstawione powy\u017cej."
+ "Metoda `predict` taktyki `SimpleRulePolicy` realizuje reguły przedstawione powyżej."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
@@ -308,7 +496,7 @@
" for user_act in user_action:\n",
" self.update_system_action(user_act, user_action, state, system_action)\n",
"\n",
- " # Regu\u0142a 3\n",
+ " # Reguła 3\n",
" if any(True for slots in user_action.values() for (slot, _) in slots if slot in ['Stay', 'Day', 'People']):\n",
" if self.results:\n",
" system_action = {('Booking', 'Book'): [[\"Ref\", self.results[0].get('Ref', 'N/A')]]}\n",
@@ -322,7 +510,7 @@
" constraints = [(slot, value) for slot, value in state['belief_state'][domain.lower()]['semi'].items() if value != '']\n",
" self.results = deepcopy(self.db.query(domain.lower(), constraints))\n",
"\n",
- " # Regu\u0142a 1\n",
+ " # Reguła 1\n",
" if intent == 'Request':\n",
" if len(self.results) == 0:\n",
" system_action[(domain, 'NoOffer')] = []\n",
@@ -333,7 +521,7 @@
" if kb_slot_name in self.results[0]:\n",
" system_action[(domain, 'Inform')].append([slot[0], self.results[0].get(kb_slot_name, 'unknown')])\n",
"\n",
- " # Regu\u0142a 2\n",
+ " # Reguła 2\n",
" elif intent == 'Inform':\n",
" if len(self.results) == 0:\n",
" system_action[(domain, 'NoOffer')] = []\n",
@@ -349,19 +537,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Podobnie jak w przypadku akt\u00f3w u\u017cytkownika akty systemowe przekazywane do modu\u0142u NLG s\u0105 czteroelementowymi listami z\u0142o\u017conymi z:\n",
+ "Podobnie jak w przypadku aktów użytkownika akty systemowe przekazywane do modułu NLG są czteroelementowymi listami złożonymi z:\n",
"\n",
" - nazwy aktu systemowe,\n",
- " - nazwy dziedziny, kt\u00f3rej dotyczy wypowied\u017a,\n",
+ " - nazwy dziedziny, której dotyczy wypowiedź,\n",
" - nazwy slotu,\n",
- " - warto\u015bci slotu.\n",
+ " - wartości slotu.\n",
"\n",
- "Sprawd\u017amy jakie akty systemowe zwraca taktyka `SimpleRulePolicy` w odpowiedzi na zmieniaj\u0105cy si\u0119 stan dialogu."
+ "Sprawdźmy jakie akty systemowe zwraca taktyka `SimpleRulePolicy` w odpowiedzi na zmieniający się stan dialogu."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"metadata": {
"lines_to_next_cell": 0
},
@@ -375,42 +563,88 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['Inform', 'Hotel', 'Choice', '10'],\n",
+ " ['Recommend', 'Hotel', 'Name', 'alexander bed and breakfast']]"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"agent.response([['Inform', 'Hotel', 'Price', 'cheap'], ['Inform', 'Hotel', 'Parking', 'yes']])"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['Inform', 'Hotel', 'Choice', '2'],\n",
+ " ['Recommend', 'Hotel', 'Name', 'city centre north b and b']]"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"agent.response([['Inform', 'Hotel', 'Area', 'north']])"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 14,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['Inform', 'Hotel', 'Area', 'north']]"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"agent.response([['Request', 'Hotel', 'Area', '?']])"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 15,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[['Book', 'Booking', 'Ref', '00000013']]"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"agent.response([['Inform', 'Hotel', 'Day', 'tuesday'], ['Inform', 'Hotel', 'People', '2'], ['Inform', 'Hotel', 'Stay', '4']])"
]
@@ -421,15 +655,25 @@
"source": [
"### Testy End-to-End\n",
"\n",
- "Na koniec przeprowad\u017amy dialog \u0142\u0105cz\u0105c w potok nasze modu\u0142y\n",
- "z modu\u0142ami NLU i NLG dost\u0119pnymi dla MultiWOZ w \u015brodowisku `ConvLab-2`."
+ "Na koniec przeprowadźmy dialog łącząc w potok nasze moduły\n",
+ "z modułami NLU i NLG dostępnymi dla MultiWOZ w środowisku `ConvLab-2`."
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 20,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[]\n",
+ "loading saved Classifier\n",
+ "loaded.\n"
+ ]
+ }
+ ],
"source": [
"from convlab2.nlu.svm.multiwoz import SVMNLU\n",
"from convlab2.nlg.template.multiwoz import TemplateNLG\n",
@@ -441,33 +685,90 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 17,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'SVC' object has no attribute '_impl'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_13500\\3260802613.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0magent\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mresponse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"I need a cheap hotel with free parking .\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\dialog_agent\\agent.py\u001b[0m in \u001b[0;36mresponse\u001b[1;34m(self, observation)\u001b[0m\n\u001b[0;32m 120\u001b[0m \u001b[1;31m# get dialog act\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 121\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 122\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobservation\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 123\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 124\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mobservation\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\multiwoz\\nlu.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, utterance, context)\u001b[0m\n\u001b[0;32m 74\u001b[0m ]\n\u001b[0;32m 75\u001b[0m }\n\u001b[1;32m---> 76\u001b[1;33m \u001b[0mslu_hyps\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode_sent\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"decode\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"output\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 77\u001b[0m \u001b[0mact_list\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 78\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mhyp\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mslu_hyps\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode_sent\u001b[1;34m(self, sentinfo, output_fname, config)\u001b[0m\n\u001b[0;32m 320\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 321\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextractFeatures2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 322\u001b[1;33m \u001b[0mdecode_results\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 323\u001b[0m \u001b[0mcounter\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 324\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 258\u001b[0m \u001b[0mbaseXs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mindex\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseX_pointers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 259\u001b[0m \u001b[0mX\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtoSparse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdictionary\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 260\u001b[1;33m \u001b[0mresults\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclassifiers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 261\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 262\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, X)\u001b[0m\n\u001b[0;32m 496\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 497\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 498\u001b[1;33m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 499\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 500\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36mpredict_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 588\u001b[0m \u001b[0mdatasets\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 589\u001b[0m \"\"\"\n\u001b[1;32m--> 590\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 591\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_predict_proba\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 592\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36m_check_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 557\u001b[0m raise AttributeError(\"predict_proba is not available when \"\n\u001b[0;32m 558\u001b[0m \" probability=False\")\n\u001b[1;32m--> 559\u001b[1;33m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_impl\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'c_svc'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'nu_svc'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 560\u001b[0m raise AttributeError(\"predict_proba only implemented for SVC\"\n\u001b[0;32m 561\u001b[0m \" and NuSVC\")\n",
+ "\u001b[1;31mAttributeError\u001b[0m: 'SVC' object has no attribute '_impl'"
+ ]
+ }
+ ],
"source": [
"agent.response(\"I need a cheap hotel with free parking .\")"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 18,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'SVC' object has no attribute '_impl'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_13500\\2723043776.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0magent\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mresponse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Where it is located ?\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\dialog_agent\\agent.py\u001b[0m in \u001b[0;36mresponse\u001b[1;34m(self, observation)\u001b[0m\n\u001b[0;32m 120\u001b[0m \u001b[1;31m# get dialog act\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 121\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 122\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobservation\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 123\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 124\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mobservation\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\multiwoz\\nlu.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, utterance, context)\u001b[0m\n\u001b[0;32m 74\u001b[0m ]\n\u001b[0;32m 75\u001b[0m }\n\u001b[1;32m---> 76\u001b[1;33m \u001b[0mslu_hyps\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode_sent\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"decode\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"output\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 77\u001b[0m \u001b[0mact_list\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 78\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mhyp\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mslu_hyps\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode_sent\u001b[1;34m(self, sentinfo, output_fname, config)\u001b[0m\n\u001b[0;32m 320\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 321\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextractFeatures2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 322\u001b[1;33m \u001b[0mdecode_results\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 323\u001b[0m \u001b[0mcounter\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 324\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 258\u001b[0m \u001b[0mbaseXs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mindex\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseX_pointers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 259\u001b[0m \u001b[0mX\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtoSparse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdictionary\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 260\u001b[1;33m \u001b[0mresults\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclassifiers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 261\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 262\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, X)\u001b[0m\n\u001b[0;32m 496\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 497\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 498\u001b[1;33m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 499\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 500\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36mpredict_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 588\u001b[0m \u001b[0mdatasets\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 589\u001b[0m \"\"\"\n\u001b[1;32m--> 590\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 591\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_predict_proba\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 592\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36m_check_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 557\u001b[0m raise AttributeError(\"predict_proba is not available when \"\n\u001b[0;32m 558\u001b[0m \" probability=False\")\n\u001b[1;32m--> 559\u001b[1;33m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_impl\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'c_svc'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'nu_svc'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 560\u001b[0m raise AttributeError(\"predict_proba only implemented for SVC\"\n\u001b[0;32m 561\u001b[0m \" and NuSVC\")\n",
+ "\u001b[1;31mAttributeError\u001b[0m: 'SVC' object has no attribute '_impl'"
+ ]
+ }
+ ],
"source": [
"agent.response(\"Where it is located ?\")"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 19,
"metadata": {
"lines_to_next_cell": 0
},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'SVC' object has no attribute '_impl'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_13500\\871593950.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0magent\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mresponse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"I would prefer the hotel be in the north part of town .\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\dialog_agent\\agent.py\u001b[0m in \u001b[0;36mresponse\u001b[1;34m(self, observation)\u001b[0m\n\u001b[0;32m 120\u001b[0m \u001b[1;31m# get dialog act\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 121\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 122\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnlu\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobservation\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcontext\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 123\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 124\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minput_action\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mobservation\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\multiwoz\\nlu.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, utterance, context)\u001b[0m\n\u001b[0;32m 74\u001b[0m ]\n\u001b[0;32m 75\u001b[0m }\n\u001b[1;32m---> 76\u001b[1;33m \u001b[0mslu_hyps\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode_sent\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"decode\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"output\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 77\u001b[0m \u001b[0mact_list\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 78\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mhyp\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mslu_hyps\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode_sent\u001b[1;34m(self, sentinfo, output_fname, config)\u001b[0m\n\u001b[0;32m 320\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 321\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextractFeatures2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msentinfo\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlog_input_key\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 322\u001b[1;33m \u001b[0mdecode_results\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 323\u001b[0m \u001b[0mcounter\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 324\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mdecode\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 258\u001b[0m \u001b[0mbaseXs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mindex\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbaseX_pointers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 259\u001b[0m \u001b[0mX\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtoSparse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbaseXs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdictionary\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 260\u001b[1;33m \u001b[0mresults\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclassifiers\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthis_tuple\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 261\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 262\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\develop\\wmi\\aitech\\sem1\\systemy dialogowe\\lab\\convlab-2\\convlab2\\nlu\\svm\\Classifier.py\u001b[0m in \u001b[0;36mpredict\u001b[1;34m(self, X)\u001b[0m\n\u001b[0;32m 496\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 497\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mpredict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 498\u001b[1;33m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpredict_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 499\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 500\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36mpredict_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 588\u001b[0m \u001b[0mdatasets\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 589\u001b[0m \"\"\"\n\u001b[1;32m--> 590\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_proba\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 591\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_predict_proba\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 592\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\venv\\lib\\site-packages\\sklearn\\svm\\base.py\u001b[0m in \u001b[0;36m_check_proba\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 557\u001b[0m raise AttributeError(\"predict_proba is not available when \"\n\u001b[0;32m 558\u001b[0m \" probability=False\")\n\u001b[1;32m--> 559\u001b[1;33m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_impl\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'c_svc'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'nu_svc'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 560\u001b[0m raise AttributeError(\"predict_proba only implemented for SVC\"\n\u001b[0;32m 561\u001b[0m \" and NuSVC\")\n",
+ "\u001b[1;31mAttributeError\u001b[0m: 'SVC' object has no attribute '_impl'"
+ ]
+ }
+ ],
"source": [
"agent.response(\"I would prefer the hotel be in the north part of town .\")"
]
@@ -485,44 +786,64 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Zauwa\u017cmy, ze nasza prosta taktyka dialogowa zawiera wiele luk, do kt\u00f3rych nale\u017c\u0105 m.in.:\n",
+ "Zauważmy, ze nasza prosta taktyka dialogowa zawiera wiele luk, do których należą m.in.:\n",
"\n",
- " 1. Niezdolno\u015b\u0107 do udzielenia odpowiedzi na przywitanie, pro\u015bb\u0119 o pomoc lub restart.\n",
+ " 1. Niezdolność do udzielenia odpowiedzi na przywitanie, prośbę o pomoc lub restart.\n",
"\n",
- " 2. Brak regu\u0142 dopytuj\u0105cych u\u017cytkownika o szczeg\u00f3\u0142y niezb\u0119dne do dokonania rezerwacji takie, jak d\u0142ugo\u015b\u0107 pobytu czy liczba os\u00f3b.\n",
+ " 2. Brak reguł dopytujących użytkownika o szczegóły niezbędne do dokonania rezerwacji takie, jak długość pobytu czy liczba osób.\n",
"\n",
- "Bardziej zaawansowane modu\u0142y zarz\u0105dzania dialogiem zbudowane z wykorzystaniem regu\u0142 mo\u017cna znale\u017a\u0107 w\n",
- "\u015brodowisku `ConvLab-2`. Nale\u017c\u0105 do nich m.in. monitor [RuleDST](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/dst/rule/multiwoz/dst.py) oraz taktyka [RuleBasedMultiwozBot](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/policy/rule/multiwoz/rule_based_multiwoz_bot.py).\n",
+ "Bardziej zaawansowane moduły zarządzania dialogiem zbudowane z wykorzystaniem reguł można znaleźć w\n",
+ "środowisku `ConvLab-2`. Należą do nich m.in. monitor [RuleDST](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/dst/rule/multiwoz/dst.py) oraz taktyka [RuleBasedMultiwozBot](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/policy/rule/multiwoz/rule_based_multiwoz_bot.py).\n",
"\n",
"Zadania\n",
"-------\n",
- " 1. Zaimplementowa\u0107 w projekcie monitor stanu dialogu.\n",
+ " 1. Zaimplementować w projekcie monitor stanu dialogu.\n",
"\n",
- " 2. Zaimplementowa\u0107 w projekcie taktyk\u0119 prowadzenia dialogu.\n",
+ " 2. Zaimplementować w projekcie taktykę prowadzenia dialogu.\n",
"\n",
"Termin: 24.05.2021, godz. 23:59.\n",
"\n",
"Literatura\n",
"----------\n",
- " 1. Pawel Budzianowski, Tsung-Hsien Wen, Bo-Hsiang Tseng, I\u00f1igo Casanueva, Stefan Ultes, Osman Ramadan, Milica Gasic, MultiWOZ - A Large-Scale Multi-Domain Wizard-of-Oz Dataset for Task-Oriented Dialogue Modelling. EMNLP 2018, pp. 5016-5026\n",
- " 2. Cathy Pearl, Basic principles for designing voice user interfaces, https://www.oreilly.com/content/basic-principles-for-designing-voice-user-interfaces/ data dost\u0119pu: 21 marca 2021\n",
- " 3. Cathy Pearl, Designing Voice User Interfaces, Excerpts from Chapter 5: Advanced Voice User Interface Design, https://www.uxmatters.com/mt/archives/2018/01/designing-voice-user-interfaces.php data dost\u0119pu: 21 marca 2021"
+ " 1. Pawel Budzianowski, Tsung-Hsien Wen, Bo-Hsiang Tseng, Iñigo Casanueva, Stefan Ultes, Osman Ramadan, Milica Gasic, MultiWOZ - A Large-Scale Multi-Domain Wizard-of-Oz Dataset for Task-Oriented Dialogue Modelling. EMNLP 2018, pp. 5016-5026\n",
+ " 2. Cathy Pearl, Basic principles for designing voice user interfaces, https://www.oreilly.com/content/basic-principles-for-designing-voice-user-interfaces/ data dostępu: 21 marca 2021\n",
+ " 3. Cathy Pearl, Designing Voice User Interfaces, Excerpts from Chapter 5: Advanced Voice User Interface Design, https://www.uxmatters.com/mt/archives/2018/01/designing-voice-user-interfaces.php data dostępu: 21 marca 2021"
]
}
],
"metadata": {
+ "author": "Marek Kubis",
+ "email": "mkubis@amu.edu.pl",
+ "interpreter": {
+ "hash": "91e2b0d1baa6ebb76863bdb1d11380bf032a6a1fc1b919194f041a5133852891"
+ },
"jupytext": {
"cell_metadata_filter": "-all",
"main_language": "python",
"notebook_metadata_filter": "-all"
},
- "author": "Marek Kubis",
- "email": "mkubis@amu.edu.pl",
+ "kernelspec": {
+ "display_name": "Python 3.7.9 ('venv': venv)",
+ "language": "python",
+ "name": "python3"
+ },
"lang": "pl",
- "subtitle": "9.Zarz\u0105dzanie dialogiem z wykorzystaniem regu\u0142[laboratoria]",
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.9"
+ },
+ "subtitle": "9.Zarządzanie dialogiem z wykorzystaniem reguł[laboratoria]",
"title": "Systemy Dialogowe",
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 4
-}
\ No newline at end of file
+}
diff --git a/lab/10-zarzadzanie-dialogiem-uczenie.ipynb b/lab/10-zarzadzanie-dialogiem-uczenie.ipynb
new file mode 100644
index 0000000..1d02d9c
--- /dev/null
+++ b/lab/10-zarzadzanie-dialogiem-uczenie.ipynb
@@ -0,0 +1,521 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": false
+ },
+ "source": [
+ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
+ "\n",
+ " Systemy Dialogowe \n",
+ " 10. Zarządzanie dialogiem z wykorzystaniem technik uczenia maszynowego [laboratoria] \n",
+ " Marek Kubis (2021)\n",
+ "\n",
+ "\n",
+ "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zarządzanie dialogiem z wykorzystaniem technik uczenia maszynowego\n",
+ "==================================================================\n",
+ "\n",
+ "Uczenie przez wzmacnianie\n",
+ "-------------------------\n",
+ "\n",
+ "Zamiast ręcznie implementować zbiór reguł odpowiedzialnych za wyznaczenie akcji, którą powinien podjąć agent będąc w danym stanie, odpowiednią taktykę prowadzenia dialogu można zbudować, wykorzystując techniki uczenia maszynowego.\n",
+ "\n",
+ "Obok metod uczenia nadzorowanego, które wykorzystaliśmy do zbudowania modelu NLU, do konstruowania taktyk\n",
+ "prowadzenia dialogu wykorzystuje się również *uczenie przez wzmacnianie* (ang. *reinforcement learning*).\n",
+ "\n",
+ "W tym ujęciu szukać będziemy funkcji $Q*: S \\times A \\to R$, która dla stanu dialogu $s \\in S$ oraz aktu\n",
+ "dialogowego $a \\in A$ zwraca nagrodę (ang. *reward*) $r \\in R$, tj. wartość rzeczywistą pozwalającą ocenić na ile\n",
+ "podjęcie akcji $a$ w stanie $s$ jest korzystne.\n",
+ "\n",
+ "Założymy również, że poszukiwana funkcja powinna maksymalizować *zwrot* (ang. *return*), tj.\n",
+ "skumulowaną nagrodę w toku prowadzonego dialogu, czyli dla tury $t_0$ cel uczenia powinien mieć postać:\n",
+ "\n",
+ "$$ \\sum_{t=t_0}^{\\infty}{\\gamma^{t-1}r_t} $$\n",
+ "\n",
+ "gdzie:\n",
+ "\n",
+ " - $t$: tura agenta,\n",
+ "\n",
+ " - $r_t$: nagroda w turze $t$,\n",
+ "\n",
+ " - $\\gamma \\in [0, 1]$: współczynnik dyskontowy (w przypadku agentów dialogowych bliżej $1$ niż $0$, por. np. Rieser i Lemon (2011))."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Agent dialogowy w procesie uczenia przez wzmacnianie wchodzi w interakcję ze *środowiskiem*, które\n",
+ "dla akcji podejmowanej przez taktykę prowadzenia dialogu zwraca kolejny stan oraz nagrodę powiązaną z\n",
+ "wykonaniem tej akcji w bieżącym stanie.\n",
+ "\n",
+ "Sposób w jaki informacje pochodzące ze środowiska są wykorzystywane do znalezienia funkcji $Q*$\n",
+ "zależy od wybranej metody uczenia.\n",
+ "W przykładzie przestawionym poniżej skorzystamy z algorytmu $DQN$ (Mnih i in., 2013) co oznacza, że:\n",
+ "\n",
+ " 1. będziemy aproksymować funkcję $Q*$ siecią neuronową,\n",
+ "\n",
+ " 2. wagi sieci będziemy wyznaczać korzystając z metody spadku gradientu.\n",
+ "\n",
+ "Przykład\n",
+ "--------\n",
+ "\n",
+ "Taktykę prowadzenia dialogu osadzimy w środowisku *ConvLab-2*."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ModuleNotFoundError",
+ "evalue": "No module named 'convlab2'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32mc:\\Develop\\wmi\\AITECH\\sem1\\Systemy dialogowe\\lab\\10-zarzadzanie-dialogiem-uczenie.ipynb Cell 4'\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mconvlab2\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mdialog_agent\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39magent\u001b[39;00m \u001b[39mimport\u001b[39;00m PipelineAgent\n\u001b[0;32m 2\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mconvlab2\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mdialog_agent\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39menv\u001b[39;00m \u001b[39mimport\u001b[39;00m Environment\n\u001b[0;32m 3\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mconvlab2\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mdst\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mrule\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mmultiwoz\u001b[39;00m \u001b[39mimport\u001b[39;00m RuleDST\n",
+ "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'convlab2'"
+ ]
+ }
+ ],
+ "source": [
+ "from convlab2.dialog_agent.agent import PipelineAgent\n",
+ "from convlab2.dialog_agent.env import Environment\n",
+ "from convlab2.dst.rule.multiwoz import RuleDST\n",
+ "from convlab2.policy.rule.multiwoz import RulePolicy\n",
+ "from convlab2.policy.dqn import DQN\n",
+ "from convlab2.policy.rlmodule import Memory\n",
+ "from convlab2.evaluator.multiwoz_eval import MultiWozEvaluator\n",
+ "import logging\n",
+ "\n",
+ "logging.disable(logging.DEBUG)\n",
+ "\n",
+ "# determinizacja obliczeń\n",
+ "import random\n",
+ "import torch\n",
+ "import numpy as np\n",
+ "\n",
+ "np.random.seed(123)\n",
+ "random.seed(123)\n",
+ "torch.manual_seed(123)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Środowisko, z którym agent będzie wchodził w interakcje zawierać będzie\n",
+ "symulator użytkownika wykorzystujący taktykę prowadzenia dialogu zbudowaną z wykorzystaniem reguł."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "usr_policy = RulePolicy(character='usr')\n",
+ "usr_simulator = PipelineAgent(None, None, usr_policy, None, 'user') # type: ignore\n",
+ "\n",
+ "dst = RuleDST()\n",
+ "evaluator = MultiWozEvaluator()\n",
+ "env = Environment(None, usr_simulator, None, dst, evaluator)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zobaczmy jak w *ConvLab-2* zdefiniowana jest nagroda w klasie `Environment`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%script false --no-raise-error\n",
+ "#\n",
+ "# plik convlab2/dialog_agent/env.py\n",
+ "#\n",
+ "class Environment():\n",
+ "\n",
+ " # (...)\n",
+ "\n",
+ " def step(self, action):\n",
+ "\n",
+ " # (...)\n",
+ "\n",
+ " if self.evaluator:\n",
+ " if self.evaluator.task_success():\n",
+ " reward = 40\n",
+ " elif self.evaluator.cur_domain and self.evaluator.domain_success(self.evaluator.cur_domain):\n",
+ " reward = 5\n",
+ " else:\n",
+ " reward = -1\n",
+ " else:\n",
+ " reward = self.usr.get_reward()\n",
+ " terminated = self.usr.is_terminated()\n",
+ "\n",
+ " return state, reward, terminated\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jak można zauważyć powyżej akcja, która prowadzi do pomyślnego zakończenia zadania uzyskuje nagrodę $40$,\n",
+ "akcja która prowadzi do prawidłowego rozpoznania dziedziny uzyskuje nagrodę $5$,\n",
+ "natomiast każda inna akcja uzyskuje \"karę\" $-1$. Taka definicja zwrotu premiuje krótkie dialogi\n",
+ "prowadzące do pomyślnego wykonania zadania.\n",
+ "\n",
+ "Sieć neuronowa, którą wykorzystamy do aproksymacji funkcji $Q*$ ma następującą architekturę"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%script false --no-raise-error\n",
+ "#\n",
+ "# plik convlab2/policy/rlmodule.py\n",
+ "# klasa EpsilonGreedyPolicy wykorzystywana w DQN\n",
+ "#\n",
+ "class EpsilonGreedyPolicy(nn.Module):\n",
+ " def __init__(self, s_dim, h_dim, a_dim, epsilon_spec={'start': 0.1, 'end': 0.0, 'end_epoch': 200}):\n",
+ " super(EpsilonGreedyPolicy, self).__init__()\n",
+ "\n",
+ " self.net = nn.Sequential(nn.Linear(s_dim, h_dim),\n",
+ " nn.ReLU(),\n",
+ " nn.Linear(h_dim, h_dim),\n",
+ " nn.ReLU(),\n",
+ " nn.Linear(h_dim, a_dim))\n",
+ " # (...)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "policy = DQN(is_train=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Każdy krok procedury uczenia składa się z dwóch etapów:\n",
+ "\n",
+ " 1. Wygenerowania przy użyciu taktyki (metoda `policy.predict`) oraz środowiska (metoda `env.step`) *trajektorii*, tj. sekwencji przejść pomiędzy stanami złożonych z krotek postaci:\n",
+ " - stanu źródłowego,\n",
+ " - podjętej akcji (aktu systemowego),\n",
+ " - nagrody,\n",
+ " - stanu docelowego,\n",
+ " - znacznika końca dialogu."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# por. ConvLab-2/convlab2/policy/dqn/train.py\n",
+ "def sample(env, policy, batch_size, warm_up):\n",
+ " buff = Memory()\n",
+ " sampled_num = 0\n",
+ " max_trajectory_len = 50\n",
+ "\n",
+ " while sampled_num < batch_size:\n",
+ " # rozpoczęcie nowego dialogu\n",
+ " s = env.reset()\n",
+ "\n",
+ " for t in range(max_trajectory_len):\n",
+ " try:\n",
+ " # podjęcie akcji przez agenta dialogowego\n",
+ " a = policy.predict(s, warm_up=warm_up)\n",
+ "\n",
+ " # odpowiedź środowiska na podjętą akcje\n",
+ " next_s, r, done = env.step(a)\n",
+ "\n",
+ " # dodanie krotki do zbioru danych\n",
+ " buff.push(torch.Tensor(policy.vector.state_vectorize(s)).numpy(), # stan źródłowy\n",
+ " policy.vector.action_vectorize(a), # akcja\n",
+ " r, # nagroda\n",
+ " torch.Tensor(policy.vector.state_vectorize(next_s)).numpy(), # stan docelowy\n",
+ " 0 if done else 1) # znacznik końca\n",
+ "\n",
+ " s = next_s\n",
+ "\n",
+ " if done:\n",
+ " break\n",
+ " except:\n",
+ " break\n",
+ "\n",
+ " sampled_num += t\n",
+ "\n",
+ " return buff"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " 2. Wykorzystania wygenerowanych krotek do aktualizacji taktyki.\n",
+ "\n",
+ "Funkcja `train` realizująca pojedynczy krok uczenia przez wzmacnianie ma następującą postać"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def train(env, policy, batch_size, epoch, warm_up):\n",
+ " print(f'epoch: {epoch}')\n",
+ " buff = sample(env, policy, batch_size, warm_up)\n",
+ " policy.update_memory(buff)\n",
+ " policy.update(epoch)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Metoda `update` klasy `DQN` wykorzystywana do aktualizacji wag ma następującą postać"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%%script false --no-raise-error\n",
+ "#\n",
+ "# plik convlab2/policy/dqn/dqn.py\n",
+ "# klasa DQN\n",
+ "#\n",
+ "class DQN(Policy):\n",
+ " # (...)\n",
+ " def update(self, epoch):\n",
+ " total_loss = 0.\n",
+ " for i in range(self.training_iter):\n",
+ " round_loss = 0.\n",
+ " # 1. batch a sample from memory\n",
+ " batch = self.memory.get_batch(batch_size=self.batch_size)\n",
+ "\n",
+ " for _ in range(self.training_batch_iter):\n",
+ " # 2. calculate the Q loss\n",
+ " loss = self.calc_q_loss(batch)\n",
+ "\n",
+ " # 3. make a optimization step\n",
+ " self.net_optim.zero_grad()\n",
+ " loss.backward()\n",
+ " self.net_optim.step()\n",
+ "\n",
+ " round_loss += loss.item()\n",
+ "\n",
+ " # (...)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Przebieg procesu uczenia zilustrujemy wykonując 100 iteracji. W każdej iteracji ograniczymy się do 100 przykładów."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "epoch = 100\n",
+ "batch_size = 100\n",
+ "\n",
+ "train(env, policy, batch_size, 0, warm_up=True)\n",
+ "\n",
+ "for i in range(1, epoch):\n",
+ " train(env, policy, batch_size, i, warm_up=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Sprawdźmy jakie akty systemowe zwraca taktyka `DQN` w odpowiedzi na zmieniający się stan dialogu."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "from convlab2.dialog_agent import PipelineAgent\n",
+ "dst.init_session()\n",
+ "agent = PipelineAgent(nlu=None, dst=dst, policy=policy, nlg=None, name='sys')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Price', 'cheap'], ['Inform', 'Hotel', 'Parking', 'yes']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Area', 'north']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "agent.response([['Request', 'Hotel', 'Area', '?']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "agent.response([['Inform', 'Hotel', 'Day', 'tuesday'], ['Inform', 'Hotel', 'People', '2'], ['Inform', 'Hotel', 'Stay', '4']])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jakość wyuczonego modelu możemy ocenić mierząc tzw. wskaźnik sukcesu (ang. *task success rate*),\n",
+ "tj. stosunek liczby dialogów zakończonych powodzeniem do liczby wszystkich dialogów."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from convlab2.dialog_agent.session import BiSession\n",
+ "\n",
+ "sess = BiSession(agent, usr_simulator, None, evaluator)\n",
+ "dialog_num = 100\n",
+ "task_success_num = 0\n",
+ "max_turn_num = 50\n",
+ "\n",
+ "# por. ConvLab-2/convlab2/policy/evaluate.py\n",
+ "for dialog in range(dialog_num):\n",
+ " random.seed(dialog)\n",
+ " np.random.seed(dialog)\n",
+ " torch.manual_seed(dialog)\n",
+ " sess.init_session()\n",
+ " sys_act = []\n",
+ " task_success = 0\n",
+ "\n",
+ " for _ in range(max_turn_num):\n",
+ " sys_act, _, finished, _ = sess.next_turn(sys_act)\n",
+ "\n",
+ " if finished is True:\n",
+ " task_success = sess.evaluator.task_success()\n",
+ " break\n",
+ "\n",
+ " print(f'dialog: {dialog:02} success: {task_success}')\n",
+ " task_success_num += task_success\n",
+ "\n",
+ "print('')\n",
+ "print(f'task success rate: {task_success_num/dialog_num:.2f}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Uwaga**: Chcąc uzyskać taktykę o skuteczności porównywalnej z wynikami przedstawionymi na stronie\n",
+ "[ConvLab-2](https://github.com/thu-coai/ConvLab-2/blob/master/README.md) trzeba odpowiednio\n",
+ "zwiększyć zarówno liczbę iteracji jak i liczbę przykładów generowanych w każdym przyroście.\n",
+ "W celu przyśpieszenia procesu uczenia warto zrównoleglić obliczenia, jak pokazano w\n",
+ "skrypcie [train.py](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/policy/dqn/train.py).\n",
+ "\n",
+ "Literatura\n",
+ "----------\n",
+ " 1. Rieser, V., Lemon, O., (2011). Reinforcement learning for adaptive dialogue systems: a data-driven methodology for dialogue management and natural language generation. (Theory and Applications of Natural Language Processing). Springer. https://doi.org/10.1007/978-3-642-24942-6\n",
+ "\n",
+ " 2. Richard S. Sutton and Andrew G. Barto, (2018). Reinforcement Learning: An Introduction, Second Edition, MIT Press, Cambridge, MA http://incompleteideas.net/book/RLbook2020.pdf\n",
+ "\n",
+ " 3. Volodymyr Mnih and Koray Kavukcuoglu and David Silver and Alex Graves and Ioannis Antonoglou and Daan Wierstra and Martin Riedmiller, (2013). Playing Atari with Deep Reinforcement Learning, NIPS Deep Learning Workshop, https://arxiv.org/pdf/1312.5602.pdf"
+ ]
+ }
+ ],
+ "metadata": {
+ "author": "Marek Kubis",
+ "email": "mkubis@amu.edu.pl",
+ "interpreter": {
+ "hash": "2f9d6cf1e3d8195079a65c851de355134a77367bcd714b1a5d498c42d3c07114"
+ },
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.8.3 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "lang": "pl",
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.3"
+ },
+ "subtitle": "10.Zarządzanie dialogiem z wykorzystaniem technik uczenia maszynowego[laboratoria]",
+ "title": "Systemy Dialogowe",
+ "year": "2021"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/lab/11-generowanie-odpowiedzi.ipynb b/lab/11-generowanie-odpowiedzi.ipynb
new file mode 100644
index 0000000..20c19d2
--- /dev/null
+++ b/lab/11-generowanie-odpowiedzi.ipynb
@@ -0,0 +1,433 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
+ " \n",
+ " Systemy Dialogowe \n",
+ " 11. Generowanie odpowiedzi [laboratoria] \n",
+ " Marek Kubis (2021)\n",
+ "\n",
+ "\n",
+ "![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Generowanie odpowiedzi\n",
+ "======================\n",
+ "\n",
+ "W systemie dialogowym taktyka prowadzenia dialogu odpowiada za wyznaczanie aktów systemowych, czyli wskazanie tego **co ma zostać przez system wypowiedziane** i/lub wykonane.\n",
+ "Zadaniem modułu generowania odpowiedzi jest zamiana aktów dialogowych na wypowiedzi w języku\n",
+ "naturalnym, czyli wskazanie tego **w jaki sposób** ma zostać wypowiedziane to co ma zostać\n",
+ "wypowiedziane.\n",
+ "\n",
+ "Generowanie odpowiedzi przy użyciu szablonów\n",
+ "--------------------------------------------\n",
+ "Podstawowe narzędzie wykorzystywane w modułach generowania odpowiedzi stanowią szablony tekstowe\n",
+ "interpolujące zmienne. W Pythonie mechanizm ten jest dostępny za pośrednictwem\n",
+ "[f-stringów](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), metody\n",
+ "[format](https://docs.python.org/3/library/string.html#formatstrings) oraz zewnętrznych bibliotek takich, jak [Jinja2](https://jinja.palletsprojects.com/).\n",
+ "\n",
+ "O ile podejście wykorzystujące wbudowane mechanizmy języka Python sprawdza się w prostych\n",
+ "przypadkach..."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "def nlg(system_act):\n",
+ " domain, intent, slot, value = system_act\n",
+ "\n",
+ " if intent == 'Inform' and slot == 'Phone':\n",
+ " return f'Numer telefonu to {value}'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nlg(['Hotel', 'Inform', 'Phone', '1234567890'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "source": [
+ "... to trzeba mieć świadomość, że w toku prac nad agentem dialogowym może być konieczne\n",
+ "uwzględnienie m.in.:\n",
+ "\n",
+ " 1. szablonów zależnych od wartości slotów"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "def nlg(system_act):\n",
+ " domain, intent, slot, value = system_act\n",
+ "\n",
+ " if domain == 'Restaurant' and intent == 'Inform' and slot == 'Count':\n",
+ " if value == 0:\n",
+ " return f'Nie znalazłem restauracji spełniających podane kryteria.'\n",
+ " elif value == 1:\n",
+ " return f'Znalazłem jedną restaurację spełniającą podane kryteria.'\n",
+ " elif value <= 4:\n",
+ " return f'Znalazłem {value} restauracje spełniające podane kryteria.'\n",
+ " elif value <= 9:\n",
+ " return f'Znalazłem {value} restauracji spełniających podane kryteria.'\n",
+ " else:\n",
+ " return f'Znalazłem wiele restauracji spełniających podane kryteria.'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "nlg(['Restaurant', 'Inform', 'Count', 0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "nlg(['Restaurant', 'Inform', 'Count', 1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "nlg(['Restaurant', 'Inform', 'Count', 2])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "nlg(['Restaurant', 'Inform', 'Count', 6])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nlg(['Restaurant', 'Inform', 'Count', 100])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "source": [
+ " 2. wielu wariantów tej samej wypowiedzi"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "import random\n",
+ "\n",
+ "def nlg(system_act):\n",
+ " domain, intent, slot, value = system_act\n",
+ "\n",
+ " if intent == 'Affirm':\n",
+ " r = random.randint(1, 3)\n",
+ "\n",
+ " if r == 1:\n",
+ " return 'Tak'\n",
+ " elif r == 2:\n",
+ " return 'Zgadza się'\n",
+ " else:\n",
+ " return 'Potwierdzam'\n",
+ "\n",
+ "nlg(['Hotel', 'Affirm', '', ''])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "source": [
+ " 3. wielojęzycznego interfejsu użytkownika"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "outputs": [],
+ "source": [
+ "def nlg_en(system_act):\n",
+ " domain, intent, slot, value = system_act\n",
+ "\n",
+ " if domain == 'Hotel' and intent == 'Request' and slot == 'CreditCardNo':\n",
+ " return 'What is your credit card number?'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nlg_en(['Hotel', 'Request', 'CreditCardNo', '?'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "lines_to_next_cell": 0
+ },
+ "source": [
+ "Generowanie odpowiedzi z wykorzystaniem uczenia maszynowego\n",
+ "-----------------------------------------------------------\n",
+ "Obok mechanizmu szablonów do generowania odpowiedzi można również\n",
+ "stosować techniki uczenia maszynowego.\n",
+ "Zagadnienie to stanowiło\n",
+ "przedmiot konkursu [E2E NLG Challenge](http://www.macs.hw.ac.uk/InteractionLab/E2E/) (Novikova i in., 2017).\n",
+ "Przyjrzyjmy się danym, jakie udostępnili organizatorzy."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!mkdir -p l10\n",
+ "!curl -L -C - https://github.com/tuetschek/e2e-dataset/releases/download/v1.0.0/e2e-dataset.zip -o l10/e2e-dataset.zip\n",
+ "!unzip l10/e2e-dataset.zip -d l10"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "\n",
+ "trainset = pd.read_csv('l10/e2e-dataset/trainset.csv')\n",
+ "trainset"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zadanie\n",
+ "-------\n",
+ "Zaimplementować moduł generowania odpowiedzi obejmujący akty systemowe występujące w zgromadzonym korpusie.\n",
+ "\n",
+ "Termin: 1.06.2022, godz. 23:59.\n",
+ "\n",
+ "Literatura\n",
+ "----------\n",
+ " 1. 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"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "df = pd.read_csv('../data/dialog-17-04-03.tsv', sep='\\t', header=None)\n",
+ "df.columns = ['user','text','data']\n",
+ "df= df[df.user=='system']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.drop(axis=1, labels=['user'], inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " | \n",
+ " user | \n",
+ " text | \n",
+ " data | \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 1 | \n",
+ " system | \n",
+ " Witamy w internetowym systemie rezerwacji Nach... | \n",
+ " welcomemsg() | \n",
+ " \n",
+ " \n",
+ " 3 | \n",
+ " system | \n",
+ " System Nachos obsługuje następujące kina: Mult... | \n",
+ " select(location) | \n",
+ " \n",
+ " \n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ " user text data\n",
+ "1 system Witamy w internetowym systemie rezerwacji Nach... welcomemsg()\n",
+ "3 system System Nachos obsługuje następujące kina: Mult... select(location)"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def nlg(system_act):\n",
+ " intent, slot, value = system_act\n",
+ "\n",
+ " if intent=='welcomemsg':\n",
+ " return 'Witamy w internetowym systemie rezerwacji Nachos, w czym mogę pomóc?'\n",
+ " elif intent=='inform':\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " if domain == 'Restaurant' and intent == 'Inform' and slot == 'Count':\n",
+ " if value == 0:\n",
+ " return f'Nie znalazłem restauracji spełniających podane kryteria.'\n",
+ " elif value == 1:\n",
+ " return f'Znalazłem jedną restaurację spełniającą podane kryteria.'\n",
+ " elif value <= 4:\n",
+ " return f'Znalazłem {value} restauracje spełniające podane kryteria.'\n",
+ " elif value <= 9:\n",
+ " return f'Znalazłem {value} restauracji spełniających podane kryteria.'\n",
+ " else:\n",
+ " return f'Znalazłem wiele restauracji spełniających podane kryteria.'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inform(quantity=2) AND inform(time=12:00)\n",
+ "['inform','quantity','2']"
+ ]
+ }
+ ],
+ "metadata": {
+ "author": "Marek Kubis",
+ "email": "mkubis@amu.edu.pl",
+ "jupytext": {
+ "cell_metadata_filter": "-all",
+ "main_language": "python",
+ "notebook_metadata_filter": "-all"
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "lang": "pl",
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.10"
+ },
+ "subtitle": "11.Generowanie odpowiedzi[laboratoria]",
+ "title": "Systemy Dialogowe",
+ "year": "2021"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/lab/utils/state.py b/lab/utils/state.py
new file mode 100644
index 0000000..fa9f63e
--- /dev/null
+++ b/lab/utils/state.py
@@ -0,0 +1,25 @@
+def default_state():
+ state = dict(user_action=[],
+ system_action=[],
+ belief_state={},
+ request_state={},
+ terminated=False,
+ history=[])
+ state['belief_state'] = {
+ "cinema": {
+ "book": {
+ "title": "",
+ "date": "",
+ "time": "",
+ "quantity": "",
+ "seats": "",
+ "area": "",
+ "interval": "",
+ },
+ "semi": {
+ "goal": ""
+ }
+ },
+
+ }
+ return state
diff --git a/lab/utils/value_dict.json b/lab/utils/value_dict.json
new file mode 100644
index 0000000..ce6888b
--- /dev/null
+++ b/lab/utils/value_dict.json
@@ -0,0 +1,507 @@
+{
+ "train": {
+ "time": [
+ "05:51",
+ "07:51",
+ "09:51",
+ "11:51",
+ "13:51",
+ "15:51",
+ "17:51",
+ "19:51",
+ "21:51",
+ "23:51",
+ "06:08",
+ "08:08",
+ "10:08",
+ "12:08",
+ "14:08",
+ "16:08",
+ "18:08",
+ "20:08",
+ "22:08",
+ "24:08",
+ "07:27",
+ "09:27",
+ "11:27",
+ "13:27",
+ "15:27",
+ "17:27",
+ "19:27",
+ "21:27",
+ "23:27",
+ "01:27",
+ "07:07",
+ "09:07",
+ "11:07",
+ "13:07",
+ "15:07",
+ "17:07",
+ "19:07",
+ "21:07",
+ "23:07",
+ "01:07",
+ "05:58",
+ "06:58",
+ "07:58",
+ "08:58",
+ "09:58",
+ "10:58",
+ "11:58",
+ "12:58",
+ "13:58",
+ "14:58",
+ "15:58",
+ "16:58",
+ "17:58",
+ "18:58",
+ "19:58",
+ "20:58",
+ "21:58",
+ "22:58",
+ "23:58",
+ "06:55",
+ "07:55",
+ "08:55",
+ "09:55",
+ "10:55",
+ "11:55",
+ "12:55",
+ "13:55",
+ "14:55",
+ "15:55",
+ "16:55",
+ "17:55",
+ "18:55",
+ "19:55",
+ "20:55",
+ "21:55",
+ "22:55",
+ "23:55",
+ "24:55",
+ "06:35",
+ "07:35",
+ "08:35",
+ "09:35",
+ "10:35",
+ "11:35",
+ "12:35",
+ "13:35",
+ "14:35",
+ "15:35",
+ "16:35",
+ "17:35",
+ "18:35",
+ "19:35",
+ "20:35",
+ "21:35",
+ "22:35",
+ "23:35",
+ "24:35",
+ "05:56",
+ "06:24",
+ "06:56",
+ "07:24",
+ "07:56",
+ "08:24",
+ "08:56",
+ "09:24",
+ "09:56",
+ "10:24",
+ "10:56",
+ "11:24",
+ "11:56",
+ "12:24",
+ "12:56",
+ "13:24",
+ "13:56",
+ "14:24",
+ "14:56",
+ "15:24",
+ "15:56",
+ "16:24",
+ "16:56",
+ "17:24",
+ "17:56",
+ "18:24",
+ "18:56",
+ "19:24",
+ "19:56",
+ "20:24",
+ "20:56",
+ "21:24",
+ "21:56",
+ "22:24",
+ "22:56",
+ "23:24",
+ "23:56",
+ "24:24",
+ "06:09",
+ "06:38",
+ "07:09",
+ "07:38",
+ "08:09",
+ "08:38",
+ "09:09",
+ "09:38",
+ "10:09",
+ "10:38",
+ "11:09",
+ "11:38",
+ "12:09",
+ "12:38",
+ "13:09",
+ "13:38",
+ "14:09",
+ "14:38",
+ "15:09",
+ "15:38",
+ "16:09",
+ "16:38",
+ "17:09",
+ "17:38",
+ "18:09",
+ "18:38",
+ "19:09",
+ "19:38",
+ "20:09",
+ "20:38",
+ "21:09",
+ "21:38",
+ "22:09",
+ "22:38",
+ "23:09",
+ "23:38",
+ "24:09",
+ "24:38",
+ "06:07",
+ "08:07",
+ "10:07",
+ "12:07",
+ "14:07",
+ "16:07",
+ "18:07",
+ "20:07",
+ "22:07",
+ "24:07",
+ "05:52",
+ "07:52",
+ "09:52",
+ "11:52",
+ "13:52",
+ "15:52",
+ "17:52",
+ "19:52",
+ "21:52",
+ "23:52",
+ "07:08",
+ "09:08",
+ "11:08",
+ "13:08",
+ "15:08",
+ "17:08",
+ "19:08",
+ "21:08",
+ "23:08",
+ "06:52",
+ "08:52",
+ "10:52",
+ "12:52",
+ "14:52",
+ "16:52",
+ "18:52",
+ "20:52",
+ "22:52",
+ "07:06",
+ "08:06",
+ "09:06",
+ "10:06",
+ "11:06",
+ "12:06",
+ "13:06",
+ "14:06",
+ "15:06",
+ "16:06",
+ "17:06",
+ "18:06",
+ "19:06",
+ "20:06",
+ "21:06",
+ "22:06",
+ "23:06",
+ "24:06",
+ "01:06",
+ "06:54",
+ "07:54",
+ "08:54",
+ "09:54",
+ "10:54",
+ "11:54",
+ "12:54",
+ "13:54",
+ "14:54",
+ "15:54",
+ "16:54",
+ "17:54",
+ "18:54",
+ "19:54",
+ "20:54",
+ "21:54",
+ "22:54",
+ "23:54",
+ "24:54",
+ "07:44",
+ "08:44",
+ "09:44",
+ "10:44",
+ "11:44",
+ "12:44",
+ "13:44",
+ "14:44",
+ "15:44",
+ "16:44",
+ "17:44",
+ "18:44",
+ "19:44",
+ "20:44",
+ "21:44",
+ "22:44",
+ "23:44",
+ "24:44",
+ "01:44",
+ "08:23",
+ "09:23",
+ "10:23",
+ "11:23",
+ "12:23",
+ "13:23",
+ "14:23",
+ "15:23",
+ "16:23",
+ "17:23",
+ "18:23",
+ "19:23",
+ "20:23",
+ "21:23",
+ "22:23",
+ "23:23",
+ "24:23",
+ "01:23",
+ "02:23",
+ "06:01",
+ "07:01",
+ "08:01",
+ "09:01",
+ "10:01",
+ "11:01",
+ "12:01",
+ "13:01",
+ "14:01",
+ "15:01",
+ "16:01",
+ "17:01",
+ "18:01",
+ "19:01",
+ "20:01",
+ "21:01",
+ "22:01",
+ "23:01",
+ "24:01",
+ "06:32",
+ "07:32",
+ "08:32",
+ "09:32",
+ "10:32",
+ "11:32",
+ "12:32",
+ "13:32",
+ "14:32",
+ "15:32",
+ "16:32",
+ "17:32",
+ "18:32",
+ "19:32",
+ "20:32",
+ "21:32",
+ "22:32",
+ "23:32",
+ "24:32",
+ "06:10",
+ "08:10",
+ "10:10",
+ "12:10",
+ "14:10",
+ "16:10",
+ "18:10",
+ "20:10",
+ "22:10",
+ "24:10",
+ "06:43",
+ "08:43",
+ "10:43",
+ "12:43",
+ "14:43",
+ "16:43",
+ "18:43",
+ "20:43",
+ "22:43",
+ "24:43",
+ "pierwszą",
+ "drugą",
+ "trzecią",
+ "piątą",
+ "szóstą",
+ "siódmą",
+ "ósmą",
+ "dziewiatą",
+ "dziesiątą",
+ "jedenastą",
+ "dwunastą",
+ "trzynastą",
+ "czternastą",
+ "piętnastą",
+ "szesnastą",
+ "siedemnastą",
+ "osiemnastą",
+ "dziewiętnastą",
+ "dwudziestą pierwszą",
+ "dwudziestą drugą",
+ "dwudziestą trzecią",
+ "dwudziestą czwartą",
+ "o północy"
+ ],
+ "date": [
+ "w najbliższy poniedziałek",
+ "w najbliższy wtorek",
+ "w najbliższą środę",
+ "w najbliższy czwartek",
+ "w najbliższy piątek",
+ "w najbliższą sobotę",
+ "w najbliższą niedzielę",
+ "w poniedziałek",
+ "we wtorek",
+ "w środę",
+ "w czwartek",
+ "w piątek",
+ "w sobotę",
+ "w niedzielę",
+ "na najbliższy poniedziałek",
+ "na najbliższy wtorek",
+ "na najbliższą środę",
+ "na najbliższy czwartek",
+ "na najbliższy piątek",
+ "na najbliższą sobotę",
+ "na najbliższą niedzielę",
+ "najbliższy poniedziałek",
+ "najbliższy wtorek",
+ "najbliższa środa",
+ "najbliższy czwartek",
+ "najbliższy piątek",
+ "najbliższa sobota",
+ "najbliższa niedziela",
+ "na jutro",
+ "jutro",
+ "w dniu jutrzejszym",
+ "po jutrze",
+ "pojutrze",
+ "za dwa dni",
+ "za trzy dni",
+ "za tydzień",
+ "dzisiaj",
+ "dziś",
+ "na dzień 21/09",
+ "na 21/09",
+ "dzień 21/09",
+ "dnia 21/09",
+ "21/09",
+ "12/09",
+ "5/09",
+ "21/12",
+ "12/12",
+ "5/12",
+ "21/3",
+ "12/3",
+ "5/3"
+ ],
+ "quantities" : [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "jeden",
+ "dwa",
+ "trzy",
+ "cztery",
+ "pięć",
+ "sześć",
+ "siedem",
+ "osiem",
+ "dziewięć",
+ "dziesięć",
+ "jedenaście",
+ "dwanaście",
+ "trzynaście"
+ ],
+ "seats" : [
+ "a1",
+ "a1 a2",
+ "a1 a2 a3",
+ "a1 a2 a3 a4",
+ "a1 a2 a3 a4 a5",
+ "h1",
+ "h1 h2",
+ "h1 h2 h3",
+ "h1 h2 h3 h4",
+ "h1 h2 h3 h4 h5",
+ "a12",
+ "a11 a12",
+ "a11 a12 a13",
+ "a11 a12 a13 a14",
+ "a11 a12 a13 a14 a15"
+ ],
+ "areas" : [
+ "u góry po prawej",
+ "u góry po lewej",
+ "u góry na środku",
+ "na środku po prawej",
+ "na środku po lewej",
+ "na dole po prawej",
+ "na dole po lewej",
+ "na dole na środku",
+ "po lewej",
+ "po prawej",
+ "na środku",
+ "lewo",
+ "prawo",
+ "środek",
+ "blisko od ekranu",
+ "daleko od ekranu",
+ "blisko ekranu",
+ "daleko ekranu"
+ ],
+ "interval" : [
+ "rano",
+ "wieczorem",
+ "w południe",
+ "po południu",
+ "popołudniu",
+ "w nocy"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/components/DP.py b/src/components/DP.py
index 7f5feed..927e69d 100644
--- a/src/components/DP.py
+++ b/src/components/DP.py
@@ -1,11 +1,31 @@
-# Martyna
+from urllib import request
+
+
class DP:
- def __init__(self, slots):
- self.slots = slots
+ def __init__(self):
+ pass
- def getAct(slots):
- # iterate over slots
- # find empty
- # returns system act
- pass
\ No newline at end of file
+ def getAction(self, lastUserAct, emptySlots, systemSlots):
+ systemAct = None
+ slotVal = None
+ if ((lastUserAct == "hello") | (lastUserAct == "inform") | (lastUserAct == None)):
+ # there are no empty slots
+ if not emptySlots:
+ systemAct = "inform"
+ slotVal = systemSlots
+ # there are empty slots
+ else:
+ for slot in systemSlots:
+ if slot in emptySlots:
+ systemAct = "request"
+ slotVal = slot
+ break
+ return ["Cinema", systemAct, slotVal, ""]
+ elif (lastUserAct == "request"):
+ # todo policy for user request
+ return ["Cinema", "", "", ""]
+ else:
+ systemAct = "repeat"
+ return ["Cinema", systemAct, "", ""]
+
\ No newline at end of file
diff --git a/src/components/DST.py b/src/components/DST.py
index 1e99228..1699122 100644
--- a/src/components/DST.py
+++ b/src/components/DST.py
@@ -1,22 +1,87 @@
-# Adrian
class DST:
- def __init__(self, slots):
- self.slots = slots
- def getDialogueState(self, userActs):
- # iterate over speech acts
- if userActs['act'] == 'book':
- if userActs['slots']:
- for (k, v) in userActs['slots']:
- print(k)
- if k in self.slots:
- self.slots[k] = v
+ def __init__(self):
+ self.init_session()
+ # self.value_dict = json.load(open('utils/value_dict.json'))
- # returns all slots
- return self.slots
+ def update(self, user_act=None):
+ intentVal = None
+ for intent, domain, slot, value in user_act:
+ domain = domain.lower()
+ intent = intent.lower()
+ value = value.lower()
+
+ if intentVal is None : intentVal = intent
+ k = slot
-#dst = DST()
-# userActs = {'inform': {'name': 'edyta', 'age': 18}, 'reqmore': {'date', 'time'}}
-#ivona_acts = {'act': 'book', 'slots': [('name', 'ewa'), ('hour', 'dziesiąta'), ('size', 'trzech')]}
-#print(dst.getDialogueState(ivona_acts))
+ if intent == 'inform':
+
+ domain_dic = self.state['belief_state'][domain]
+
+ if k in domain_dic['semi']:
+ self.state['belief_state'][domain]['semi'][k] = value
+ elif k in domain_dic['book']:
+ self.state['belief_state'][domain]['book'][k] = value
+ elif k.lower() in domain_dic['book']:
+ self.state['belief_state'][domain]['book'][k.lower()] = value
+ elif intent == 'reqmore':
+
+ if domain not in self.state['request_state']:
+ self.state['request_state'][domain] = {}
+ if k not in self.state['request_state'][domain]:
+ self.state['request_state'][domain][k] = 0
+ self.state['user_action'].append(intentVal)
+ return self.state
+
+ def addSystemAct(self, act):
+ self.state["system_action"].append(act)
+
+ def getLastUserAct(self):
+ try:
+ return self.state["user_action"][-1]
+ except:
+ return None
+
+ def getEmptySlots(self):
+ result = []
+ for key in self.state['belief_state']["cinema"]["book"].keys():
+ if self.state['belief_state']["cinema"]["book"][key] == "":
+ result.append(key)
+ return result
+
+ def getSystemSlots(self):
+ result = []
+ for key in self.state['belief_state']["cinema"]["book"].keys():
+ if key != "interval":
+ result.append(key)
+ return result
+
+ def init_session(self):
+ self.state = self.default_state()
+
+ def default_state(self):
+ state = dict(user_action=[],
+ system_action=[],
+ belief_state={},
+ request_state={},
+ terminated=False,
+ history=[])
+ state['belief_state'] = {
+ "cinema": {
+ "book": {
+ "title": "",
+ "date": "",
+ "time": "",
+ "quantity": "",
+ "seats": "",
+ "area": "",
+ "interval": "",
+ },
+ "semi": {
+ "goal": ""
+ }
+ },
+
+ }
+ return state
diff --git a/src/components/NLU.py b/src/components/NLU.py
index fd2665b..9c2f4e9 100644
--- a/src/components/NLU.py
+++ b/src/components/NLU.py
@@ -13,7 +13,7 @@ class NLU:
csentence = [{'form': word} for word in sentence]
fsentence = self.conllu2flair([csentence])[0]
self.nluModel.predict(fsentence)
- return [(token, ftoken.get_tag('slot').value) for token, ftoken in zip(sentence, fsentence)]
+ return self.toDSTInput([(token, ftoken.get_tag('slot').value) for token, ftoken in zip(sentence, fsentence)])
def conllu2flair(self, sentences, label=None):
fsentences = []
@@ -40,4 +40,34 @@ class NLU:
# new_str = re.sub(' +', ' ', new_str)
for char in punctuation:
messageLower = messageLower.replace(char,'')
- return messageLower.split()
\ No newline at end of file
+ return messageLower.split()
+
+ def toDSTInput(self, taggedSentence):
+ result = []
+ intent = None
+ slotValue = None
+ slot = None
+ for tuple in taggedSentence:
+ value, tagInt = tuple
+ if intent is None: intent = tagInt.split("/")[1]
+ if tagInt.split("/")[0] == "O":
+ if slotValue is not None:
+ result.append([intent, 'Cinema', slot, slotValue])
+ slot = None
+ slotValue = None
+ elif tagInt.split("/")[0].split("-")[0] == "B":
+ slot = tagInt.split("/")[0].split("-")[1]
+ slotValue = value
+ elif tagInt.split("/")[0].split("-")[0] == "I":
+ try:
+ slotValue += " " + value
+ except:
+ slot = tagInt.split("/")[0].split("-")[1]
+ slotValue = value
+
+ if slotValue is not None:
+ result.append([intent, 'Cinema', slot, slotValue])
+ return result
+
+
+
diff --git a/src/dialogue_system.py b/src/dialogue_system.py
index b8b6b50..41ca86e 100644
--- a/src/dialogue_system.py
+++ b/src/dialogue_system.py
@@ -1,17 +1,7 @@
from components.NLU import NLU
from components.NLG import NLG
from components.DST import DST
-
-slots = [
- ("title", None),
- ("date", None),
- ("time", None),
- ("quantity", None),
- ("seats", None),
- ("goal", None),
- ("area", None),
- ("interval", None),
-]
+from components.DP import DP
def chatbot():
@@ -19,6 +9,8 @@ def chatbot():
# NLU
nlu = NLU()
+ dst = DST()
+ dp = DP()
# hello message
print("wpisz /exit aby zakończyć")
@@ -32,5 +24,10 @@ def chatbot():
isActive = False
else:
nluPred = nlu.predict(sentence=userMessage)
- print(nluPred)
+ # print(nluPred)
+ dst.update(nluPred)
+ # print(dst.state)
+ dpAct = dp.getAction(dst.getLastUserAct(), dst.getEmptySlots(), dst.getSystemSlots())
+ print(dpAct)
+ # todo update DST system act
chatbot()
\ No newline at end of file
diff --git a/tasks/zad8/pl/intentClassification.py b/tasks/zad8/pl/intentClassification.py
new file mode 100644
index 0000000..b3932f9
--- /dev/null
+++ b/tasks/zad8/pl/intentClassification.py
@@ -0,0 +1,28 @@
+import pandas as pd
+
+def flatten(t):
+ return [item for sublist in t for item in sublist]
+
+def getData():
+ Xdata = []
+ Ydata = []
+ pathOut = './tasks/zad8/pl/'
+ pathIn = "./data/clean/"
+ i = 0
+ j = 0
+ nr = 0
+ for i in range(16,20):
+ for j in range(20):
+ for nr in range(1,5):
+ fileName = pathIn + "dialog-" + str(i).zfill(2) + "-" + str(j).zfill(2) + "-" + str(nr).zfill(2) + ".tsv"
+ try:
+ df = pd.read_csv(fileName, sep='\t', header=None, encoding="utf-8")
+ Xdata.append(df[1].tolist())
+ Ydata.append(df[2].tolist())
+ except:
+ pass
+ return flatten(Xdata), flatten(Ydata)
+
+x,y = getData()
+
+print(y)
\ No newline at end of file
diff --git a/tasks/zad8/pl/test.conllu b/tasks/zad8/pl/test.conllu
index 4674a20..5f2286c 100644
--- a/tasks/zad8/pl/test.conllu
+++ b/tasks/zad8/pl/test.conllu
@@ -19,9 +19,9 @@
# text: o której godzinie w piątek mogę zobaczyć na noże
# intent: reqmore inform
# slots: októrejgodzinie:goal,wpiątek:date,nanoże:title
-1 o reqmore inform B-goal
-2 której reqmore inform I-goal
-3 godzinie reqmore inform I-goal
+1 o reqmore inform B-time
+2 której reqmore inform I-time
+3 godzinie reqmore inform I-time
4 w reqmore inform NoLabel
5 piątek reqmore inform B-date
6 mogę reqmore inform NoLabel
@@ -237,11 +237,11 @@
# slots: 1:quantity
1 1 inform B-quantity
-# text: jakie sš dostępne ulgi
+# text: jakie są dostępne ulgi
# intent: nan
# slots:
1 jakie NoLabel
-2 sš NoLabel
+2 są NoLabel
3 dostępne NoLabel
4 ulgi NoLabel
diff --git a/tasks/zad8/pl/train.conllu b/tasks/zad8/pl/train.conllu
index 5f8e9ad..5b96485 100644
--- a/tasks/zad8/pl/train.conllu
+++ b/tasks/zad8/pl/train.conllu
@@ -561,12 +561,12 @@
2 potrafisz help NoLabel
# text: jakie są najbliższe seanse
-# intent: inform
+# intent: reqmore
# slots:
-1 jakie inform B-goal
-2 są inform I-goal
-3 najbliższe inform I-goal
-4 seanse inform I-goal
+1 jakie reqmore NoLabel
+2 są reqmore NoLabel
+3 najbliższe reqmore B-interval
+4 seanse reqmore NoLabel
# text: a jakie są dostępne
# intent: reqmore
@@ -729,7 +729,7 @@
5 grają reqmore NoLabel
6 jakieś reqmore NoLabel
7 stare reqmore NoLabel
-8 filmy reqmore NoLabel
+8 filmy reqmore B-title
# text: to dziękuję
# intent: thankyou
@@ -808,14 +808,14 @@
3 film inform NoLabel
# text: jakie filmy są teraz w kinach
-# intent: request
+# intent: reqmore
# slots: jakiefilmysą:goal
-1 jakie request B-goal
-2 filmy request I-goal
-3 są request I-goal
-4 teraz request NoLabel
-5 w request NoLabel
-6 kinach request NoLabel
+1 jakie reqmore B-goal
+2 filmy reqmore I-goal
+3 są reqmore I-goal
+4 teraz reqmore B-interval
+5 w reqmore NoLabel
+6 kinach reqmore NoLabel
# text: poproszę 3x bilet na ambulans
# intent: inform
@@ -1824,13 +1824,13 @@
# slots:
1 witam hello NoLabel
-# text: jakie sš najbliższe seanse
+# text: jakie są najbliższe seanse
# intent: reqmore
# slots: najbliższeseanse:goal
1 jakie reqmore NoLabel
-2 sš reqmore NoLabel
-3 najbliższe reqmore B-goal
-4 seanse reqmore I-goal
+2 są reqmore NoLabel
+3 najbliższe reqmore B-interval
+4 seanse reqmore B-goal
# text: w jakim to kinie
# intent: reqmore
@@ -2525,7 +2525,7 @@
1 niech ack NoLabel
2 będzie ack NoLabel
-# text: jakieś potwierdzenie rezerwacji dostanę czy mogę po prostu wejść i usišść
+# text: jakieś potwierdzenie rezerwacji dostanę czy mogę po prostu wejść i usiąść
# intent: request
# slots:
1 jakieś request NoLabel
@@ -2538,7 +2538,7 @@
8 prostu request NoLabel
9 wejść request NoLabel
10 i request NoLabel
-11 usišść request NoLabel
+11 usiąść request NoLabel
# text: wybieram batmana o 16:20
# intent: inform
@@ -2853,14 +2853,15 @@
2 filmy inform B-goal
3 są inform NoLabel
4 wieczorem inform B-interval
+
# text: co gracie za trzy dni
# intent: inform
# slots: zatrzydni:date
-1 co inform NoLabel
-2 gracie inform NoLabel
-3 za inform B-date
-4 trzy inform I-date
-5 dni inform I-date
+1 co reqmore NoLabel
+2 gracie reqmore NoLabel
+3 za reqmore B-date
+4 trzy reqmore I-date
+5 dni reqmore I-date
# text: co gracie za dwa dni
# intent: inform
@@ -2940,7 +2941,7 @@
4 moje inform NoLabel
5 miejsca inform NoLabel
6 to inform NoLabel
-7 h1h3h56 inform NoLabel
+7 h1h3h56 inform B-seats
# text: wymień seansy jutro
# intent: inform
| |