Eliza 10 - Fleshing out DecompAssemblyRule

by Ravi Bhavnani


In this step, we'll flesh out the DecompAssemblyRule class so that we can finish building RememberPattern. The two stubbed DecompAssemblyRule methods we need to flesh out are:

      public bool CanDecompose
          (string input);

      public string GenerateResponse
          (string input);

Writing CanDecompose()

CanDecompose() checks whether the user's input matches the decomposition rule. Eliza's REMEMBER pattern defines two decomposition rules:

    decomp: * i remember *
    decomp: * do you remember *

Both rules consist of a phrase being matched (e.g. "I REMEMBER"), optional text before the phrase, and text after the phrase. Let's take a stab at writing the psuedo-code for CanDecompose().

    check if the input contains the phrase being searched for;
    if it doesn't
       return false;

    extract the text element that occurs before the phrase;
    extract the text element that occurs after the phrase;
    store the text elements for later use by GenerateResponse();
    return true;

Recall the first decomposition/assembly rule for the REMEMBER pattern:

    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 recollect (2) just now?
      reasmb: What in the present situation reminds you of (2)?
      reasmb: What is the connection between me and (2)?

If the user entered:

    ONCE IN A WHILE I REMEMBER PLAYING IN A BAND WHEN I WAS A TEENAGER.

CanDecompose() would break this down into:

  • Phrase searched for: "I REMEMBER"
  • Text element before phrase: "ONCE IN A WHILE"
  • Text element after phrase: "PLAYING IN A BAND WHEN I WAS A TEENAGER"

Because we're storing the text elements for later use by GenerateResponse(), we'll need to add a new private variable to DecompAssemblyRule to hold them.

    /// <summary>
    /// The text elements in the user's input.
    /// </summary>
    private List<string> _textElements;

The following methods of the string class may come in handy when writing CanDecompose().

GO AHEAD AND WRITE DecompAssemblyRule.CanDecompose(). THEN COMPARE YOUR CODE WITH THIS.

Notice how our code comments match the psuedo-code? That's an example of well-documented code.

Writing GenerateResponse()

Now it's time to write GenerateResponse(). This method generates a response from the next available reassembly string. Running CanDecompose() gave us the following results:

  • Phrase searched for: "I REMEMBER"
  • Text element before phrase: "ONCE IN A WHILE"
  • Text element after phrase: "PLAYING IN A BAND WHEN I WAS A TEENAGER"

GenerateResponse() will take the first available reassembly string from this list:

      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 recollect (2) just now?
      reasmb: What in the present situation reminds you of (2)?
      reasmb: What is the connection between me and (2)?

which is:

      reasmb: Do you often think of (2)?

The "(2)" in the reassembly string will be replaced with the second text element, i.e. "PLAYING IN A BAND WHEN I WAS A TEENAGER". However, before replacement, the text element is transformed using these "post transformation" rules (see Eliza's script ). (I added some that were missing.)

    post: am are
    post: are am
    post: was were
    post: were was
    post: your my
    post: my your
    post: i you
    post: you I
    post: i'm you are
    post: you're I am
    post: me you
    post: myself yourself
    post: yourself myself

resulting in:

    PLAYING IN A BAND WHEN YOU WERE A TEENAGER

Replacing the (2) in "Do you often think of (2)?" with the transformed text element causes GenerateResponse() to return:

    DO YOU OFTEN THINK OF PLAYING IN A BAND WHEN YOU WERE A TEENAGER?

Before we can finish writing GenerateResponse(), we need a means to transform text elements as shown above. We'll delegate this task to a new helper class, StringTransformer.

StringTransformer

Create a StringTransformer class with the static method PostTransform(), like so:

PostTransform() will need to:

  1. Split the incoming text into words.
  2. Transform each word (if necessary).
  3. Return the transformed sentence.

You may find these methods helpful when writing PostTransform():

GO AHEAD AND WRITE StringTransformer. THEN COMPARE YOUR CODE WITH THIS.

Now that we have a way to transform text elements, we're ready to write GenerateResponse().

GO AHEAD AND WRITE GenerateResponse(). THEN COMPARE YOUR CODE WITH THIS.

Testing our work

It's time to test our work. Run Eliza and verify that it cycles through different responses when responding to input that contains "I REMEMBER" and "DO YOU REMEMBER".

What's next?

If you take a look at Eliza's script, you'll notice it contains several patterns whose decompose/reassembly rules are similar to RememberPattern. In the next step, we'll add these patterns to Eliza, thereby increasing her "intelligence". We'll also polish up her behavior a bit.

 

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