Building a simple ChatBot in Python with RASA

[ad_1]

In this section we are going to work on the Dialogue part for “building a simple chatbot using RASA conversational AI solution”.

If you haven’t went through part 1 I recommend you to first read part 1 and only then read this one.

Now things are getting interesting, chatbot wise — till now we’ve built the NLP/U part and now we are going to work on the dialogue side.

As I mentioned in part 1, for every chatbot that actually do a little bit more that just question answering, the very basic one is a chatbot that supports “slot filling”, which means (in our example) to interact with the user to get the mandatory slots that it needs (according to the “domain definition” — don’t worry we’ll get to that later on).

One slot filling scenario could be:

  • user: “I want Pizza” ; #missing slots: [size, toppings, etc.]
  • bot: “what size?”
  • user: “large”
  • bot: “Which toppings would you like?”
  • user: “Olives”

In this example we have 2 interactions with the user — 2 slots to fill.

Building the Dialogue

Similar to what we’ve built in the NLU (part 1 mentioned above) we should create the domain and the training data.

Building the Domain

Here we would create the file chat_domail.yml.

You can use this file:

intents:
    - order_pizza
    - greet

entities:
    - size
    - toppings

slots:
    size:
         type: text
    toppings:
        type: text

templates:
    utter_greet:
        - 'Hello, how can I help you?'
        - 'Hi, I am here to help.'
    utter_get_pizza_size:
        - 'What pizza size?'
    utter_get_pizza_toppings:
        - 'What toppings would you like on your pizza?'
actions:
    - utter_greet
    - utter_get_pizza_size
    - utter_get_pizza_toppings
    - actions.ActionOrderPizza

Pay attention to the last one — more info below on the explanation part.

But if you create your own or changing this one, it is always a good practice to validate the format (this is a fragile format and things won’t work in case you break it):

Link to online yml validation.

Let’s try to explain the file above.

  • Intents — is the parent structure, usually are the supported actions of your bot (but there are exceptions)
  • Entities — are the words that you want the bot to extract from the free text
  • Slots — Defining them here, is like saying to the bot which entities to track through the dialogue, for example, if the user is saying: “I want pizza”, we want the bot to interact with the user to get the “size” or the “topping” slots fulfilled.
  • Actions — are either utterances, which means, the output that we want to send the user, or you can actually create your own class that inherent form Action. In our example its: “actions.ActionOrderPizza”, here again Rasa has a very cool interface, you should inherent from Class Action and add your logic in the derived class according to what you need, here is an example — create the file action.py:
from rasa_core.actions import Action

class ActionOrderPizza(Action):
    def name(self):
        return 'action_order_pizza'
    def run(self):
        print('Ordering Pizza is completed! It should be with you soon :)')
        pass

In the above example I created it as “stubs” no real logic there, just for the sake of the example.

Building the Training Data for the Dialogue

Here we are going to build a mark down file, we’ll named it: stories.md, as the name implies here we describe the possible dialogue flows as user stories.

Here you may raise a concern that its a very manual process but don’t worry RASA has a great tool for you to online train you dialogue! or even more load pre-trained dialogues.

But first let’s create a very short and basic flow, and train the dialogue model, we’ll get back to the online training later on.

For the basic flow you can use this file stories.md:

* greet
    - utter_greet
* order_pizza
    - utter_get_pizza_size
* order_pizza
    - utter_get_pizza_toppings
* order_pizza
    - action_order_pizza

Pay attention that in the above flow we are covering the following scenario:

  1. Bot: “Hello, how can I help you?”
  2. User: “I want pizza” #missing the slots: “size” and “toppings”
  3. Bot: “What size?”
  4. User: “large”
  5. Bot: “what toppings would like on your pizza?”
  6. User: “cheese”

Now we are ready to train a dialogue using the above training data.

Let’s write some code, you can use this file:

import logging
from rasa_core.agent import Agent
from rasa_core.domain import Domain
from rasa_core.policies.keras_policy import KerasPolicy
from rasa_core.policies.memoization import MemoizationPolicy

if __name__ == '__main__':
    logging.basicConfig(level='INFO')
    dialog_training_data_file = './data/stories.md'
    path_to_model = './models/dialogue'
    # domain = Domain()
    agent = Agent('chat_domain.yml', policies = [MemoizationPolicy(), KerasPolicy()])

    agent.train(
        dialog_training_data_file,
        augmentation_factor=50,
        max_history=2,
        epochs=500,
        batch_size=10,
        validation_split=0.2)
    agent.persist(path_to_model)

Now run:

python dialogue_model.py

Note: the code above is running with no errors on Python3 but for some reason I had some issues with Python2.

If everything went well you should have the model trained and the output is under, models/dialogue/, it should look like this:

Building a simple ChatBot in Python with RASA 1

NOW we are ready for the online training! yay!!!

As I promised RASA has an amazing capability to online train your bot and create a much more elaborated stories.md file for you to use after online training session is finished.

Now create the online_train.py:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import logging

from rasa_core.channels.console import ConsoleInputChannel
from rasa_core.agent import Agent
from rasa_core.interpreter import RegexInterpreter
from rasa_core.policies.keras_policy import KerasPolicy
from rasa_core.policies.memoization import MemoizationPolicy
from rasa_core.interpreter import RasaNLUInterpreter


logger = logging.getLogger(__name__)

def run_online_trainer(input_channel,
                        interpreter,
                        domain_def_file='chat_domain.yml',
                        training_data_file='./data/stories.md',

                        ):
    agent = Agent(  domain_def_file,
                    policies=[KerasPolicy(), MemoizationPolicy()],
                    interpreter=interpreter)
    agent.train_online( training_data_file,
                        input_channel=input_channel,
                        max_history=2,
                        batch_size=500,
                        epochs=200,
                        max_training_samples=300)
    return agent


if __name__ == '__main__':
    logging.basicConfig(level='INFO')
    interpreter = RasaNLUInterpreter('./models/nlu/default/chat')
    run_online_trainer(ConsoleInputChannel(), interpreter)

No we are ready to run:

python online_train.py

You should get an interactive session in which you should follow the expected flow, for example:

Building a simple ChatBot in Python with RASA 2
  1. In the first green line it says that the bot has been loaded and is waiting for the user input.
  2. Next we type: “hi”
  3. Now you can see that the system prints the “Chat history”:
  • we can see that the flow is correct:
  • bot did: action_listen
  • user said: hi
  • whose intent is: greet

4. Now the system is waiting for your feedback, in this case the flow is correct, so we should type: 2.

5. You can continue doing this as long as you want, when you finish type “0” to export the new stories.md file (give it new name, such: “stories_v1.md”).

Now replace the previous stories file (back it up first!) or concatenate them in the same stories file, that way you should have more and more training data!

That’s it — now the last part is to test it — more to come…

Please feel free ask question here or go to relevant gitter section:

This article has been published from the source link without modifications to the text. Only the deadline has been changed.

Source link