https://szkolazpieklarodem.pl/
W tej sekcji napiszemy więcej kodu, aby wytrenować nasz model okna dialogowego i przeszkolić go ponownie, gdy otrzyma nieprawidłowe wyniki. Tak więc, gdy nasz bot zrobi coś złego, natychmiast wkraczamy i pozwalamy modelowi aby wiedzieć, że jego przewidywania są błędne, mówiąc mu, co jest słuszne. Bez konieczności zatrzymywania model sam się szkoli, a gdy już to zakończymy, interakcja między użytkownikiem a botem zostaje przechwycona w pliku i dodana do naszych istniejących danych szkoleniowych. Działa bardziej jak system informacji zwrotnej na każdym kroku, zamiast czekać na pojedynczą nagrodę na końcu. Następnym krokiem jest utworzenie nowego pliku o nazwie endpoints.yml z poniższą zawartością. Będziemy używać tego pliku w naszym pliku kodu Pythona train_online.py. Dzięki tej konfiguracji możemy udostępnić metodę Rasa jako interfejsy API HTTP.
action_endpoint:
url: http://localhost:5055/webhook
#nlg:
# url: http://localhost:5056/nlg
core_endpoint:
url: http://localhost:5005
Now, let’s create train_online.py for our online/interactive training purposes.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import logging
from rasa_core import utils, train
from rasa_core.training import online
from rasa_core.interpreter import NaturalLanguageInterpreter
logger = logging.getLogger(__name__)
def train_agent(interpreter):
return train.train_dialog_model(domain_file=”horoscope_domain.yml”,
stories_file=”data/stories.md”,
output_path=”models/dialog”,
nlu_model_path=interpreter,
endpoints=”endpoints.yml”,
max_history=2,
kwargs={“batch_size”: 50,
“epochs”: 200,
“max_training_samples”: 300
})
if __name__ == ‘__main__’:
utils.configure_colored_logging(loglevel=”DEBUG”)
nlu_model_path = “./models/nlu/default/horoscopebot”
interpreter = NaturalLanguageInterpreter.create(nlu_model_path)
agent = train_agent(interpreter)
online.serve_agent(agent)
max_history to liczba stanów, które model ma śledzić.
Zanim zaczniemy uruchamiać nasz końcowy skrypt, train_online.py, powinniśmy wiedzieć i przygotować się na coś, co nazywa się rasa-nlu-sdk.
rasa-nlu-sdk
Stos Rasa NLU zawiera rasa-nlu-sdk, który jest pakietem SDK języka Python do tworzenia niestandardowych akcji dla Rasa Core. Jeśli chodzi o nasz przykład chatbota, musimy zdefiniować kilka niestandardowych akcji, jak na przykład wejście do API w celu pobrania dzisiejszego horoskopu, czy może operacja zapisu do bazy danych w celu dodania użytkownika do listy subskrybentów. Dobra wiadomość jest taka, że mają do tego oddzielną bibliotekę, którą możemy zainstalować za pomocą pip. Zainstalujmy to za pomocą następującego polecenia:
pip install rasa-core-sdk==0.11.0
Teraz musimy przejść do innej zakładki naszego terminala lub do świeżej linii poleceń i wykonać następujące polecenie w naszym katalogu projektu (miejscu, w którym znajduje się nasz plik action.py):
python -m rasa_core_sdk.endpoint –actions actions
INFO:__main__:Starting action endpoint server…
INFO:rasa_core_sdk.executor:Registered function for ‘get_todays_horoscope’.
INFO:rasa_core_sdk.executor:Registered function for ‘subscribe_user’.
INFO:__main__:Action endpoint is up and running. on (‘0.0.0.0’, 5055)
To polecenie uruchomi serwer akcji, który będzie nasłuchiwał wszelkich akcji niestandardowych przewidywanych przez model. Gdy tylko jakakolwiek akcja zostanie uruchomiona, wykona ją i udzieli odpowiedzi zgodnie z metodą. Domyślny port punktu końcowego serwera akcji to 5055 na hoście lokalnym. Jeśli chcesz to zmienić, możesz dodać argument pass –port w wierszu poleceń. Nasuwa się szybkie pytanie: dlaczego? Po co mi do tego osobny serwer? Dlaczego nie możemy używać zwykłego Pythona? Tak, możemy używać zwykłego języka Python, ale załóżmy, że wymagane działania chcesz opracować w jakimkolwiek innym języku lub masz już pewne działania ujawnione jako interfejsy API. Teraz wystarczy przejść do pliku endpoints.yml, który już utworzyliśmy, i użyć go, aby wspomnieć, gdzie powinien być używany serwer akcji i gdzie powinien znajdować się serwer core_endpoint. W systemie produkcyjnym oba mogą być różnymi serwerami mającymi zupełnie różne adresy URL.
Teraz, gdy uruchomimy nasz następny skrypt, w którym wspomnieliśmy o pliku endpoints.yml, Rasa przeczyta plik i pobierze konfigurację naszego serwera akcji, który jest już uruchomiony i działa zgodnie z konfiguracją, którą zrobiliśmy wcześniej.
action_endpoint:
url: http://localhost:5055/webhook
Uruchommy train_online.py w nowym terminalu wiersza poleceń.
$python3 train_online.py
Po udanym wytrenowaniu modelu dialogowego otrzymamy taki komunikat:
2018-08-30 07:09:37 INFO rasa_core.policies.keras_policy – Done
fitting keras policy model
2018-08-30 07:09:37 INFO rasa_core.agent – Model directory models/nlu
exists and contains old model files. All files will be overwritten.
2018-08-30 07:09:37 INFO rasa_core.agent – Persisted model to ‘/Users/
sumit/apress_all/Chapter IV/horoscope_bot/models/nlu’
2018-08-30 07:09:37 INFO rasa_core.training.online – Rasa Core server
is up and running on http://localhost:5005
Bot loaded. Type a message and press enter (use ‘/stop’ to exit).
127.0.0.1 – – [2018-08-30 07:09:37] “GET /domain HTTP/1.1” 200 996 0.001847
Teraz możesz zacząć rozmawiać ze swoim botem, który właśnie się urodził. Odtąd to, jak będziesz go trenować, zależy wyłącznie od Ciebie. Możesz go poprawić, gdy zareaguje na coś złego lub nieoczekiwanego. Zróbmy to i zobaczmy, czy sytuacja się poprawi. Wpisuję „Cześć” jako pierwszą wiadomość, a bot zwraca następujące informacje:
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’: ‘greeting’}
we currently have slots: DD: None, MM: None, horoscope_sign: None,
subscribe: None
——
The bot wants to [utter_greet] due to the intent. Is this correct?
- Yes
- No, intent is right but the action is wrong
- The intent is wrong
- Export current conversations as stories and quit
—————————————————————————
Teraz bot mówi mi, co zrobił, na podstawie tego, co powiedział użytkownik i jak to zrozumiał. Teraz daje nam również cztery opcje. Porozmawiamy o tym za chwilę. To, co bot_ zrobił tutaj, ma znaczenie action_listen; po prostu czekał, aż użytkownik coś wprowadzi, co jest w porządku. Bot wypowiada intencję {‘confidence’: 0.8472929307505297, ‘name’: ‘greeting’}, co jest poprawne, więc naciskamy 1, co oznacza, co bot rozumie i stara się to zrobić poprawnie.
1
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’: ‘greeting’}
bot did: utter_greet
we currently have slots: DD: None, MM: None, horoscope_sign: None,
subscribe: None
——
The bot wants to [action_listen]. Is this correct?
- Yes.
- No, the action is wrong.
- Export current conversations as stories and quit
—————————————————————————
I proszę bardzo, nasz bot przynajmniej przywitał użytkownika poprawnie. Jeśli zobaczysz powyższą odpowiedź, możesz faktycznie sprawdzić, co zrobił nasz bot; śledzi to wszystko, podczas gdy my go szkolimy.
bot did: utter_greet
Teraz bot mówi, że następną rzeczą jest poczekanie i wysłuchanie, co użytkownik powie (tj. oczekiwanie na dane wejściowe użytkownika). Czy to jest poprawne? Tak, zgadza się, więc ponownie naciskamy 1, a bot wyświetla monit użytkownikowi. Wchodzę i pytam: „Jaki jest mój horoskop na dzisiaj?”
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’:
‘greeting’}
bot did: utter_greet
bot did: action_listen
user said: what’s my horoscope for today?
whose intent is: {‘confidence’: 0.8902154738608781, ‘name’:
‘get_horoscope’}
we currently have slots: DD: None, MM: None, horoscope_sign: None,
subscribe: None
——
The bot wants to [utter_ask_horoscope_sign] due to the intent. Is this
correct?
- Yes
- No, intent is right but the action is wrong
- The intent is wrong
- Export current conversations as stories and quit
—————————————————————————
bot did: utter_greet
Teraz bot mówi, że następną rzeczą jest poczekanie i wysłuchanie, co użytkownik powie (tj. oczekiwanie na dane wejściowe użytkownika). Czy to jest poprawne? Tak, zgadza się, więc ponownie naciskamy 1, a bot wyświetla monit użytkownikowi. Wchodzę i pytam: „Jaki jest mój horoskop na dzisiaj?”
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’:
‘greeting’}
bot did: utter_greet
bot did: action_listen
user said: what’s my horoscope for today?
whose intent is: {‘confidence’: 0.8902154738608781, ‘name’:
‘get_horoscope’}
we currently have slots: DD: None, MM: None, horoscope_sign: None,
subscribe: None
——
The bot wants to [utter_ask_horoscope_sign] due to the intent. Is this
correct?
- Yes
- No, intent is right but the action is wrong
- The intent is wrong
- Export current conversations as stories and quit
—————————————————————————
Teraz bot bardzo poprawnie identyfikuje intencję jako intencję „get_horoskop” z 89-procentową dokładnością, co jest całkiem dobrym wynikiem. Bot mówi również, że chce wypowiedzieć_ zapytaj_horoskop_znak, co znowu jest poprawne, ponieważ użytkownik nie wspomniał jeszcze o żadnym znaku horoskopu, a miejsce nadal ma wartość Brak, jak pokazano. Ponownie wciskamy 1.
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’: ‘greeting’}
bot did: utter_greet
bot did: action_listen
user said: what’s my horoscope for today?
whose intent is: {‘confidence’: 0.8902154738608781, ‘name’:
‘get_horoscope’}
bot did: utter_ask_horoscope_sign
we currently have slots: DD: None, MM: None, horoscope_sign: None,
subscribe: None
——
The bot wants to [action_listen]. Is this correct?
- Yes.
- No, the action is wrong.
- Export current conversations as stories and quit
—————————————————————————
Teraz bot pyta, czy czas poczekać na dane wejściowe użytkownika. Tak, użytkownik musi podać znak horoskopu
Ponownie wciskamy 1 i po wyświetleniu monitu wprowadziliśmy „Koziorożec” jako dane wejściowe.
—————————————————————————
Chat history:
bot did: action_listen
user said: hi
whose intent is: {‘confidence’: 0.8472929307505297, ‘name’: ‘greeting’}
bot did: utter_greet
bot did: action_listen
user said: what’s my horoscope for today?
whose intent is: {‘confidence’: 0.8902154738608781, ‘name’:
‘get_horoscope’}
bot did: utter_ask_horoscope_sign
bot did: action_listen
user said: Capricorn
whose intent is: {‘confidence’: 0.8456705103362621, ‘name’:
‘get_horoscope’}
with horoscope_sign: capricorn
we currently have slots: DD: None, MM: None, horoscope_sign: capricorn,
subscribe: None
The bot wants to [get_todays_horoscope] due to the intent. Is this correct?
- Yes
- No, intent is right but the action is wrong
- The intent is wrong
- Export current conversations as stories and quit
—————————————————————————
Teraz, jak widzimy, miejsce na znak horoskopu jest automatycznie ustawiane powyżej na „Koziorożec”. Kolejnym krokiem jest nauczenie bota wywoływania get_todays_horoskop i wywoływania akcji get_todays_horoskop. Do tego czasu nasz slot jest już ustawiony na zmienną horoskop_znak, którą zdefiniowaliśmy w horoskop_domain.yml, więc jeśli ta akcja zostanie wywołana ponownie, chatbot powinien zwrócić aktualny horoskop na dany dzień. Spróbujmy. Wpisałem „Koziorożec”. Bot trafia do punktu końcowego serwera akcji i zwraca wynik użytkownikowi zgodnie z definicją w naszej akcji niestandardowej. Twój horoskop na dziś: Podróż od porażki do sukcesu napędzana jest optymizmem. Będziesz dzisiaj bardzo optymistycznie nastawiony do swojej pracy, przyszłości i wszystkiego, co może doprowadzić cię do sukcesu, mówi Ganesha. Będziesz także bardzo ostrożny w codziennej pracy i wykorzystasz każdą okazję, która przybliży Cię o krok do Twoich celów. Aby zrealizować swoje marzenia, wystarczy determinacja i szczęście; będziesz miał dzisiaj oba. Wydaje się to uczciwe, ponieważ brakuje mi terminu na dokończenie tego rozdziału, a teraz jest 6:00 rano, a ja jeszcze nie spałem. Dołóż wszelkich starań, aby Twoje pieniądze były warte wydania tej książki. OK, wróćmy i zobaczmy, co nasz bot próbuje dalej zrobić.
——
The bot wants to [action_listen]. Is this correct?
- Yes.
- No, the action is wrong.
- Export current conversations as stories and quit
Może nie chcemy, żeby nasz bot słuchał teraz, po tym jak wypowiedział horoskop na dzisiaj. Chcemy, aby nasz bot prosił użytkownika o zasubskrybowanie aktualizacji zgodnie z naszym skryptem konwersacji, a także zgodnie z utworzonymi przez nas historiami. Więc naciskam 2 i pojawia się komunikat
——
what is the next action for the bot?
0 action_listen 1.00
1 action_restart 0.00
2 action_default_fallback 0.00
utter_greet 0.00
4 utter_ask_horoscope_sign 0.00
5 utter_ask_dob 0.00
6 utter_subscribe 0.00
7 get_todays_horoscope 0.00
8 subscribe_user 0.00
Ponieważ chcemy, aby nasz użytkownik subskrybował, należy nacisnąć 6, aby bot zapytał użytkownika, czy chce zapisać się na codzienne aktualizacje. Bot odpowiada: „Czy chcesz subskrybować codzienne aktualizacje?” Teraz bot mówi:
—————————————————————————
The bot wants to [get_todays_horoscope]. Is this correct?
- Yes.
- No, the action is wrong.
- Export current conversations as stories and quit
Akcja tutaj nie jest poprawna, więc wciskamy 2 i uczymy bota, aby słuchał tutaj akcji użytkownika.
—————————————————————————
what is the next action for the bot?
0 action_listen 0.21
1 action_restart 0.01
2 action_default_fallback 0.01
3 utter_greet 0.21
4 utter_ask_horoscope_sign 0.51
5 utter_ask_dob 0.01
6 utter_subscribe 0.02
7 get_todays_horoscope 0.78
8 subscribe_user 0.22
—————————————————————————
Wciskamy 0, gdy bot czeka na poznanie prawidłowego kolejnego kroku. Bot będzie teraz czekać na dane wejściowe użytkownika w naszym interaktywnym procesie uczenia się
Użytkownik mówi tutaj: „Proszę mnie zasubskrybować”, a nasz bot z 80% pewnością rozpoznaje, że jest to zamiar subskrypcji, a także, w oparciu o nasze dane szkoleniowe w data.json, dość łatwo rozumie, że użytkownik prosi o subskrypcję i nie wypisywać się. Innymi słowy, ustawia przedział subskrypcji na True, jak widać tutaj:
—————————————————————————
user said: Please subscribe me
whose intent is: {‘confidence’: 0.795172441763619, ‘name’:
‘subscription’}
with subscribe: True
we currently have slots: DD: None, MM: None, horoscope_sign: capricorn,
subscribe: True
—————————————————————————
Teraz, gdy nasz bot zrozumiał intencję, a także przeanalizował zawarte w niej encje, nadszedł czas, aby odpowiedzieć użytkownikowi, mówiąc: „Zasubskrybowano go pomyślnie” i bingo — otrzymujemy wiadomość od bota: Subskrypcja została pomyślnie zapisana. ty idź! Możesz z powodzeniem samodzielnie zbudować własnego chatbota. W ramach ćwiczenia polecam dodać wszystkie omówione przez nas przypadki użycia HoroskopBota i sprawdzić, czy to działa. Spróbuj dodać więcej przypadków użycia i więcej funkcjonalności, gdy wszystko, co zrobiliśmy do tej pory, działa dobrze. Możesz tutaj dodać więcej komunikatów, aby bot powiedział „Do widzenia, miłego dnia” po zakończeniu rozmowy. Jestem głęboko przekonany, że powinieneś mieć taką możliwość. Upewnij się, że to zrobiłeś i daj nam znać, jak poszło. Teraz ostatnia część polega na oddaniu całej tej wiedzy użytkownikowi, abyśmy nie musieli ponownie uczyć tych samych historii, a bot będzie próbował uczyć się na podstawie istniejących historii i jeszcze więcej.