Is it Live? Or is it Chatbot::Eliza?
When we were in college, my wife (then, girlfriend) had the best answering machine greeting message, ever. When people called her, the answering machine would answer, “Hello?” and wait. Invariably, the caller would start talking as though they had actually reached a live person. They'd be talking about last weeks assignments, or a party next week. Then the other shoe would drop. The answering machine would then continue, “Oh, I'm sorry. I'm not here at the moment. If you'd like to leave a message, please wait for the beep!” The caller would then have to start over, probably feeling a bit sheepish. Eventually, she changed her message to something more conventional, probably under threat of severe beatings from her friends and family. But before she changed it, she got to where she wouldn't even bother answering the phone if she was available; it was a lot of fun listening to people talk to a machine, thinking they were talking to a person.
I can relate. Ever since High School, I've wanted to write programs that acted like, or looked like real people. I remember playing with a program called Eliza when I was young and thinking how amazing it was that it worked as well as it id. The Eliza program would impersonate a Psychiatrist and attempt to “analyze” your “problem” by holding a natural language conversation with you. However, as soon as you realized that it was just matching simple patterns, it would mention something that you had said earlier, just to throw you for a loop. It was primitive, but effective.
When I was in college, I got heavily involved in playing in Multi-User Dungeons, or MUDs. These games were essentially text-based MMORPG's where people all over the world could talk to each other and explore places that had been created by other players. It was fun. Then came the 'bots. It became interesting, at least to me. The 'bots were programs just like Eliza. In fact, many of them used the same algorithm to appear as though they were another player in the game. Instead of a Psychiatrist, some of the 'bots posed as girlfriends, bar maids, mailmen, and even pets. But there was something new; they could respond to specific orders. For example, you could ask a 'bot how to get to a certain location in the MUD, or when a certain player was last on-line. You could even ask them about themselves. In addition to being fun and interesting, they became useful.
So a program that pretends to be human must be difficult to write, right? Well actually, it's embarrassingly simple, thanks to Perl's Chatbot::Eliza module. Let's take a look at a (very) trivial example:
#!/usr/bin/perl
use Chatbot::Eliza;
$bot = new Chatbot::Eliza("Jill", "");
$bot->command_interface();
That's right, 4 lines of code and no configuration needed! The module comes with a default database that allows it to carry on the tradition of the original Eliza program. Here is a sample of an interaction with “Jill.”
Jill: Please tell me what's been bothering you.
you: I'm bored.
Jill: Do you enjoy being bored?
you: No.
Jill: Does this make you feel unhappy?
you: Yes.
Jill: Please go on.
you: I want something to do.
Jill: Suppose you got something to do soon.
you: That would be great!
Jill: Tell me more about that.
you: I'm bored.
Jill: Is it because you are bored that you came to me?
you: yes.
Jill: I see.
Not bad for 4 lines of code, but our program isn't very flexible. For one thing, it's relegated to a command-line interface. Let's make a change to the program to demonstrate using the module from our own run-loop:
#!/usr/bin/perl
use Chatbot::Eliza;
$bot = new Chatbot::Eliza("Jill", "");
print $bot->{initial}->[0] . "\n";
$true++;
while ($true) {
print "You: ";
$message = <STDIN>;
$message = $bot->transform($message);
print "$message\n";
}
exit;
This program behaves almost exactly like the first program, but it demonstrates how the module could be integrated into a Jabber client, or an IRC client, or whatever. All you'd have to do is get a message from the user, pass it to the transform() method and send the result back to the user.
Still, a faux psychiatrist is kind of old hat; let's see how hard it is to change the program's “personality.” The module comes with a default data-set that implements the psychiatrist, but you can pass the name of a new database as the second parameter of the object's constructor. Depending on your political bent, this might resemble:
$bot = new Chatbot::Eliza("Sarah", "palin.txt");
or
$bot = new Chatbot::Eliza("Barak", "obama.txt");
Either of those could be a lot of fun, but I try to keep out of politics here. Anyway, now that we know how to load a different database, what does this database look like? Here is an excerpt from the default database:
key: remember 5
decomp: * i remember *
reasmb: Do you often think of (2) ?
reasmb: Does thinking of (2) bring anything else to mind ?
reasmb: What else do you recollect ?
reasmb: Why do you remember (2) just now ?
reasmb: What in the present situation reminds you of (2) ?
reasmb: What is the connection between me and (2) ?
reasmb: What else does (2) remind you of ?
The rest of the patterns resemble this one, so let's discuss what this does and how. The key: line introduces a keyword, “remember” and assigns it a ranking of 5. This represents a slight performance optimization. The module first scans the input message for key words. When a keyword is found, it's ranking is noted. The keyword with the highest rank wins and we move on the the “decomp” section. The decomp section is simply a pattern that we apply to an input sentence. The asterisks are wildcards and cause parts of the sentence to be stored for later substitution into the reply. If the decomp matches, the module will chose, randomly, from the list of reasmb choices. The reasmb, or reassembly patterns are what the module returns as a reply. Note that the numbers in parenthesis correspond to the asterisks in the decomp section. For example, (2) represents the second asterisk in the decomp pattern.
From here, it's easy to imagine creating a database that mimics almost any type of personality. But, we could do more. With just a little bit of work, we could slightly change the database format so that the returned message was a tab-delimited list. The first item on the list could be the return message, as before. The next item could be the name of a Perl function and parameters to evaluate. Such a pattern might look like:
key: like 5
decomp: * like you
reasmb: It's nice to hear that you like me <tab> karma(+1);
Then we could implement a subroutine called karma() that keeps track of how “nice” a person is. We would have to change our main loop so that when a given variable exceeds certain thresholds, a new database could be loaded resulting in “Jill” becoming increasingly “flirty,” or “witchy” depending on how she's spoken to. We could also implement functions that interact with the rest of the world. We could then ask “Jill” what the load average is on a given server, or we could ask her for the first link returned by Google for a given word or phrase. The sky is the limit.
Now I'm not seriously proposing an Eliza bot as the next generation of computer user interface. However, the Chatbot::Eliza Perl module is a fun toy that's easy to use and simple to expand and integrate. Have fun.