[box type=”note” align=”” class=”” width=””]This article is an excerpt taken from a book Natural Language Processing with Python Cookbook written by Krishna Bhavsar, Naresh Kumar, and Pratap Dangeti. This book includes unique recipes to teach various aspects of performing Natural Language Processing with NLTK—the leading Python platform for the task.[/box]
Today we will learn to create a conversational assistant or chatbot using Python programming language.
Conversational assistants or chatbots are not very new. One of the foremost of this kind is ELIZA, which was created in the early 1960s and is worth exploring. In order to successfully build a conversational engine, it should take care of the following things:
1. Understand the target audience
2. Understand the natural language in which communication happens.
3. Understand the intent of the user
4. Come up with responses that can answer the user and give further clues
NLTK has a module, nltk.chat, which simplifies building these engines by providing a generic framework.
Let’s see the available engines in NLTK:
Engines | Modules |
Eliza | nltk.chat.eliza Python module |
Iesha | nltk.chat.iesha Python module |
Rude | nltk.chat.rudep ython module |
Suntsu | Suntsu nltk.chat.suntsu module |
Zen | nltk.chat.zen module |
In order to interact with these engines we can just load these modules in our Python program and invoke the demo()
function.
This recipe will show us how to use built-in engines and also write our own simple conversational engine using the framework provided by the nltk.chat module.
Getting ready
You should have Python installed, along with the nltk library. Having an understanding of regular expressions also helps.
How to do it…
- Open atom editor (or your favorite programming editor).
- Create a new file called Conversational.py.
- Type the following source code:
- Save the file.
- Run the program using the Python interpreter.
- You will see the following output:
How it works…
Let’s try to understand what we are trying to achieve here.
import nltk
This instruction imports the nltk library into the current program.
def builtinEngines(whichOne):
This instruction defines a new function called builtinEngines that takes a string parameter, whichOne:
if whichOne == 'eliza': nltk.chat.eliza.demo()
elif whichOne == 'iesha': nltk.chat.iesha.demo()
elif whichOne == 'rude': nltk.chat.rude.demo()
elif whichOne == 'suntsu': nltk.chat.suntsu.demo()
elif whichOne == 'zen': nltk.chat.zen.demo()
else:
print("unknown built-in chat engine {}".format(whichOne))
These if, elif, else instructions are typical branching instructions that decide which chat engine’s demo()
function is to be invoked depending on the argument that is present in the
whichOne
variable. When the user passes an unknown engine name, it displays a message to the user that it’s not aware of this engine.
It’s a good practice to handle all known and unknown cases also; it makes our programs more robust in handling unknown situations def myEngine():
. This instruction defines a new function called
myEngine()
; this function does not take any parameters.
chatpairs = (
(r"(.*?)Stock price(.*)", ("Today stock price is 100",
"I am unable to find out the stock price.")), (r"(.*?)not well(.*)",
("Oh, take care. May be you should visit a doctor", "Did you take some medicine ?")),
(r"(.*?)raining(.*)",
("Its monsoon season, what more do you expect ?", "Yes, its good for farmers")),
(r"How(.*?)health(.*)",
("I am always healthy.",
"I am a program, super healthy!")), (r".*",
("I am good. How are you today ?", "What brings you here ?"))
)
This is a single instruction where we are defining a nested tuple data structure and assigning it to chat pairs. Let’s pay close attention to the data structure:
- We are defining a tuple of tuples
- Each subtuple consists of two elements:
- The first member is a regular expression (this is the user’s question in regex format)
- The second member of the tuple is another set of tuples (these are the answers)
def chat():
print("!"*80)
print(" >> my Engine << ")
print("Talk to the program using normal english") print("="*80)
print("Enter 'quit' when done")
chatbot = nltk.chat.util.Chat(chatpairs, nltk.chat.util.reflections)
chatbot.converse()
We are defining a subfunction called chat()
inside the myEngine()
function. This is permitted in Python. This chat()
function displays some information to the user on the screen and calls the nltk built-in nltk.chat.util.Chat()
class with the chatpairs variable. It passes nltk.chat.util.reflections as the second argument. Finally we call the chatbot.converse()
function on the object that’s created using the chat()
class.
chat()
This instruction calls the chat()
function, which shows a prompt on the screen and accepts the user’s requests. It shows responses according to the regular expressions that we have built before:
if name
== ' main ':
for engine in ['eliza', 'iesha', 'rude', 'suntsu', 'zen']:
print("=== demo of {} ===".format(engine)) builtinEngines(engine)
print() myEngine()
These instructions will be called when the program is invoked as a standalone program (not using import). They do these two things:
- Invoke the built-in engines one after another (so that we can experience them)
- Once all the five built-in engines are excited, they call our
myEngine()
, where our customer engine comes into play
We have learned to create a chatbot of our own using the easiest programming language ‘Python’. To know more about how to efficiently use NLTK and implement text classification, identify parts of speech, tag words, etc check out Natural Language Processing with Python Cookbook.