Defining AIML categories inline

Instead of loading an external AIML DB, it is also possible to create a bot from scratch by executing notebook cells containing AIML code. This notebook offers a few examples.

Full AIML

The most direct procedure is to add a fully-compliant AIML document in a cell, preceded by the %aiml magic. This magic must be present alone in the first cell line, save for comment lines, i.e. lines starting with # (which are ignored).

The XML preamble is optional; if missing it will be added automatically. Encoding is always UTF-8

In [1]:
%aiml
# Receiving a greeting and answering back

<?xml version="1.0" encoding="utf-8"?>
<aiml version="1.0">
  
  # The "good NNN" greeting allows us to infer the time of the day
  <category>
    <pattern>GOOD *</pattern>
    <template>
      <think><set name="tod"><star/></set></think>
      <srai>HI</srai>
    </template>
  </category>

  # A Hello greeting is less defining
  <category>
    <pattern>HELLO</pattern>
    <template><srai>HI</srai></template>
  </category>

  # This is the template creating the greeting response
  <category>
    <pattern>HI</pattern>
    <template>
      <random>
        <li>Hi there</li>
        <li>Hello</li>
        <li>
           <condition name="tod">
             <li value="morning">Good morning</li>
             <li value="afternoon">Good afternoon</li>
             <li value="evening">Good evening</li>
             <li value="night">Good night</li>
             <li>Hello</li>
           </condition>
        </li>
      </random>
    </template>
  </category>

</aiml>
Loaded 3 new patterns

There can also be comment lines within the AIML document; they are ignored (of course, given that AIML is XML, we can also add comments as XML comments)

Test it

In [2]:
Good morning
Good morning
In [3]:
Hello
Good morning

We can inspect the session predicates, to check the "tod" (time-of-day) predicate that was (supposedly) assigned

In [4]:
%show session
Session fields:
tod = morning

Simplified AIML

Given that XML is rather verbose, a slightly simplified syntax is also possible by removing the outer wrapper tags: <aiml>, <category>, <pattern>, <template>.

This mode is automatically triggered if the first non-comment & non-empty line of an %aiml cell does not begin with an XML tag (i.e. an angle bracket element). In this mode:

  • categories are separated by blank lines (at least one, any amount of them)
  • within a category, the first line is always the pattern
  • all the remaining lines are joined together to form the template
  • except if the second line starts with <that>, in which case this line is considered as a pattern-side THAT and the template is formed by all lines starting from the third. There is no need to close the <that> element in the second line
  • the template must be proper AIML code, with all the necessary AIML tags, closed as necessary

As an example, the following cell contains exactly the same AIML code as the one above in the "full AIML" format. In fact, if we execute it the answer will be loaded 0 new patterns, since those patterns were already defined above and hence they are already in the bot (if we execute a %forget cell before, then they will be loaded new).

As an additional bonus, automatic normalization (uppercasing and punctuation removal) is done on patterns and on text fragments of <srai> elements, so we can use "normal" text there.

If you want to include the defined categories within a topic, use the topic name as an additional parameter to the header magic, i.e.

  %aiml <topicname>
In [5]:
%aiml

  
# The "good NNN" greeting allows us to infer the time of the day
good *
<think><set name="tod"><star/></set></think>
<srai>HI</srai>

# A Hello greeting is less defining
hello
<srai>hi</srai>

# This is the template creating the greeting response
hi
<random>
   <li>Hi there</li>
   <li>Hello</li>
   <li>
      <condition name="tod">
        <li value="morning">Good morning</li>
        <li value="afternoon">Good afternoon</li>
        <li value="evening">Good evening</li>
        <li value="night">Good night</li>
        <li>Hello</li>
      </condition>
   </li>
</random>
Loaded 0 new patterns

Test again

In [6]:
good morning
Hi there

Updating pattern space

Every %aiml cell executed adds to the existing categories, so that the current state of the brain is the sum of all executed %aiml cells (plus the categories added via %load or %learn magics).

So we can now add new categories:

In [7]:
%aiml

# Note we use the full form, since substitution patterns will have "what's" expanded
# We refer this to the HI category defined above
what is up
<srai>hi</srai>
Loaded 1 new patterns
In [8]:
what's up?
Hello

We can modify an existing category. It will say loaded 0 new patterns because the pattern already existed, but the result will be modified

In [9]:
%aiml

hello
How do you do?
Loaded 0 new patterns
In [10]:
hello
How do you do?

However we cannot delete an existing pattern (the most we can do is assign an empty output to it). Currently the only way to completely remove it is to execute a %forget cell and then re-execute all notebook cells defining AIML (%aiml, %load, %learm).

Saving/loading bots

Saving full bot state

The %save & %load commands can be used to save to disk and load from it the full bot state (optionally we can omit saving/loading part of this state)

In [11]:
%save myexample.bot
Saving session predicates... 1 predicates
Saving bot predicates... 1 predicates
Saving subbers for person2 ... 9 subs
Saving subbers for gender ... 8 subs
Saving subbers for normal ... 59 subs
Saving subbers for person ... 13 subs
Saving brain to myexample.brain... done (0.01 seconds)
Writing main bot file: myexample.ini
Packing into: myexample.bot

The saving process by default creates one *.bot file. This is a ZIP file with two files inside:

  • A .ini file that contains session predicates, bot predicates and all substitution strings. Plus a pointer to the brain file.
  • A .brain file that contains the bot categories, in a compiled form

There is a variant, indicated by the rawfiles option, in which those two files are left unpacked.

The saved state can be now loaded back by using the %load command

In [12]:
%forget
Resetting bot brain
In [13]:
%load myexample
Opening: myexample.bot
Loading session predicates... 1 predicates
Loading bot predicates... 1 predicates
Loading subs for person2 ... 9 subs
Loading subs for gender ... 8 subs
Loading subs for normal ... 59 subs
Loading subs for person ... 13 subs
Loading brain from /tmp/myexample.brain... done (4 categories in 0.00 seconds)

%save and %load accept additional parameters that make them skip saving/loading part of the data: noses, nobot, nosub, nobrain. They can be mixed freely

In [14]:
%show session 
Session fields:
tod = morning

Saving AIML rules

A final option for reusing the AIML cells in other notebooks (or other systems) is to use the %record magic. This command has three forms:

  • %record on starts saving. All AIML cells executed afterwards will be kept in a special list
  • %record save <name> saves all cells stored so far as an AIML file (the .aiml suffix is added automatically)
  • %record off stops saving AIML cells and cleans up all cells stored in memory

Note that only the AIML cells since %record on was executed will be saved. Rules loaded via %learn or %load commands will not be included.

In [15]:
%record on
Record activated
In [16]:
%aiml

# Note we use the full form, since substitution patterns will have "what's" expanded 
what is up
Howdy
Loaded 0 new patterns
In [17]:
%aiml

<category>
  <pattern>HI</pattern>
  <template>Hello</template>
</category>
Loaded 0 new patterns
In [18]:
%record save aimlexample 
Record saved to "aimlexample.aiml" (2 cells)
In [19]:
%record off
Record deactivated

AIML files saved can be loaded again with the %learn magic. They can also be used in any system that understands AIML 1.0

In [20]:
%forget
Resetting bot brain
In [21]:
%learn aimlexample.aiml
Learning patterns in "aimlexample.aiml"
Loading aimlexample.aiml... done (0.00 seconds)
Loaded 2 new patterns
In [22]:
Hi
Hello

This definition of AIML categories done inline in notebook cells can also be done on top of a bot loaded via %learn or %load. See 04-chatbot-alice-augment for an example.

Version: 1.0 (2016-07-19)
Author: Paulo Villegas