AIML Masterclass: Telling a Story
One of the requests that people often ask is how can I make my chatbot tell a monologue or story and continue to keep telling it regardless of what the user says. I only want the bot to stop when the user asks it to stop talking. In other words, something like this:
Hotel Bot: You can use me to find out information about this hotel.
Hotel Bot: I can tell you about the entertainment and bars.
User: Sounds cool.
Hotel Bot: I can even book show tickets for you.
User: Ok, I don’t want to hear any more right now.
Hotel Bot: No problem. Let me know how I can help.
In the above example, the hotel bot displays its information a line at a time until it either runs out of things to say or the user doesn’t want it to continue.
Why would we want to do this?
Rather than displaying a huge chunk of information at a time, it makes for a better user experience to show just one line at a time. However, we don’t want the user to have to sit through a long monologue without being able to quit out.
We can do this in AIML in just two parts. First of all though before we get to the details of the AIML, we need to set up the story for the bot to display. This is the only part that the user will need to amend and ideally should be in a separate AIML file. Here is the layout of each story:
In this example, we have the name of the story (Example Story), the introduction to the story, each line of the story, the end of the story (which must be the words END OF STORY) and finally a topic which prompts the bot to start telling the story. A completed story for our hotel bot can be included in any other AIML file and could look like this:
The hotel bot’s monologue is 5 lines long but you can make it any length you like. We’ll code the AIML to accept a story with a maximum of 10 lines,as any more will probably be frustrating for the user but I’ll show you how to make this longer if needed.
Here are a few requirements that we wish to achieve with this AIML file:
1. If the user requests a story, start telling the story.
2. Keep telling the story in small pieces until it ends, ignoring whatever the user says, UNLESS the user says something like “Stop” or “Exit” or “I hate that story” etc.
3. Make the categories for stopping or exiting able to work with any story (i.e. they do not depend on TOPIC).
4. Make the story AIML work when combined with an existing bot without having to change the categories of those bots. If the bot is not in the middle of telling the story, just respond normally as the underlying personality would.
Now we have our requirements, let’s look at the code which solves this. You can click here to get a copy of the finished AIML file which also includes the example story category for completeness. Don’t be worried by it! I’ll explain what it all does and break it down for you:
It looks a little complicated at first so let’s look at it piece by piece.
Set the story topic
Remember how we set the topic to TELLASTORY in our “hotel bot intro” category? We need to wrap the main category in this topic so that it will now become active. The underscore wildcard in the pattern is the top priority in a match and means activate this template no matter what the user says.
Check the input
The template itself starts with a <think> tag because we are going to do some internal processing where we don’t want the user to see any results yet. The first thing we need to check is if the user has said something that indicates he no longer wants the story to continue. We do this by setting a new topic (QUITSTORY), passing the user’s input to it and checking whether it contains any keywords that will stop the story, things like STOP, EXIT or QUIT. We then need to set the topic back to TELLASTORY so the story can continue.
Check whether to quit the story
I’ll explain the QUITSTORY topic shortly but if the user’s input contains one of the keywords, a variable called “storycontinue” is set to “NO” which we will now check for using the above condition. If the user has asked the bot to stop talking, we set the “progress” of the story (a new variable) to QUIT.
Decide which line of the story to display
We now need to display the appropriate line of the story, so we use the condition above to see how far along the story we are. We do this by checking the value of “progress”, setting a variable called “storyline” to be the next line of the story and increasing the value of “progress” ready for the next user interaction.
It’s coded to accept a story with a maximum length of 10 lines but we can amend it to allow stories of any length we choose by simply adding more <li> checks.
Remember we set the value of “progress” to QUIT if the user wanted to stop the bot? This condition also checks that value. If it matches, we blank out the topic, so the bot stops the monologue, and set “storycontinue” to YES ready for the next story.
However, if this is the first line of the story, the variable “progress” will not be set, so it’s important we have the catch all check as the last <li>which will set a variable called “storyline” to be the first line of the story and set the value of “progress” to 2.
Has the story finished?
Now we have the line of the story ready to to display to the user, we need to check to make sure whether we have reached the end of the story by using the above condition. If the story has finished, we set “storyline” to display something more user friendly instead of “END OF STORY”, set the topic to unknown so the bot can now talk about other things, reset the progress variable back to 1 to begin any new story and set “storycontinue” to YES, to allow a new story to start .
Display the line of the story or a quit message
Now we have finished all our processing, we are ready to display the current line of the story or to quit out, so we start displaying results back to the user by closing our </think> tag. We use a condition to check the value of “progress”. If it’s set to “QUIT”, we display a message saying we are stopping and set the value back to 1 ready for any new story. We do this inside a <think> tag, as we don’t want the user to see this part. If it’s anything other than “QUIT”, we display the next line of the story which we set in the “storyline” variable.
Finally, we tidy up by closing our tags and wait for the user’s reaction to our message.
Check to see if the user wants the story to stop
The only part left to cover is the topic that indicates that the user wants the story to end. This is the QUITSTORY topic. This checks the user input and sets a variable called “storycontinue” to NO if the input matches any of the patterns in this topic. I’ve included a few common ones but you can expand this to include things like “YOU ARE SO ANNOYING!!!!” :D
We need these keywords in a separate topic, as the user may say them to the bot when it isn’t in story mode and one of our requirements was that this code should be reusable in any AIML bot. We don’t want them to overwrite any existing categories in the bot.
You can click here to get a copy of story.aiml and you are more than welcome to use it in your own chatbot if you like. I’ve included the example story template but ideally any stories should be in a different AIML file just to keep things tidy.
Hope all that makes sense. If you want to improve on the code, a good place to start would be to allow the chatbot developer to include his own customised quit and end of story messages. You could do this by allowing him to set these messages in the story category and using “get” to display them in the main categories instead of “That’s the end of the story” and “Ok. I’ll stop the story.”
If the user’s input is more than one sentence, the bot will see this as 2 separate interactions and display more than one line of the story. I’ll leave you to think how we can resolve this issue. Hint: “input index” is your friend!
I hope you enjoyed this first AIML masterclass. If you have any questions about it or have a topic you want me to cover in another post, please let me know at firstname.lastname@example.org
To bring the best bots to your business, check out www.pandorabots.com or contact us at email@example.com for more details.