AI Chat Bot in Python with AIML

Overview

Intro

Artificial intelligence chat bots are easy to write in Python with the AIML package. AIML stands for Artificial Intelligence Markup Language, but it is just simple XML. These code examples will walk you through how to create your own artificial intelligence chat bot using Python.

What is AIML?

AIML was developed by Richard Wallace. He made a bot called A.L.I.C.E. (Artificial Linguistics Internet Computer Entity) which won several artificial intelligence awards. Interestingly, one of the Turing tests to look for artificial intelligence is to have a human chat with a bot through a text interface for several minutes and see if they thought it was a human. AIML is a form of XML that defines rules for matching patterns and determining responses.

For a full AIML primer, check out Alice Bot's AIML Primer. You can also learn more about AIML and what it is capable of on the AIML Wikipedia page. We will create the AIML files first and then use Python to give it some life.

Create Standard Startup File

It is standard to create a startup file called std-startup.xml as the main entry point for loading AIML files. In this case we will create a basic file that matches one pattern and takes one action. We want to match the pattern load aiml b, and have it load our aiml brain in response. We will create the basic_chat.aiml file in a minute.

<aiml version="1.0.1" encoding="UTF-8">
    <!-- std-startup.xml -->

    <!-- Category is an atomic AIML unit -->
    <category>

        <!-- Pattern to match in user input -->
        <!-- If user enters "LOAD AIML B" -->
        <pattern>LOAD AIML B</pattern>

        <!-- Template is the response to the pattern -->
        <!-- This learn an aiml file -->
        <template>
            <learn>basic_chat.aiml</learn>
            <!-- You can add more aiml files here -->
            <!--<learn>more_aiml.aiml</learn>-->
        </template>
       
    </category>

</aiml>

Creating an AIML File

Above we created the AIML file that only handles one pattern, load aiml b. When we enter that command to the bot, it will try to load basic_chat.aiml. It won't work unless we actually create it. Here is what you can put inside basic_chat.aiml. We will match two basic patterns and respond.

<aiml version="1.0.1" encoding="UTF-8">
<!-- basic_chat.aiml -->

    <category>
        <pattern>HELLO</pattern>
        <template>
            Well, hello!
        </template>
    </category>
   
    <category>
        <pattern>WHAT ARE YOU</pattern>
        <template>
            I'm a bot, silly!
        </template>
    </category>
   
</aiml>

Random Responses

You can also add random responses like this. This one will respond randomly when it receives a message that starts with "One time I ". The * is a wildcard that matches anything.

<category>
    <pattern>ONE TIME I *</pattern>
    <template>
        <random>
            <li>Go on.</li>
            <li>How old are you?</li>
            <li>Be more specific.</li>
            <li>I did not know that.</li>
            <li>Are you telling the truth?</li>
            <li>I don't know what that means.</li>
            <li>Try to tell me that another way.</li>
            <li>Are you talking about an animal, vegetable or mineral?</li>
            <li>What is it?</li>
        </random>
    </template>
</category>

Use Existing AIML Files

It can be fun to write your own AIML files, but it can be a lot of work. I think it needs around 10,000 patterns before it starts to feel realistic. Fortunately, the ALICE foundation provides a number of AIML files for free. Browse the AIML files on the Alice Bot website. There was one floating around before called std-65-percent.xml that contained the most common 65% of phrases. There is also one that lets you play BlackJack with the bot.

Install Python AIML Module

So far, everything has been AIML XML files. All of that is important and will make up the brain of the bot, but it's just information right now. The bot needs to come to life. You could use any language to implement the AIML specification, but some nice person has already done that in Python.

Install the aiml package first with pip or download from https://pypi.python.org/pypi/aiml/.

pip install aiml

Note that the aiml package only works with Python 2. Py3kAiml on GitHub is a Python 3 alternative.

Simplest Python Program

This is the simplest program we can start with. It creates the aiml object, learns the startup file, and then loads the rest of the aiml files. After that, it is ready to chat, and we enter an infinite loop that will continue to prompt the user for a message. You will need to enter a pattern the bot recognizes. The patterns recognized depend on what AIML files you loaded.

We create the startup file as a separate entity so that we can add more aiml files to the bot later without having to modify any of the programs source code. We can just add more files to learn in the startup xml file.

import aiml

# Create the kernel and learn AIML files
kernel = aiml.Kernel()
kernel.learn("std-startup.xml")
kernel.respond("load aiml b")

# Press CTRL-C to break this loop
while True:
    print kernel.respond(raw_input("Enter your message >> "))

Speeding up Brain Load

When you start to have a lot of AIML files, it can take a long time to learn. This is where brain files come in. After the bot learns all the AIML files it can save its brain directly to a file which will drastically speed up load times on subsequent runs.

import aiml
import os

kernel = aiml.Kernel()

if os.path.isfile("bot_brain.brn"):
    kernel.bootstrap(brainFile = "bot_brain.brn")
else:
    kernel.bootstrap(learnFiles = "std-startup.xml", commands = "load aiml b")
    kernel.saveBrain("bot_brain.brn")

# kernel now ready for use
while True:
    print kernel.respond(raw_input("Enter your message >> "))

Reloading AIML While Running

You can send the load message to the bot while it is running and it will reload the AIML files. Keep in mind that if you are using the brain method as it is written above, reloading it on the fly will not save the new changes to the brain. You will either need to delete the brain file so it rebuilds on the next startup, or you will need to modify the code so that it saves the brain at some point after reloading. See the next section on creating Python commands for the bot to do that.

load aiml b

Adding Python Commands

If you want to give your bot some special commands that run Python functions, then you should capture the input message to the bot and process it before sending it to kernel.respond(). In the example above we are getting user input from raw_input. We could get our input from anywhere though. Perhaps a TCP socket, or a voice-to-text source. Process the message before it goes through AIML. You may want to skip the AIML processing on certain messages.

while True:
    message = raw_input("Enter your message to the bot: ")
    if message == "quit":
        exit()
    elif message == "save":
        kernel.saveBrain("bot_brain.brn")
    else:
        bot_response = kernel.respond(message)
        # Do something with bot_response

Sessions and Predicates

By specifying a session, the AIML can tailor different conversations to different people. For example, if one person tells the bot their name is Alice, and the other person tells the bot their name is Bob, the bot can differentiate the people. To specify which session you are using you pass it as a second parameter to respond().

sessionId = 12345
kernel.respond(raw_input(">>>"), sessionId)

This is good for having personalized conversations with each client. You will have to generate your own session Id some how and track them. Note that saving the brain file does not save all the session values.

sessionId = 12345

# Get session info as dictionary. Contains the input
# and output history as well as any predicates known
sessionData = kernel.getSessionData(sessionId)

# Each session ID needs to be a unique value
# The predicate name is the name of something/someone
# that the bot knows about in your session with the bot
# The bot might know you as "Billy" and that your "dog" is named "Brandy"
kernel.setPredicate("dog", "Brandy", sessionId)
clients_dogs_name = kernel.getPredicate("dog", sessionId)

kernel.setBotPredicate("hometown", "127.0.0.1")
bot_hometown = kernel.getBotPredicate("hometown")

In the AIML we can set predicates using the set response in template.

<aiml version="1.0.1" encoding="UTF-8">
   <category>
      <pattern>MY DOGS NAME IS *</pattern>
      <template>
         That is interesting that you have a dog named <set name="dog"><star/></set>
      </template> 
   </category> 
   <category>
      <pattern>WHAT IS MY DOGS NAME</pattern>
      <template>
         Your dog's name is <get name="dog"/>.
      </template> 
   </category> 
</aiml>

With the AIML above you could tell the bot:

My dogs name is Max

And the bot will respond with

That is interesting that you have a dog named Max

And if you ask the bot:

What is my dogs name?

The bot will respond:

Your dog's name is Max.

Additional References