Eliza 18 - Love and hate

by Ravi Bhavnani


Love and hate are powerful human emotions. In this step, we’ll make Eliza respond to these emotions much like a human would, thereby increasing the illusion that Eliza understands what you say.

We’ll do this by adding a few rules to IPattern, so that it recognizes statements like these:

    I LIKE TO WRITE CODE ALL DAY.
    I LOVE CHOCOLATE ICE CREAM.
    I HATE TO WAKE UP EARLY IN THE MORNING.
    I HATE DOING LAUNDRY.

IPattern today

In its current form, entering statements like these causes Eliza to respond in a rather uninteresting manner:

If we enable logging, we see that Eliza selected IPattern’s last catch-all rule to generate a response, because none of the preceding rules matched.

To make Eliza respond "intelligently" to emotions of love and hate, we’ll need to add rules to IPattern that cause it to recognize text patterns that indicate love and hate. We’ll add these rules before the pattern’s last catch-all rule.

Recognizing love

Let’s start by recognizing input like this:

    I LIKE TO WRITE CODE ALL DAY.

We’ll add the following rule that recognizes the phrase I LIKE TO to the IPattern constructor

With the rule in place, Eliza now responds to the input "I LIKE TO WRITE CODE ALL DAY." in the following manner:

But what if the user entered this?

    I LOVE TO WRITE CODE ALL DAY.

Ideally, Eliza should respond in a similar fashion, since the sentiment is the same. But because the user typed LOVE instead of LIKE, our rule won't fire. Instead, the catch all rule will match, causing Eliza to respond with:

How do we fix this? If you're thinking synonyms, you're right! Let’s define a synonym for LIKE and LOVE and update the rule to use that. We’ll start by adding the synonym to the Eliza.InitializeSynonyms() method.

Next, we’ll modify the rule to use this synonym.

Now, Eliza responds to both I LIKE TO and I LOVE TO in the same manner.

Testing our changes

Because we've made changes to Eliza’s logic, we must update our tests. Remember the importance of testing? If not, re-read the piece of advice we encountered in Step 14:

Want to sleep well at night? Ensure you have tests in place for all your app’s functionality. That way, if you (or someone else) modifies the app’s code, running your tests will ensure that the changes didn't break anything, or if they did, you’ll at least know where to look!

First, we’ll add a test to IPatternTest to verify our new rule works as expected.

Next, because the new rule adds to Eliza’s memory, we’ll modify the code that tests GenericResponsePattern to verify the addition works. This is done by editing Program.cs in the ElizaTest project.

Running ElizaTest displays this satisfying output, allowing us to sleep easy at night.

Adding more love

Notice that our modification to IPattern nicely handles user input like:

    I LIKE TO WRITE CODE ALL DAY.
    I LOVE TO WATCH TV WHILE STUFFING MY FACE WITH PIZZA.

but fails to recognize love in statements such as:

    I LOVE WRITING CODE ALL DAY.
    I LOVE WATCHING TV WHILE STUFFING MY FACE WITH PIZZA.

causing Eliza to use GenericResponsePattern which results in a largely uninteresting conversation.

This is because the rule we added to IPattern only recognizes the phrases I LIKE TO and I LOVE TO and not the plain ol' I LIKE and I LOVE. To fix this, we’ll add another rule that recognizes just I LIKE and I LOVE. As before, we’ll create a synonym for words that mean LOVE that appear without a following TO.

Then we’ll add a rule to IPattern that uses this synonym.

With the rule in place, Eliza clearly seems to understand the emotion of love.

Before we bask in all this love, let’s update IPatternTest to ensure we've tested our changes.

Once again, running ElizaTest displays this equally satisfying output, allowing us to continue to sleep easy at night.

Time to hate

Having made Eliza comprehend love, it seems only fair that it should also understand hate. We’ll use what we learned in recognizing love to come up with rules that recognize hate. We’ll start by recognizing this type of input:

    I HATE TO WAKE UP EARLY IN THE MORNING.

This is done by adding the following rule to IPattern :

With this rule in place, Eliza seems to respond intelligently to statements about things the user hates doing.

Now it’s time to make Eliza understand expressions about hate like these:

      I HATE ALL FORMS OF PHYSICAL ACTIVITY.
      I DETEST DOING ANYTHING THAT TAKES TIME AWAY FROM PROGRAMMING.
      ...

We’ll start by defining a few synonyms for the verb HATE.

Next, we’ll add a rule that uses this synonym.

With this rule in place, Eliza responds realistically to statements about things the user hates.

Testing our changes

Again, because we've made more changes to Eliza’s logic, we must update our tests. First, we’ll add tests to IPatternTest to verify that our new rules work as expected.

Because these new rules also add to Eliza’s memory, we’ll modify the code in the test project’s Program.cs file that tests GenericResponsePattern to verify the additions work.

As before, running ElizaTest displays this satisfying output, allowing us to sleep easy at night (or during the day, if you're like me).

Where we’ve reached

In this step, we made Eliza recognize emotions of love and hate. In the next step, we’ll improve Eliza’s responses to questions that start with WHAT and WHO so that they're more realistic.

 

Most of the content at this site is copyright © Ravi Bhavnani.
Questions or comments?  Send mail to ravib@ravib.com