from IPython.display import Image
Image("/Users/vlad/Desktop/ChatBot/Image_2_rasa.png", width = 1000, height = 1000)
Chatbots are increasingly transforming the way we interact with software. They provide a great business opportunity for both, small and large companies. Their purpose is to support and scale business teams in their relations with customers. Doing this helps businesses save a lot of money which is why many business owners are adopting this technology.
But first, what is a chatbot? Chatbots can be definied as software agents that converse through a chat interface. What that means, is that they are software programs that are able to have a human-like conversation, which provides some kind of value to the end user. The user can interact with the chatbot by typing in a question, a request or simply by using their voice, depending on the chatbot's providor. Virtual assistants, like Apple's Siri or Amazon's Alexa, are two examples of widly adopted chatbots that interact by voice rather than by text. Typically, the chatbot will greet the user and then invite him to to ask some kind of question. When the user replies, the chatbot will parse the input and figure out what is the intention of the user's request. The chatbot then, will respond in some kind of consequential or logical manner, either by providing, relevant to the user's question, information or by asking the user for further details before ultimately answering his question. Great chatbots can keep up with this conversational workflow back and forth in a natural way, within the scope of what the chatbot is designed to do.
According to the way they are designed, chatbots can be devided into two categories: the "smart" bots and the "dumb" ones. The “dumb” bots behave according to a set of rules. They are preprogrammed to act in a certain way and can’t “think outside the box”. They scan the user's input for keywords or commands and can’t respond to anything else.
The second type of chatbots is built using more advanced technologies, such as Artificial Intelligence, Machine Learning (ML), and Named Entity Recognition (NER). “Smart” bots learn from conversations with humans and become more and more advanced as time goes by. They can not only respond to a list of predetermined commands but also understand organic human speech.
Such bots can serve as personal assistants or even digital friends. They shine in operations that require extensive search, complex calculations or picking similar objects among a great mass of things.
from IPython.display import Image
Image("/Users/vlad/Desktop/ChatBot/Image_1_rasa.png", width = 1000, height = 1000)
In this blog post, you will learn how to build a simple weather chatbot that relies on natural language processing and machine learning without any special coding skills or machine learning knowledge. We will use a pair of open source, highly scalable, python libraries for building conversational software, Rasa NLU and Rasa Core. Both libraries hold to a high standard of professionalism, and this extends to implementations of machine learning algorithms. They aim to bridge the gap between research and application, bringing recent advances in machine learning to non-experts who want to implement conversational AI systems.
One core advantage of Rasa NLU and Rasa Core over other similar systems, is that it allows you to build a working conversational system with a minimum amount of training data.
The RASA platform is based on two fundamental components:
To make everything work, we have first to install three packages: RASA NLU, RASA CORE and Apixu package for weather prediction:
#for some basic configurations
%matplotlib inline
import logging, io, json, warnings
logging.basicConfig(level="INFO")
warnings.filterwarnings('ignore')
The Domain is a yml file that defines the universe in which our bot operates.
weather_domain = """
entities:
- location
slots:
location:
type: text
intents:
- greet
- inform
- deny
templates:
utter_greet:
- 'Hello! How can I help you?'
- 'Hi there! How can I help you?'
utter_goodbye:
- 'Talk later then!'
- 'Bye Bye then!'
- 'Cu next time then:)'
- 'Okay then, bye bye!'
utter_ask_location:
- 'What location would you like to check the weather?'
utter_ask_for_anything_else:
- "What else can I do for you?"
actions:
- utter_greet
- utter_goodbye
- utter_ask_location
- utter_ask_for_anything_else
- __main__.WeatherAction
"""
%store weather_domain > weather_domain.yml
The domain contains the following RASA components:
Next, we create a markdown file which contains some basic stories for our chatbot. For more information about Rasa stories check out the official RASA documenation: http://rasa.com/docs/core/stories/.
weather_stories = """
## story_01
* greet
- utter_greet
* inform
- utter_ask_location
* inform{"location": "Athens"}
- slot{"location": "Athens"}
- action_weather
- utter_ask_for_anything_else
* deny
- utter_goodbye
## story_02
* greet
- utter_greet
* inform
- utter_ask_location
* inform{"location": "Crete"}
- slot{"location": "Crete"}
- action_weather
- utter_ask_for_anything_else
* deny
- utter_goodbye
## story_03
* greet
- utter_greet
* inform
- utter_ask_location
* inform{"location": "Thessaloniki"}
- slot{"location": "Thessaloniki"}
- action_weather
- utter_ask_for_anything_else
- utter_ask_for_anything_else
* deny
- utter_goodbye
## story_04
* greet
- utter_greet
* inform
- utter_ask_location
* inform{"location": "Crete"}
- slot{"location": "Crete"}
- action_weather
- utter_ask_for_anything_else
* inform{"location": "Bucharest"}
- slot{"location": "Bucharest"}
- action_weather
- utter_ask_for_anything_else
* deny
- utter_goodbye
"""
%store weather_stories > weather_stories.md
Both Rasa NLU and Core work with human-readable training data formats. Rasa NLU requires a list of utterances annotated with intents and entities. These can be specified either in a json structure or in a markdown format.
In our blog post, we use a markdown format which is compact and quite simple to work with. We could also use a JSON structure instead, which is slightly more cumbersome to read, but not whitespace sensitive and more suitable for transmission of training data between applications and servers.
For more information regarding the training data format you can check the documentation on: http://rasa.com/docs/nlu/master/dataformat/.
weather_nlu = """
## intent:greet
- hey
- hello
- hi
- good morning
- good evening
- hey there
## intent: inform
- I would like to know the weather
- I want to know the weather
- What's the weather?
- I would like to know the weather in [Athens](location)
- What's the weather in [Athens](location)
- What is the weather in [Athens](location)
- I want to know the weather in [Athens](location)
- I would like to know the weather in [Thessaloniki](location)
- I would like to know the weather in [Crete](location)
- I would like to know the weather in [Rome](location)
- I would like to know the weather in [Bucharest](location)
## intent: deny
- Nothing
- Nothing for this time
- I am okay, thanks
- Nothing, thanks
"""
%store weather_nlu > weather_nlu.md
In the next step we will make a connection to the Apixu API and get the weather in Athens, just to check if everything works fine.
from apixu.client import ApixuClient, ApixuException
api_key = 'ac778d7ea3f7492e99290419180309'
client = ApixuClient(api_key)
current = client.getCurrentWeather(q='Athens')
We get the following JSON file wich contains all the needed information.
#create a function to print JSON formats in a eye-appealing format
def pprint(o):
# small helper to make dict dumps a bit prettier
print(json.dumps(o, indent=2))
pprint(current)
Let's check if the connection works by printing the weather in Athens today!
#get information from JSON file
country = current['location']['country']
city = current['location']['name']
weather_condition = current['current']['condition']['text']
temp_feelslike_celsius = current['current']['feelslike_c']
temp_celsius = current['current']['temp_c']
wind_kph = current['current']['wind_kph']
humidity = current['current']['humidity']
#quick check
print('It is {0} in {1} today. The temperature is {2} degrees celsius.'.format(weather_condition,city,temp_celsius))
Now, we are ready to define our custom action class. Note that we also define the WeatherAction class in our domain file, inside the "actions" compartment. In case you forget to put it there, your chatbot will not work.
#import libraries
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from rasa_core.actions.action import Action
from rasa_core.events import SlotSet
#define the custom action
class WeatherAction(Action):
def name(self):
return 'action_weather'
def run(self,dispatcher, tracker, domain):
from apixu.client import ApixuClient
api_key = "ac778d7ea3f7492e99290419180309"
client = ApixuClient(api_key)
location = tracker.get_slot('location')
current = client.getCurrentWeather(q=location)
country = current['location']['country']
city = current['location']['name']
weather_condition = current['current']['condition']['text']
temp_feelslike_celsius = current['current']['feelslike_c']
temp_celsius = current['current']['temp_c']
wind_kph = current['current']['wind_kph']
humidity = current['current']['humidity']
response = 'It is {0} in {1} today.The temperature is {2} degrees celsius and it feels like {3} degrees. The humidity is {4}% and the wind is {5} km/h '.format(weather_condition,
city,
temp_celsius,
temp_feelslike_celsius, humidity,
wind_kph)
dispatcher.utter_message(response)
return [SlotSet('location',location)]
As we previously mentioned Rasa NLU is the natural language understanding module. It comprises loosely coupled modules, combining a number of natural language processing and machine learning libraries in a consistent API. The developers aimed for a balance between customisability and ease of use. To this end, there are pre-defined pipelines with sensible defaults which work well for most use cases. One of these libraries is the the spaCy NLP library.
In our example, we used the "nlp_spacy" pipeline to load the spaCy language model, then the "tokenizer_spacy" pipeline to split each sentence (user message) into individial words and the "ner_crf" component to train a conditional random field to recognise the entities in the training data, using the tokens and POS tags as base features. Next, we used the "intent_featurizer_spacy" to represent each sentence into a multidimentional euclidean space, and finally the "intent_classifier_sklearn" for our text classification task.
weathermodel_config = """
language: "en"
pipeline:
- name: "nlp_spacy" # loads the spacy language model
- name: "tokenizer_spacy" # splits the sentence into tokens
- name: "ner_crf" # uses the pretrained spacy NER model
- name: "intent_featurizer_spacy" # transform the sentence into a vector representation
- name: "intent_classifier_sklearn" # uses the vector representation to classify using SVM
"""
%store weathermodel_config > weathermodel_config.yml
Now, we are finally ready to train our model!
from rasa_nlu.training_data import load_data
from rasa_nlu.config import RasaNLUModelConfig
from rasa_nlu.model import Trainer
from rasa_nlu import config
# loading the nlu training samples
training_data = load_data("weather_nlu.md")
# trainer to educate our pipeline
trainer = Trainer(config.load("weathermodel_config.yml"))
# train the model!
interpreter = trainer.train(training_data)
# store it for future use
model_directory = trainer.persist("./models/nlu", fixed_model_name="current")
Once we trained our model, we can play around with by shooting in some messages.
pprint(interpreter.parse("I would like to know the weather"))
pprint(interpreter.parse("I would like to see the weather in Bucharest"))
from rasa_core.policies import FallbackPolicy, KerasPolicy, MemoizationPolicy
from rasa_core.agent import Agent
agent = Agent('weather_domain.yml', policies=[MemoizationPolicy(), KerasPolicy()])
# loading our neatly defined training dialogues
training_data = agent.load_data('weather_stories.md')
agent.train(
training_data,
validation_split=0.1,
epochs=2000,
augmentation_factor = 50
)
agent.persist('models/dialogue')
Now it’s time to enjoy the fruit of our hard work by having a conversation with our bot! Below you can see a simple example of a possible discussion with our bot.
#ignore some warnings
import warnings
import ruamel.yaml
warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)
from rasa_core.agent import Agent
agent = Agent.load('models/dialogue', interpreter = model_directory)
print("Your bot is ready to talk! Type your messages here or send 'stop'")
while True:
a = input()
if a == 'stop':
break
responses = agent.handle_message(a)
for response in responses:
print(response["text"])
Rasa Core also has the capability to visualise a graph of training dialogues. A story graph is a directed graph with actions as nodes. Edges are labeled with the user utterances that occur in between the execution of two actions. If there is no user interaction between two consecutive actions, the edge label is omitted. Each graph has an initial node called START and a terminal node called END. Note that the graph does not capture the full dialogue state and not all possible walks along the edges necessarily occur in the training set. To simplify the visualization a heuristic is used to merge similar nodes.
You can see the story graph of our training dialogues in the image below.
from IPython.display import Image
from rasa_core.agent import Agent
agent = Agent('weather_domain.yml')
agent.visualize("weather_stories.md", "weather_stories.png", max_history = 2)
Image(filename="weather_stories.png")
We can also evaluate the accuarcy of our model by generating the classification report and by plotting the relevant confusion matrix.
from rasa_core.evaluate import run_story_evaluation
run_story_evaluation("weather_stories.md", "models/dialogue",
nlu_model_path=None,
max_stories=None,
out_file_plot="stories_evaluation.pdf")
In addition to supervised learning, Rasa Core supports a machine teaching approach where developers correct actions made by the system. It is a practical approach for generating training data, and exploring the space of plausible conversations efficiently.
In order to learn how this functionality works, you can run the cell and play with it.
from rasa_core import utils
from rasa_core.channels.console import ConsoleInputChannel
from rasa_core.interpreter import RegexInterpreter
logger = logging.getLogger(__name__)
def run_concertbot_online(input_channel, interpreter,
domain_file="weather_domain.yml",
training_data_file='weather_stories.md'):
agent = Agent(domain_file,
policies=[MemoizationPolicy(max_history=2), KerasPolicy()],
interpreter=interpreter)
training_data = agent.load_data(training_data_file)
agent.train_online(training_data,
input_channel=input_channel,
# batch_size=50,
epochs=2000)
#max_training_samples=30)
return agent
if __name__ == '__main__':
utils.configure_colored_logging(loglevel="INFO")
run_concertbot_online(ConsoleInputChannel(), RegexInterpreter())
Chatbots are gaining more popularity than ever and they are totally bringing new ways of how businesses run marketing. They have become the latest addition to every marketer’s bag of strategies, as being an early adopter can give you major advantage from customer support to lead generation.
Despite the hype, the chatbot development faces many constrains and drawbacks. With all the big companies of the world betting so heavily on AI, you would expect chatbots to be more intelligent by now. The truth is-they aren't. Building a bot that truly understands the depth and context of a conversation, and one that is capable enough to hold its ground in a long conversation has proved to be a challenging task. You may ask a bot 100 different questions and it will answer. But that is not a long conversation, is it? That is you trying to have 100 micro-conversations with a bot. Having 100 micro-conversations is not the same as having one long, meaningful conversation! For chatbots to go truly mainstream, we need to start having bots that can give the same kind of experience we get while talking to a friend. Unless we are able to enrichen the “conversational” aspect of the bot, the engagement will always be on the low side. And if the engagement is on the low side, a chatbot will become just a marketing dissemination tool, and not a growth driver — which it can potentially be.
A simple chatbot is not a challenging task as compared to complex chatbots. If you are planning to build a complex chatbot, you should seriously consider stability, scalability and flexibility aspects. If you don’t pay enough attention to the intricacies of the human language, a conversation can quickly go off the rails. You may be either required to build your own solution from scratch or use a combination of a tools for solving general NLP problems (i.e RASA) plus custom server side logic for more powerful features.
Just like building any other type of software product, building a chatbot is a continuous process. Developing a good chatbot is a lot of work. It requires everyone undertaking the project to challenge some of the misconception people commonly have around the chatbot technology. It also poses some development challenges that are unique to ML-enabled applications. Finally, developing a chatbot will require a great deal of planning. This planning involves everything from chatbot and auxiliary tools architecture to its integration with existing processes to strategies for making users accustomed to the chatbot faster.
Despite all its limitations and drawbacks, its definitelly worth trying to build and add an enterprise chatbots platform to your business.
2019-05-31 12:52:41.441911
2019-01-21 12:49:52.633478
2018-10-19 08:22:01.419442
2018-09-03 13:50:05.468625