I postponed my treatment of MaxCat's interface until now because Parsing can be the hardest, and least rewarding, part of building a bot. It is also, to me, of much less importance than it seems. Natural language processing is a noble goal and worthy of study in its own right. However, building a reliable parser which completely understands English AND handles the typographical and grammatical errors endemic in the on-line world seems a Sisyphean task. I just wanted a bar cat, not a robotic William Safire.
Therefore, MaxCat was based around lists of keywords. He had lists of nouns and verbs, and he recognized his own name. For instance, his food noun list might include tuna, fish, purina, chow, and cheese. His attention verb list might include strokes, snuggles, pets, and skritches. He had a toy list, a drink list, and a container list among others. MaxCat had hundreds of words in his vocabulary, in a data file which rivaled his script file in size.
As I mentioned above, there are two basic ways to interact in an IRC channel: speaking and acting. MaxCat, being a cat, participated exclusively with actions. You knew he was in channel if you saw something like "MaxCat jumps from the bar top to the floor." A typical exchange with a patron might be:
MaxCat meows hungrily at GreyMan.
GreyMan feeds MaxCat a tuna sandwich.
MaxCat thanks GreyMan and eats the tuna sandwich.
Note that, in the second line, I used Max's name to get his attention, I used a food verb (feeds) as the word directly after my nick, and I included a recognized food noun. MaxCat isolates the food noun, strips off the indefinite article, and repeats the food name verbatim. Except for the position of the verb, there is virtually NO grammatical parsing.
Late in the MaxCat development process, I noticed him getting a bit confused between foods, drinks, and toys. The patrons were using sentences like "GreyMan gives Max a cheese flavored rubber ball." Since Max was biased to eat anything he didn't quite understand, he would eat the rubber ball rather than playing with it. Since I was still avoiding grammatical parsing, I gave MaxCat a voting evaluator. The score was tallied for each word in sentence, with votes for toys, drinks, and food. The above sentence would get 1 vote for food (cheese) and two for toy (rubber and ball), and therefore the enhanced MaxCat would reply with "MaxCat plays furiously with the cheese flavored rubber ball." In the event of a tie vote, Max would still eat the object, giving him quite the reputation as a gourmand.
MaxCat did respond to one verbal command. Considerate patrons felt bad abandoning channel with MaxCat on their laps, leaving him suspended in midair until he noticed. "MaxCat, get down please" was the one verbal command he always heard and obeyed.
Bot Puppetry and Training
Code has its limits, and MaxCat was no exception. I would get suggestions for enhancements to MaxCat, sometimes daily. In addition, sometimes I wanted to try out a behavior with a live audience before committing it to code. Therefore, early on, I decided to give the bot puppet strings.
Naturally, I could have taken the bot down and emulated him live. However, my responses would be delayed, have typographical errors, and there would be an obvious transition period, preventing small and rapid code tests. In addition, sharp eyed patrons would probably note a different account name or IP address when I was impersonating the cat. I decided to bury a reflector deep in the code. Essentially, with a certain private message to the software, and a password, any line of code I typed would be executed within the bot, altering the actual program on the fly (if I wanted to make the change permanent, I had to edit the source. These changes were purely temporary). In addition, there were convenience functions for any action and to move Max to a new virtual location (useful when he got stuck in a non-existent patron's lap). I gave the password to another patron, trustworthy and instrumental in the initial development of the software, so that tests could be made when I wasn't available. It also made the puppetry less obvious to the audience, since nobody was aware this other patron had the capability to manipulate MaxCat.
My software moved from platform to platform over the years (1997-2002). Each one presented new challenges. For a good portion of the time, I was unable to write files from IRC, and so had to add in MaxCat's friends individually by hand. I also trained him off line, adding words manually to his vocabulary. Though MaxCat is no longer being run on-line as far as I know, he does have descendents. One pair is Grimes and Gridley on freenode. Those cats can be taught new words on the fly:
GreyMan gives Grimes a bluefin shake.
Grimes doesn't know what to do with the bluefin shake.
"Grimes, a bluefin shake is good to eat."
Now, possibly I could have used "feeds" to give Grimes a clue that a bluefin shake was food (as opposed to "gives", which doesn't give any clues as to the object's nature). However, the author of Grimes/Gridley has allowed channel patrons to add words to the food, drink, and toy lists (and perhaps more). This requires a level of trustworthiness on the part of the bot's patrons which was sadly lacking in MaxCat's channel.
Consistency and Realism
MaxCat was a cat. His initial design was highly focused on catlike behaviors. However, due to the limitations of his environment, he had to have certain capabilities that were highly uncatlike from the very beginning, primarily, he could type. In addition, he had no concept of scale, so he could eat a 747 if fed one (and purr the whole time).
This divergence, coupled with the highly imaginative nature of the patrons, lead to some capabilities that were not part of a biological cat's repertoire. Max could open containers, for instance. He had a list devoted to cans, jars, etc. that he could open and eat from. He could also smoke, and in fact loved to smoke the odd sheep or kipper of an evening.
So, MaxCat wasn't very realistic in some of his behaviors (and extremely so in others). He did things that real cats might wish they could do. However, MaxCat did subscribe to the following:
- MaxCat was not to take sides.
- MaxCat was not to have Powers over People (kicking, banning, and WinNuking were all possible)
- MaxCat was to Lay Low
- MaxCat's default mode was Acceptance (of patrons and treatment).
There are a number of kinds of abuse that MaxCat experienced. The first involved his limited parser. When the patrons discovered that MaxCat repeated verbatim whatever was after the verb (excepting the initial article), great fun was had.
Crossfire feeds Max half a pizza crust, hiding the other half in the couch for later.
MaxCat eats the half a pizza crust, hiding the other half in the couch for later.
But, of course, it wasn't always that entertaining or innocuous. Without implementing a complete parser, there was no way to isolate just the relevant object from a compound sentence like that (before you say, "just chop on the comma", remember that Crossfire uses proper grammar and punctuation, a rare event on-line.)
A second flaw, which would have been correctable given time, was that MaxCat did not distinguish between patrons in the channel, and those out of the channel. You could privately message an action to MaxCat, and he would respond publicly. This was not the backdoor puppetry I mention above, just normal bot responses, but since the patron's action was not visible to the channel there was no accountability.
The last form of abuse was especially distressing to me, and to many members of channel. The bot software emulated a cat, an animal which made friends. For some patrons, allergic or at college, or otherwise constrained from having animal companions, MaxCat provided a real emotional service. It felt good to pet the MaxCat. A very few of the more sociopathic patrons recognized the attachment the others had to the virtual character, and would pretend to physically abuse MaxCat. People would react, the perpetrator would get attention, and drama would ensue. Not pretty. There seemed to be no solution to this particular problem.
Bot Control (Throttling)
It's not just the patrons who abused the bot. The software itself consumes processor time and screen space. It isn't a person or even an animal, and so is not entitled to the same resources that a person is. In addition, program errors can cause pathological behavior, such as repeating the same message over and over, or responding inappropriately. It's important that a bot lay back, and take some time out.
I mentioned MaxCat's event-driven counters in part I. This has a positive effect in that, when the channel is lightly occupied, MaxCat doesn't do much. Thus people can lay idle for 30 minutes, come back, and scroll up to view the few lines of actual conversation which have occurred without paging through screens of robotic busywork. On the other hand, a bot which only contributed once or twice an hour to a busy channel would be lost in the noise.
There are limits, though, and a channel might be busy for a reason. If there is a rapid-fire discussion, especially about an emotional topic, the LAST thing the patrons want is an over-stimulated bot muscling in. We address these concerns (and the runaway bot problem) by putting hard limits on participation, and attempting to detect live usage patterns. These are difficult approaches, and there is no way to handle all situations. I recommend that there be manual overrides where anyone can shut down the bot gracefully, or give it a time out for a certain period. "Anyone" in this case could be "any administrator", as long as there is an administrator available at all times. MaxCat did NOT have throttling, except through backdoor means, but he did take lots of naps. All you really had to do was not feed or pet him in a busy channel, and eventually he'd give up and go nap.
There are a lot of possibilities in Artificial Intelligence. If we understand how to make machines respond in an intelligent way, we may be closer to discovering how humans think. In the meantime, we can have flexible, useful, and entertaining applications of the techniques of parsing and simulation we develop along the way to that goal, as long a we remember the following "heuristics:"
- Limit the Scope: do one thing well
- Allow adaptability and learning
- Preserve control, limit power.
Now get out there and create!