The original ELIZA program was published by Joseph Weizenbaum in 1966. It simulated a Rogerian therapist; that is, most of what it said was merely repeating (with appropriate substitutions) what it was told. Here is a bit of sample dialogue (from Rich & Knight, Artificial Intelligence, 1983):
Person: Men are all alike.
ELIZA: In what way?
Person: They're always bugging us about something or other.
ELIZA: Can you think of a specific example?
Person: Well, my boyfriend made me come here.
ELIZA: Your boyfriend made you come here.
Person: He says I'm depressed much of the time.
ELIZA: I am sorry to hear you are depressed.
Person: It's true. I am unhappy.
ELIZA: Do you think that coming here will help you not to be unhappy?
Person: I need some help, that much seems certain.
ELIZA: What would it mean to you if you got some help?
Person: Perhaps I could learn to get along with my mother.
ELIZA: Tell me more about your family.
Many of Eliza's responses, you should notice, are simply restatements of what the user says. This is done by simply rearranging a few words and replacing a few pronouns. Other responses are simply keyed to specific words, such as "mother." When nothing works, the program might randomly choose one of a set of "all-purpose" phrases; for example, "Tell me more about that." Another good trick is to remember some previous topic, and revert to it. These tricks help to give the appearance that the program has some understanding of what the user says.
Your assignment is to write a simple ELIZA-like program that holds a plausible conversation with the user.
ELIZA worked by applying pattern-matching rules. It looked for a rule whose left side matched the last sentence entered by the user, then used the right side of that rule to generate a response. Some sample rules might be:
I remember #1 => What made you think of #1?
#1 loves #2 => How does that make you feel about #1?
mother => Tell me more about your family.
The above are intended to show you the kind of rules you might have; it is not intended to say anything about how you should represent those rules in your program. While it is certainly possible to represent a rule by a string of the above form, for a small number of rules, it's easier just to write unique code for each kind of rule.
Write an ELIZA-like program (in a class named
Eliza) that interactively "converses" with
the user. Your program should have the following features:
Try to get capitalization and punctuation correct, but don't worry too much about it.
You should have (at least) the following classes, methods, and instance variables.:
self.rules. Create a number of rules (one for each subclass of
Rule) and put them into the
get_responseto do the actual pattern matching. When the user enters a line beginning with the word "
goodbye," quit the Eliza program (do this by just returning from the
rulesto produce and return Eliza's response.
if __name__ == '__main__': Eliza().hold_conversation()
def apply(self, string)
string. This method is never actually used; it's a "placeholder" method. Its whole purpose in life is to remind you that you need to override it by a method of the same name in each of its subclasses.
def can_apply(self, string)
False. This method is never actually used; it's a "placeholder" method. Its whole purpose in life is to remind you that you need to override it by a method of the same name in each of its subclasses.
def is_final(self, string)
False. Subclasses that do not override this method will automatically be non-final.
Rule, define them here and they will be inherited by all subclasses.
class Something_or_other_rule (Rule)
Write a separate class for each kind of rule that you can think of, and give each class an appropriate name. You should be able to come up with at least ten rules, including rules to do pronoun substitution and to provide random responses when nothing else applies. Each class should define the following:
def can_apply(self, string)
trueif applying this rule will make some changes in the
def is_final(self, string)
Trueif, after this rule has been successfully applied, no other rules may be applied, and the response is final. In most rule classes you will probably not define this method, but instead just inherit the method from
Rule, which returns
Ruleclass it is in. For example, if you write a class named
apply_rulemethod in such a class probably should substitute pronouns in the given string to produce the resultant string.
stringis derived from user input, and was probably a sentence or a question. However, when you are dealing with user input, you should not make any assumptions that you can avoid.
Possibly other local methods
Rule. You can override methods inherited from
Rule. You can define additional methods to be used only within this class, or within a unit test for this specific class.
All classes and all methods should be fully commented with doc comments. The comment should consist of at least one sentence that describes what the method does, and it should describe the parameters and result.
Your goal in this assignment is to write an Eliza-like program that produces a reasonable-sounding "conversation." That means coming up with a set of rules that do a good job. Since I am not specifying exactly what those rules should be, I cannot provide unit tests for them.
You should unit test every
method that you write, other than the methods defined in the
Eliza class (
Eliza is in charge of all the I/O). In particular, it should be easy to tell what each of your
apply methods is supposed to do, by looking at the unit tests for it. Make each test reasonably readable and self-contained.
While it is common practice to have a test class for each application class, that isn't a requirement. In this assignment you will have a lot of subclasses of the
Rule class, and there's nothing wrong in combining tests for those methods into one or a few test classes.
Your program is due before Fall Break is next weekend, so we won't have lab or another assignment. Enjoy Fall Break!