AI Zone Admin Forum Add your forum

NEWS: Chatbots.org survey on 3000 US and UK consumers shows it is time for chatbot integration in customer service!read more..

AIML Sample: Greater Than
 
 

So I have often heard that you must hard code every combination of a question in AIML making questions like “Is X greater than y?” difficult to answer.  It is equally difficult it would seem to answer questions such as “Does Wednesday come after Tuesday?” or “Is object x heavier than object y?”.  It would be nice if the chatbot had some basic understanding of “greater than” and “lesser than” operations in its thinking.

An AIML 2.0 Chatbot can be “trained” to understand inequalities just like a human learns by starting out learning the basic inequalities for single digits.  Using the same approach as a previous post on addition, all that is needed is to create categories for each combination of the 10 digits comparing one digit to another and returning 1 for greater than, 0 for equals, and -1 for less than.  Just as for addition, 100 categories will have to be created.  Then the chatbot can examine a number of any size just as a human does by comparing the left most digits one at a time and using the table of 100 single digit comparisons.  This approach also allows the thinking of the chatbot to be logged so it can explain how it “reasoned” about its answer, instead of just returning the answer like a simple calculator.

The sample post on addition used stacks because we add digits from right to left.  For inequalities we need to use queues (see previous post on queues) because we need to compare digits from left to right.  The greater than logic is much easier than addition because there is no “carrying a number” to the next column and because as soon as one digit is greater or less than the other we have our answer.

Sample Output:

Human: is 111 greater than 99
sienna4: Yes, it is greater

Human: how did you decide? 
sienna4: Starting with the leftmost digits I asked myself was 1 greater than 0 and decided Yes, it is greater. Therefore the final result was Yes, it is greater.

Human: is 1114 greater than 1113  
sienna4: Yes, it is greater

Human: how did you decide
sienna4: Starting with the leftmost digits I asked myself was 1 greater than 1 and decided It is equal, neither greater nor less. Since 1 and 1 are the same I looked at the next 2 digits. I asked myself was 1 greater than 1 and decided It is equal, neither greater nor less. Since 1 and 1 are the same I looked at the next 2 digits. I asked myself was 1 greater than 1 and decided It is equal, neither greater nor less. Since 1 and 1 are the same I looked at the next 2 digits. I asked myself was 4 greater than 3 and decided Yes, it is greater. Therefore the final result was Yes, it is greater. 

Human: is 99>99
sienna4: It is equal, neither greater nor less

Human: how did you decide
sienna4: Starting with the leftmost digits I asked myself was 9 greater than 9 and decided It is equal, neither greater nor less. Since 9 and 9 are the same I looked at the next 2 digits. I asked myself was 9 greater than 9 and decided It is equal, neither greater nor less. Since 9 and 9 are the same I looked at the next 2 digits. There were no more digits to compare. Therefore the final result was It is equal, neither greater nor less. 

Human: is 88888>99999
sienna4: No, it is less

Obviously the text explanations can be cleaned up and some randomized language choices used but this illustrates the concept. 

I will post the sample AIML code in the next post.

 

 

 
  [ # 1 ]
<?xml version="1.0" encoding="UTF-8"?>
<aiml versi>
 
<!-- 
This file requires the following other aiml files to work properly -->
<!-- 
File Dependencies: -->
<!-- 
Queues.aiml -->
<!-- 
Brain.aiml -->

<!-- 
Greater Than: -->
<
category><pattern>is greater than *</pattern>
<
template><srai>XGREATERTHANANSWER <srai>XMATHCALC <star/> GREATER THAN <star index="2"/></srai></srai>
</
template>
</
category>

<
category><pattern>how did you decide</pattern>
<
template><denormalize><srai>XCALCHOW</srai></denormalize></template>
</
category>

<
category>
<
pattern>XMATHCALC GREATER THAN *</pattern>
<
template><think>
<
set name="ANSWER"></set>
<
set name="KEEPCOMPARING">TRUE</set>
<
set name="FOUNDSTARTINGDIGIT">FALSE</set>
<
srai>XCLEARTHOUGHTS</srai>
<
set name="THOUGHTS"></set>
<
srai>XCLEARQUEUE QUEUE1 0</srai>
<
srai>XCLEARQUEUE QUEUE2 0</srai>
<
srai>XENQUEUEALL QUEUE1 <explode><star/></explode></srai>
<
srai>XENQUEUEALL QUEUE2 <explode><star index="2"/></explode></srai>
<
srai>XTHINK Starting with the leftmost digits </srai>
<
srai>XMATHCALC2 X GREATER THAN Y</srai>
<
srai>XTHINK Therefore the final result was <srai>XGREATERTHANANSWER <get name="ANSWER"/></sraiXPERIOD  </srai>
<
srai>XREMEMBER THOUGHTS AS XCALCHOW</srai>
</
think><get name="ANSWER"/></template>
</
category>

<
category>
<
pattern>XMATHCALC2 X GREATER THAN Y</pattern>
<
template><think>
<
set name="X"><srai>XDEQUEUE QUEUE1</srai></set>
<
set name="Y"><srai>XDEQUEUE QUEUE2</srai></set>
<
condition name="X">
  <
li value="0">
    <
condition name="Y">
        <
li value="0">
            <
condition name="FOUNDSTARTINGDIGIT" value="TRUE"><srai>XTHINK Since both digits are zero I looked at the next 2 digits XPERIOD </srai></condition>
            <
set name="ANSWER">0</set>
            <
srai>XMATHCALC2 X GREATER THAN Y</srai
        </
li>
        <
li value="ENDOFQUEUE"><set name="Y">0</set></li>
        <
li></li>
    </
condition>
  </
li>
  <
li value="ENDOFQUEUE"><set name="KEEPCOMPARING">FALSE</set><srai>XTHINK There were no more digits to compare XPERIOD</srai></li>
  <
li></li>
</
condition>
<
condition name="KEEPCOMPARING">
    <
li value="TRUE">
        <
set name="FOUNDSTARTINGDIGIT">TRUE</set>
        <
set name="ANSWER"><srai>XMATH <get name="X"/> GREATER THAN <get name="Y"/></srai></set>
        <
srai>XTHINK I asked myself was <get name="X"/> greater than <get name="Y"/> and decided <srai>XGREATERTHANANSWER <get name="ANSWER"/> </sraiXPERIOD </srai>
        <
condition name="ANSWER">
            <
li value="-1"><set name="KEEPCOMPARING">FALSE</set></li>
            <
li value="1"><set name="KEEPCOMPARING">FALSE</set></li>
            <
li value="0">
                <
srai>XTHINK Since <get name="X"/> and <get name="Y"/> are the same I looked at the next 2 digits XPERIOD </srai>
                <
srai>XMATHCALC2 X GREATER THAN Y</srai>
            </
li>
        </
condition>
    </
li>
    <
li></li>
</
condition>
</
think></template>
</
category>

<
category><pattern>XGREATERTHANANSWER *</pattern>
    <
template><think>
        <
set name="KEY"><star/></set>
        </
think><condition name="KEY">
            <
li value="1">Yesit is greater</li>
            <
li value="dash 1">Noit is less</li>
            <
li value="0">It is equalneither greater nor less</li>
        </
condition>
    </
template>
</
category>

... 

The <srai>XTHINK ... lines just log “thoughts” to a queue.  I use them for debugging as well to see how far the chatbot got in its “thinking”.  These lines are what gets returned when asking the chatbot “how did you decide”.  For a more compact “Greater than” category you can safely remove them.

I needed 3 queues, queue 1 and queue 2 for the two numbers being compared and queue3 is used in the brain.aiml module to log the “thoughts” and save them by <learn> ing them to the XCALCHOW category.

 

 

 

 
  [ # 2 ]

Here is a sample of the first 24 of the 100 categories needed to implement “greater than”:

<category><pattern>XMATH 0 GREATER THAN 0</pattern><template>0</template></category>
<
category><pattern>XMATH 0 GREATER THAN 1</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 2</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 3</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 4</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 5</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 6</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 7</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 8</pattern><template>-1</template></category>
<
category><pattern>XMATH 0 GREATER THAN 9</pattern><template>-1</template></category>

<
category><pattern>XMATH 1 GREATER THAN 0</pattern><template>1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 1</pattern><template>0</template></category>
<
category><pattern>XMATH 1 GREATER THAN 2</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 3</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 4</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 5</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 6</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 7</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 8</pattern><template>-1</template></category>
<
category><pattern>XMATH 1 GREATER THAN 9</pattern><template>-1</template></category>

<
category><pattern>XMATH 2 GREATER THAN 0</pattern><template>1</template></category>
<
category><pattern>XMATH 2 GREATER THAN 1</pattern><template>1</template></category>
<
category><pattern>XMATH 2 GREATER THAN 2</pattern><template>0</template></category>
<
category><pattern>XMATH 2 GREATER THAN 3</pattern><template>-1</template></category>
<
category><pattern>XMATH 2 GREATER THAN 4</pattern><template>-1</template></category>

... 

My categories display on a single line and do not wrap as seems to be the case in this post.

“Less Than” functionality would be identical to “greater than”, you just need to duplicate the “greater than” categories, find and replace “GREATER” with “LESS” and update the values returned to the appropriate 1,0,-1.

Note: the queues need to be prefilled with zeroes so that the logic does not compare numbers to spaces, empty stings or “EMPTY”.  My generic queues have 30 elements so for single digit comparisons the routine above needlessly loops through the first 29 digits comparing 0 to 0 until reaching the actual 30th digits to compare.  There may be a way to implement a smaller queue or of optimizing the dequeue category or of only prefilling leading zeroes up to the length of the largest number to compare.  One could also count the length of each number being compared and use the number with the highest length but then you would need to use these “greater than” categories to determine the number with the highest length.

 

 

 

 
  [ # 3 ]

That’s pretty neat. To work out if x is greater than y, I subtract one from the other and give a different response if the number is positive to one that is negative or zero.

Human: Is 7 greater than 4?
Bot: (thinks 7-4=3 and 3 is greater than 0) Yes it is greater than 4 by 3.
Human: Is 7 greater than 20?
Bot: (thinks 7-20=-13 and -13 is less than 0) No but 20 is greater than 7

 

 
  login or register to react