[alicebot-style] Super-matching with the underscore: an example app

Dirk Scheuring alicebot-style@list.alicebot.org
Thu, 19 Sep 2002 19:05:40 +0100


<?xml version="1.0" encoding="ISO-8859-1"?>

<aiml version="1.0">


<!-- This program is open source code released under -->
<!-- the terms of the GNU General Public License -->
<!-- as published by the Free Software Foundation. -->


<!-- meta name="author" content="Dirk Scheuring" -->
<!-- meta name="language" content="en" -->

<!-- last change: 020919 -->

<!-- XAIML FUZZY DECISION OBJECT -->

<!-- Objective: Say you want the general ability for your bot to ask the client to decide what to do next. -->
<!-- You want it to react to more than simple "Yes" and "No" inputs, though. -->
<!-- You want it to interpret "Alright", "I think so" and all the other ways of verbally agreeing with someone as meaning POSITIVE, too -->
<!-- And "Leave me out of that, sister", "Don´t do that", and similar inputs should be interpreted as NEGATIVE. -->
<!-- Furthermore, the bot should recognize when the client is UNDECIDED about something, adding "Don´t know", "I´m not sure" and the like to the set. -->
<!-- Finally, you want to have a distinct behavior in cases where the client says something unrelated, i.e. not covered by the set -->
<!-- (That gives you the possibility for "character reactions", like "Hey! You´re dodging my questions!") -->

<!-- Problem: Doing the above using <that/> is possible, but extremely cumbersome. -->
<!-- You may find that you want to work with several hundred patterns. -->
<!-- Which means that every time your bot asks a client for a decision, you have to insert <that/>-equipped categories for all possibilities. -->
<!-- If you want the bot to randomly phrase the same question in different ways, or add new ways for the client to express her reply, the problem gets even bigger. -->

<!-- Solution: Use <topic>, together with the _underscore, to treat yourself to a reusable FUZZY DECISION OBJECT. -->
<!-- That way, you have to write just five categories for each new question: -->
<!-- The one where the bot asks the question, and four to react to the possible outputs POSITIVE, NEGATIVE, UNDECIDED, and UNKNOWN -->
<!-- The rest is handled by your new-fangled XAIML object. -->

<!-- TEST QUESTION -->

<!-- Here´s the type of category with which the bot asks the client to decide on something. -->
<!-- We _could_ use another <srai> to factor out the setting of "oldtopic" and "topic" here, because the same code gets used by any category of that type, which differ only in the "decision" value they set. Then again, we don´t need do that. -->

<category>
<pattern>TEST CLIENTDECISION</pattern>
<template>
<think>
<set name="oldtopic"><get name="topic"/></set>
<set name="topic">CLIENTDECISION INTERFACE</set>
<set name="decision">CLIENTDECISION TEST</set>
</think>
Do you want to do a deciding test now?
</template>
</category>

<!-- Next up are the four categories that respond to the input values POSITIVE. NEGATIVE, UNDECIDED, and UNKNOWN. -->
<!-- They have to be enclosed in a <topic>, and the value of that "topic" has to be the same as the value that "decision" was set to in the "question category" -->

<topic name="CLIENTDECISION TEST">

<category>
<pattern>CLIENTDECISION POSITIVE</pattern>
<template>
<srai>END CLIENTDECISION</srai>
You´re really quite helpful. Thank you. 
</template>
</category>

<category>
<pattern>CLIENTDECISION NEGATIVE</pattern>
<template>
<srai>END CLIENTDECISION</srai>
You´re a bit uncooperative. But you make for a terrific test subject. 
</template>
</category>

<category>
<pattern>CLIENTDECISION UNDECIDED</pattern>
<template>
<random>
<li>Indecision is for the birds, really. Yes or No? </li>
<li>A well-behaved bot should let you get away with that. But not me. No, or Yes? </li>
<li>Ah, you just gots to decide now, <get name="name"/>! </li>
</random>
<srai>LOOP CLIENTDECISION</srai>
</template>
</category>

<category>
<pattern>CLIENTDECISION UNKNOWN</pattern>
<template>
<srai>END CLIENTDECISION</srai>
You think you´re smarter than me, eh? But you´ve been tested anyway... 
</category>

</topic>

<!-- You might want to save the above five categories to a seperate clientdecision-template.aiml file, and copy-and-fill whenever you come across a "client decision" situation. -->

<!-- Now for the FUZZY DECISION OBJECT itself - that´s the reusable part -->

<!-- Remember that with the question, "topic" has been set to CLIENTDECISION INTERFACE -->
<!-- The only category in this "topic" uses the _underscore to "catch" the input, reset "topic", and drop <star/> into it´s "own matching space", cordoned off from the rest of the patterns by additional words/letters at beginning and end (in this case, C and D, but that´s completely arbitrary) This technique - defining additional "matching spaces" - has some more good uses, e.g. to seperate an object from a predicate via <srai> nesting. -->

<topic name="CLIENTDECISION INTERFACE">

<category>
<pattern>_</pattern>
<template>
<think>
<set name="topic">CLIENTDECISION RECOGNIZER</set>
</think>
<srai>C <star/> D</srai>
</template>
</category>

</topic>

<!-- The next <topic> encapsulates the pattern set the client input is matched against -->

<topic name="CLIENTDECISION RECOGNIZER">

<category>
<pattern>C POSITIVE D</pattern>
<template>
<think><set name="topic"><get name="decision"/></set></think>
<srai>CLIENTDECISION POSITIVE</srai>
</template>
</category>

<category>
<pattern>C YES D</pattern>
<template>
<srai>C POSITIVE D</srai>
</template>
</category>

<category>
<pattern>C FOR SURE D</pattern>
<template>
<srai>C POSITIVE D</srai>
</template>
</category>

<category>
<pattern>C CERTAINLY D</pattern>
<template>
<srai>C POSITIVE D</srai>
</template>
</category>

<category>
<pattern>C COUNT ME IN D</pattern>
<template>
<srai>C POSITIVE D</srai>
</template>
</category>

<!-- You can find many more categories you may want to interpret as POSITIVE... -->

<category>
<pattern>C NEGATIVE D</pattern>
<template>
<think><set name="topic"><get name="decision"/></set></think>
<srai>CLIENTDECISION NEGATIVE</srai>
</template>
</category>

<category>
<pattern>C NO D</pattern>
<template>
<srai>C NEGATIVE D</srai>
</template>
</category>

<category>
<pattern>C NOPE D</pattern>
<template>
<srai>C NEGATIVE D</srai>
</template>
</category>

<category>
<pattern>C LEAVE ME OUT OF THAT * D</pattern>
<template>
<srai>C NEGATIVE D</srai>
</template>
</category>

<category>
<pattern>C YOU CANNOT DO THAT D</pattern>
<template>
<srai>C NEGATIVE D</srai>
</template>
</category>

<!-- ...more NEGATIVE categories... -->

<category>
<pattern>C UNDECIDED D</pattern>
<template>
<think><set name="topic"><get name="decision"/></set></think>
<srai>CLIENTDECISION UNDECIDED</srai>
</template>
</category>

<category>
<pattern>C _ UNDECIDED * D</pattern>
<template>
<srai>C UNDECIDED D</srai>
</template>
</category>

<category>
<pattern>C HOW SHOULD I KNOW D</pattern>
<template>
<srai>C UNDECIDED D</srai>
</template>
</category>

<category>
<pattern>C _ NOT SURE D</pattern>
<template>
<srai>C UNDECIDED D</srai>
</template>
</category>

<!-- ...and more UNDECIDED categories, but only one that returns UNKNOWN -->

<category>
<pattern>C * D</pattern>
<template>
<think><set name="topic"><get name="decision"/></set></think>
<srai>CLIENTDECISION UNKNOWN</srai>
</template>
</category>

<!-- So, if tomorrow you realize that GO FOR IT should be interpreted as POSITIVE, too, you don´t have to write a lot of new categories, all of them with with GO FOR IT as a <pattern> and one of your existing questions as the <that>. Just add one, and you´re done: -->

<category>
<pattern>C GO FOR IT D</pattern>
<template>
<srai>C POSITIVE D</srai>
</template>
</category>

</topic>

<!-- To round things off, we need a general CLIENTDECISION * <topic> to end the function calls and handle errors -->

<topic name="CLIENTDECISION *">

<!-- End a call by re-inserting the original "topic" and re-setting "decision". -->

<category>
<pattern>END CLIENTDECISION</pattern>
<template>
<think>
<set name="topic"><get name="oldtopic"/></set>
<set name="decision">undefined</set>
</think>
</template>
</category>

<!-- Signal an error if the response was unknown (just a precaution against coding errors) -->

<category>
<pattern>C * D</pattern>
<template>
AIML Exception at decision <get name="decision"/>: unhandled response.
<srai>END CLIENTDECISION</srai>
</template>
</category>

<!-- Return to the interface if it was somehow exited -->

<category>
<pattern>*</pattern>
<template>
<think>
<set name="topic">CLIENTDECISION INTERFACE</set>
</think>
</template>
</category>

<!-- Having an easy-to-remember loop pattern to repeat the procedure comes in handy sometimes... (see the treatment of UNDECIDED in the example above) -->

<category>
<pattern>LOOP CLIENTDECISION</pattern>
<template>
<think>
<set name="topic">CLIENTDECISION INTERFACE</set>
</think>
</template>
</category>

</topic>

<!-- That´s all, folks! -->

</aiml>


_____________________________________________________________
Play the Elvis® Scratch & Win for your chance to instantly win $10,000 Cash
- a 2003 Harley Davidson® Sportster® - 1 of 25,000 CD's - and more!
http://r.lycos.com/r/sagel_mail_scratch_tl/http://win.ipromotions.com/lycos_020801/index.asp?tc=7087