diff --git a/AJN.ipynb b/AJN.ipynb
new file mode 100644
index 0000000..8f87484
--- /dev/null
+++ b/AJN.ipynb
@@ -0,0 +1,303 @@
+{
+ "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",
+ " 7. Parsing semantyczny z wykorzystaniem gramatyk [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 gramatyk\n",
+ "=============================================\n",
+ "\n",
+ "Wartości slotów możemy wydobywać z wypowiedzi użytkownika korzystając z takich technik, jak:\n",
+ "\n",
+ " - wyszukiwanie słów kluczowych w tekście,\n",
+ "\n",
+ " - dopasowywanie wzorców zbudowanych przy użyciu wyrażeń regularnych,\n",
+ "\n",
+ " - parsery regułowe (temat dzisiejszych zajęć),\n",
+ "\n",
+ " - uczenie maszynowe (temat kolejnych zajęć)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Przykłady parserów regułowych\n",
+ "-----------------------------\n",
+ "\n",
+ " - [Phoenix](http://wiki.speech.cs.cmu.edu/olympus/index.php/Phoenix_Server) — parser gramatyk\n",
+ " bezkontekstowych whodzący w skład systemu dialogowego [Olympus](http://wiki.speech.cs.cmu.edu/olympus/index.php/Olympus)\n",
+ "\n",
+ " - Parsery [DCG](https://www.swi-prolog.org/pldoc/man?section=DCG) (Definite Clause Grammars) języka [Prolog](https://www.swi-prolog.org/)\n",
+ "\n",
+ " - [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) (JSGF)\n",
+ "\n",
+ "Przykład\n",
+ "--------\n",
+ "Zapiszmy w JSGF gramatykę semantyczną dla aktu dialogowego reprezentującego zamiar rezerwacji\n",
+ "stolika w restauracji."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Overwriting book.jsgf\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%writefile book.jsgf\n",
+ "#JSGF V1.0 UTF-8 pl;\n",
+ "\n",
+ "grammar book;\n",
+ "\n",
+ "public = chciałbym zarezerwować [] [];\n",
+ "\n",
+ " = {ilosc} (bilety | biletów);\n",
+ "\n",
+ " = dwa | trzy | cztery |1|2|3|4|5|6;\n",
+ "\n",
+ " = na [film] {tytul};\n",
+ "\n",
+ " = Batman | Uncharted | Pitbull;\n",
+ "\n",
+ " = na {dzien};\n",
+ "\n",
+ " = dzisiaj | jutro | poniedziałek | wtorek | środę | czwartek | piątek | sobotę | niedzielę;\n",
+ "\n",
+ " = na [godzinę] {godzina};\n",
+ "\n",
+ " = [];\n",
+ "\n",
+ " = dziewiątą | dziesiątą | jedenastą | dwunastą;\n",
+ "\n",
+ " = pietnaście | trzydzieści;\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Parser akceptujący powyższą gramatykę utworzymy korzystając z biblioteki [pyjsgf](https://github.com/Danesprite/pyjsgf)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Grammar(version=1.0, charset=UTF-8, language=pl, name=book)"
+ ]
+ },
+ "execution_count": 52,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import jsgf\n",
+ "\n",
+ "book_grammar = jsgf.parse_grammar_file('book.jsgf')\n",
+ "book_grammar"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Wykorzystajmy gramatykę `book.jsgf` do analizy następującej wypowiedzi"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[Rule(name='rezerwuj', visible=True, expansion=Sequence(Literal('chciałbym zarezerwować'), NamedRuleRef('ilosc_biletow'), NamedRuleRef('tytul_filmu'), OptionalGrouping(NamedRuleRef('dzien_rezerwacji')), OptionalGrouping(NamedRuleRef('godzina_rezerwacji'))))]"
+ ]
+ },
+ "execution_count": 53,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "utterance = 'chciałbym zarezerwować 1 biletów na film Pitbull'\n",
+ "matched = book_grammar.find_matching_rules(utterance)\n",
+ "matched"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Reprezentację znaczenia można wydobyć ze sparsowanej wypowiedzi na wiele sposobów. My do\n",
+ "wydobywania slotów wykorzystamy mechanizm tagów JSGF a za nazwę aktu dialogowego przyjmiemy nazwę\n",
+ "gramatyki. Wzorując się na [DSTC2](https://github.com/matthen/dstc) wynikową ramę zapiszemy korzystając ze słownika o polach `act` i `slots`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'act': 'book',\n",
+ " 'slots': [('ilosc', '1'),\n",
+ " ('tytul', 'Pitbull'),\n",
+ " ('dzien', None),\n",
+ " ('godzina', None)]}"
+ ]
+ },
+ "execution_count": 54,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def get_dialog_act(rule):\n",
+ " slots = []\n",
+ " get_slots(rule.expansion, slots)\n",
+ " return {'act': rule.grammar.name, 'slots': slots}\n",
+ "\n",
+ "def get_slots(expansion, slots):\n",
+ " if expansion.tag != '':\n",
+ " slots.append((expansion.tag, expansion.current_match))\n",
+ " return\n",
+ "\n",
+ " for child in expansion.children:\n",
+ " get_slots(child, slots)\n",
+ "\n",
+ " if not expansion.children and isinstance(expansion, jsgf.NamedRuleRef):\n",
+ " get_slots(expansion.referenced_rule.expansion, slots)\n",
+ "\n",
+ "get_dialog_act(matched[0])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Łącząc powyższe funkcje możemy zbudować prosty moduł NLU."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'act': 'null', 'slots': []}"
+ ]
+ },
+ "execution_count": 41,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def nlu(utterance):\n",
+ " matched = book_grammar.find_matching_rules(utterance)\n",
+ "\n",
+ " if matched:\n",
+ " return get_dialog_act(matched[0])\n",
+ " else:\n",
+ " return {'act': 'null', 'slots': []}\n",
+ "\n",
+ "nlu('chciałbym zarezerwować dwa bilety na film Pitbull')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Problemy\n",
+ "--------\n",
+ "\n",
+ " - Co z normalizacją wyrażeń liczbowych takich, jak godziny, daty czy numery telefonów?\n",
+ "\n",
+ " - Co w przypadku gdy więcej niż jedna reguła zostanie dopasowana?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zadanie\n",
+ "-------\n",
+ "Zaimplementować analizator języka naturalnego (NLU) na potrzeby realizowanego agenta dialogowego.\n",
+ "\n",
+ "Moduł powinien być zbudowany z wykorzystaniem parsingu regułowego i/lub technik uczenia maszynowego.\n",
+ "\n",
+ "Przygotować skrypt `evaluate.py` wyznaczający *dokładność* (ang. accuracy) analizatora względem zgromadzonego korpusu eksperymentalnego,\n",
+ "tj. stosunek liczby wypowiedzi użytkownika, w których akty dialogowe zostały rozpoznane prawidłowo do liczby wszystkich wypowiedzi użytkownika w korpusie.\n",
+ "\n",
+ "Analizator języka naturalnego umieścić w gałęzi `master` repozytorium projektowego. Skrypt `evaluate.py` umieścić w katalogu głównym tej gałęzi.\n",
+ "\n",
+ "Termin: 4.05.2022, godz. 23:59."
+ ]
+ }
+ ],
+ "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",
+ "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.3"
+ },
+ "subtitle": "7.Parsing semantyczny z wykorzystaniem gramatyk[laboratoria]",
+ "title": "Systemy Dialogowe",
+ "year": "2021"
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}