Advancing AIML to build a chatbot


Before starting this, it is highly recommended the you go through the article Getting Started with AIML at OpenGenus. It will set you foundations right to understand this better.

In this article, we have explored some advanced concepts in AIML (Artificial Intelligence Markup Language) such as sets, maps, the '$' wildcard, loops, Rich Media Elements, buttons, hyperlinks, formatting and much more.

Now let us get started!

Sets and Maps

If you code in any other language, or are familiar with mathematics you have probably heard of these.

Sets
It is a collection of distinct well-defined objects.
To create a set, you need to make a .set file in the Sets folder.

Lets create a file named creators.set as containing

[
    ["Richard"],
    ["Aditya"],
    ["Priyanshi"],
    ["Richard Wallace"],
    ["Aditya Chatterjee"],
    ["Priyanshi Sharma"],
    ["Your Name Here"]
]

So we can use this set in our template as <set>creators</set>, where creators is the name of our set.

Take care-It is different from the set tag.

Add the following to your file.

 <category>
        <pattern>HAVE YOU HEARD OF <set>creators</set></pattern>
        <template>Yeah, I give them some credit to my existence!</template>
    </category>
    
    <category>
        <pattern>HAVE YOU HEARD OF *</pattern>
        <template>Not really</template>
    </category>

As you would've guessed, it identifies that whether there is an object that belongs to creators.set, the first category will be used, else the second one.

For instance :
rsz_sets

AIML also has some inbuilt sets when you use services like pandorabots, like number.

Maps
Maps refers to mapping, i.e. One element has a corresponding element.
If I write "b":"bin" so b is the key that corresponds to bin.

Just like sets you'll need to create a file with .map extension in the Maps folder.
Lets create creators.map as follows.

[
["Your Name Here", "using it."],
["Richard Wallace", "Created AIML"],
["Aditya Chatterjee", "Recommended and mentored my creation"],
["Priyanshi Sharma", "Created this chatbot"],
["Richard", "Created AIML"],
["Aditya", "Recommended and mentored my creation"],
["Priyanshi", "Created this chatbot"]
]

The value corresponing to element "x" in a map "y.map" maybe referred to as <map name="y">x</map>.
Add the following to see it in action.

<category>
        <pattern>HOW DID <set>creators</set> CONTRIBUTE</pattern>
        <template><map name="creators"><star/></map></template>
    </category>
    
    <category>
        <pattern>HOW DID * CONTRIBUTE</pattern>
        <template>I doubt that.</template>
    </category>

For instance:
rsz_maps

There are also inbuilt maps when you use services like pandorabots such as predecessor, successor etc.

The '$' wildcard

Adding the dollar symbol in the template, gives it greater priority. This is useful with conflicting templated.
== $ is the highest priority match.==

The order of priority for matches is
$ -> # -> _ -> Exact match -> name -> ^ -> *

For example:

<category>
        <pattern># AIML #</pattern>
        <template>I love AIML</template>
    </category>
    <category>
        <pattern>$WHAT IS AIML</pattern>
        <template>Artificial Intelligence Markup Language</template>
    </category>

This will result in something like as follows :
rsz_dollarwildcard

Writing loops

We need a <loop\> tag for the same. Did you notice, the this is a self closing tag? Then where does the body for the loop go?
It comes under the <condition>... <condition/> tag.

When I write it as follows

<condition....>
    Line 1
    Line 2
    <loop/>
</condition>

Untill condition specified isn't satisfied, it continues to loop as specified by <loop/>.

Lets teach our bot how to count!
Take note, this uses pandorabots' successor and number set. You can define them yourself separately if you are not using pandorabots.

    <category>
        <pattern>COUNT TO <set>number</set></pattern>
        <template>
            <!-- Creating variable with value 0 -->
            <think><set name="count">0</set></think>
            <!--Condition for, variable count to be equal to specified number-->
            <condition name="count">
                <!--Printing value-->
                <li><value><star/></value></li>
                <!--Incrementing value using successor and get-->
                <li>
                    <set name="count">
                        <!--Setting count, as the successor of count-->
                        <map name = "successor"><get name="count"/></map>
                    </set>
                    <break/> <!--Giving linebreak-->
                <loop/> <!--Forming a looping construct-->
                </li>
            </condition>
        </template>
    </category>

The above code is well illustrated with comments for your understanding.

The following is the expected behaviour.
rsz_loops

In any case, if you see too many loops in condition as output, you're probab;y running an infinite loop or a very long loop.

Try it yourself - Try printing different patterns using this to full understand loops.

Rich Media Elements

Sometimes it useful to have some quick obvious replies to some questions, that we don't really want to type. A chatbot can be extended to more such elements such as carousels, buttons, images et cetera. Lets see how!

Quick Replies

Lets suggest the user some replies.
It requires 2 tags, the <reply> tag, to specify the replies, within which we have a <text> tag to specify the reply text and the <postback> tag to tell the chatbot which category to go to.

For example, lets give our user some questions in the beginning. Add the following.

<category>
        <pattern>HI</pattern>
        <template>
            Hi! Some things you could ask me.
            <reply>
                <text>Roll a dice</text>
                <postback>ROLL A DICE</postback>
            </reply>
            <reply>
                <text>I could ask you some things if you like too!</text>
                <postback>ASK ME A QUESTION</postback>
            </reply>
        </template>
    </category>

This looks like as follows
QuickReplies

Buttons

You might notice that the choices go away as soon as the user clicks them, if you want to retain them, you might want to use buttons.
You need to use the <button> tag instead of the <reply> tag.

<category>
        <pattern>HELLO</pattern>
        <template>
            Hello! Some things you could ask me.
            <button>
                <text>Roll a dice</text>
                <postback>ROLL A DICE</postback>
            </button>
            <button>
                <text>I could ask you some things if you like too!</text>
                <postback>ASK ME A QUESTION</postback>
            </button>
        </template>
    </category>

You shall notice the difference and relevance as follows.

rsz_buttons

You can add hyperlinks by the help of <link> tag, it shall contain the <text> tag and <url> tag, where the text written is linked to the URL mentioned.

<category>
        <pattern>WHERE IS OPENGENUS</pattern>
        <template>
            <link>
                <text>Right here!(Click me)</text>
                <url>iq.opengenus.org</url>
            </link>
        </template>
    </category>

It works as follows
rsz_link

If you directly use the <url> tag, you will be able to make it clickable, with the text of the url itself.

Try it yourself- Look for cards, images, carousels, videos etc. in Rich Media elements. (Refer documentation)

Formatting

We've unknowingly or knowingly used some of it.

  • <break>- Gives a linebreak!
  • <split>- Splits a message into multiple messages.
  • <delay>- Delays the sending of message, gives an effect of the typing or thinking.

Try this:

<category>
        <pattern>CAN YOU SPEAK A B C</pattern>
        <template>
            <reply>
                <text>Separate messages</text>
                <postback>CAN YOU SPEAK A B C IN SEPARATE MESSAGES</postback>
            </reply>
            <reply>
                <text>Taking my time</text>
                <postback>CAN YOU SPEAK A B C TAKING YOUR TIME</postback>
            </reply>
            <reply>
                <text>In one shot!</text>
                <postback>CAN YOU SPEAK A B C AT ONCE</postback>
            </reply>
        </template>
    </category>
    
    <category>
        <pattern>CAN YOU SPEAK A B C IN SEPARATE MESSAGES</pattern>
        <template>
            A<split/>
            B<split/>
            C
        </template>
    </category>
    
    <category>
        <pattern>CAN YOU SPEAK A B C TAKING YOUR TIME</pattern>
        <template>
            A<delay>2</delay> <!--Giving 2 seconds delay-->
            B<delay>2</delay>
            C
        </template>
    </category>
    
    <category>
        <pattern>CAN YOU SPEAK A B C AT ONCE</pattern>
        <template>
            A<break/>
            B<break/>
            C
        </template>
    </category>

You may observe the following
Formatting

More Tags

There more tags than what you have been seeing, or what you have been thinking too! Lets set this straight by learning about some more tags!

Date - Referred to as the <date/> tag , it reverts the date. You can also refer specific parts of the date using 'format'. For example <date format="%A"/> returns the day. Refer documentation for more formats, timezones etc.

<category>
        <pattern>WHAT IS THE DATE TODAY</pattern>
        <template>Today is <date/></template>
    </category>
    
    <category>
        <pattern>WHAT DAY IT IS</pattern>
        <template>Today is <date format="%A"/></template>
    </category>

rsz_date

Normalize and Denormalize - See the Substitutions folder in your directory.
It substitutes certain words, Eg. '.org' becomes 'dot org'. This is called normalisation here. When you don't what this to happen you can enclose your value is <denormalize>...</denormalize> tags. Go to Gender in substitution too. It can be referred as <gender>...</gender> and can be useful un building conversations. Try it yourself.

Input
AIML can keep track of inputs, and so can tell you what the user said, just said, of said previously with the <input/> tag, how back shall it go maybe specified by 'index'

Response
AIML can also keep track of outputs, so can tell what it said to, using <response/> tag.

<category>
        <pattern>WHAT DID I JUST SAY</pattern>
        <template>
            You said <input index="2"/> 
            <learn>
                <category>
                    <pattern>WHAT DID YOU REPLY</pattern>
                        <template>I replied <response index="2"/></template>
                </category>
            </learn>
        </template>
    </category>

rsz_inputresponse

Now that you have learnt some tags without explicitly getting to know any new concepts, you must be ready to take on more and more tags. Strive for functionality and make your bot interesting and practical!
You should be able to refer documentation to make your own bots and explore possibilities in AIML.
You are highly recommended to refer the documentation and widen your horizons to make your bot.

With this article at OpenGenus, you must have the complete idea of AIML to build a chatbot. Go ahead! Put your knowledge to action!