Difference between revisions of "CSC111 Lab 8 2011"

From dftwiki3
Jump to: navigation, search
(Rosette)
(Playing with Eliza)
Line 27: Line 27:
 
==Playing with Eliza==
 
==Playing with Eliza==
  
Eliza is named after Eliza Doolittle, of the 1913 George Bernard Shaw play ''Pigmalion'', which is the inspiration for the musical My Fair Lady.  
+
Eliza is named after Eliza Doolittle, of the 1913 George Bernard Shaw play ''Pigmalion'', which is the inspiration for the musical My Fair Lady, of which you can see a short YouTube clip below.
 
<br />
 
<br />
 
<center><videoflash>Doz5w2W-jAY</videoflash></center>
 
<center><videoflash>Doz5w2W-jAY</videoflash></center>

Revision as of 14:58, 26 October 2011

--D. Thiebaut 15:04, 26 October 2011 (EDT)


Rosette

RosetteChatbot.png
  • Rosette is this year's winner of the Loebner prize for best chatterbot, or chatbot. Give her a try, and see how long it takes for you to make her make a mistake that a human behing would not make:









Eliza!

Today we are going to therapy and will consult with Doctor Eliza.

Playing with Eliza

Eliza is named after Eliza Doolittle, of the 1913 George Bernard Shaw play Pigmalion, which is the inspiration for the musical My Fair Lady, of which you can see a short YouTube clip below.


Joseph Weizenbaum originated the program. A good description of what how Eliza works can be found here.

First, play with Eliza a bit to get a feel for it. You can either use this page, or that one, or use the "therapist" included in emacs. To start the therapist in emacs, start emacs in your 111a-xx account, and type the following commands:

     Shift ESC 
then
     x doctor 

and press the Enter key. Emacs will switch to "doctor" mode... When you are done and want to return to editing your program, type

     CTRL-x k

The initial program

Cut and paste the program below into a file called eliza.py:

# eliza.py
#
# a very simple beginning for an eliza-like program
# 
# 1) greet user
# 2) repeat a huge number of times:
#   2.1)  get user's statement about life
#   2.2)  respond in a way that seems intelligent
#
# Addition:
#  cycles through a series of canned answers to get
#  the user to think the computer is listening
import random

canned = [ "\nPlease tell me more",
           "\nI see...",
           "\nI am listening..." ]

def main():

     # 1) greet user
     print(  "Welcome.  Please tell me of your problems: " )
     print( '(You may quit at any time by answering "bye")' )
     
     # 2) repeat a huge number of times
     for i in range( 10000 ):

         # 2.1) get user's statement about her life
         answer = input( "\n> " )
         if ( answer.lower() == "bye" ):
             break
            
         # 2.2) respond semi-intelligently
         # cycle through the list of canned sentences...
         print( random.choice( canned ) )

main()




Run the program and enter at least 6 or 7 sentences. Observe how the program repeats itself in the way it responds to the user.

Go ahead and add a few more canned answers if you want :-) This will make it harder for a human to figure out the repetition, but not foolproof.

By the way, you do not have to type sentences that make sense to test your program. Just the letter 'a' is enough of an input!


Dealing with Negative Answers

  • If the user responds with just one word, such as "No", "Never", or "Not", let's make Eliza respond with a sentence of this type "Why so negative?".

Reflection

One way for Eliza to appear intelligent is to say the same thing the user just said, but to change the sentence from the first person to the second person. For example, if the user says "I am tired", Eliza will respond "You are tired". We can program that by replacing all occurrences of "I" by "you", "am" by "are", "my" by "your", and "me" by "you".

How can this be done?

Here is a possible solution (code it in a separate program):


def main():
  answer = input( "\n> " )
  
  # split user's sentence into words     
  words = answer.split( ) 
  
  #create a copy new list of words that will be Eliza's response
  newWords = []
  for word in words:
       newWords.append( word )
  
  # take each word of user sentence and if the word represents 
  # the first person singular, switch it to second person.
  for i in range( len( words ) ):           
    if words[i] == "I": 
         newWords[i] = "you"

  # join the list of words in newWords in a string, and print it         
  sentence =  ' '.join( newWords )
  print( sentence )

main()


Go ahead and implement this modification. Play with it. Verify that when you use "I" in a sentence, the program replaces it by "you". Understand why the program actually does that.

Once you have tested this, go ahead and make your program also replace

"me" by "you" "am" by "are" "I've" by "you've" "I'm" by "you're" "I'll" by "you'll" "was" by "were" "my" by "your" "mine" by "yours"

Adding a ? at the end of the reflected sentence

  • Once you have your list of new words newWords containing the reflected words, modify the last word of this list and add a "?" at the end of it.
  • In other words, if newWords is [ "You", "are", "bored", "today" ], transform it into [ "You", "are", "bored", "today?" ].

Reflection or Canned Answer?

Depending on how you have modified your program, it may respond to the user with two sentences. One reflected and one canned.

What you should do is make your program output the reflected answer when it finds out that it was able to change some of the words in the user's string, and make it output a canned answer when there is no reflection.

For example, if the user says "I am bored", your Eliza program will respond "you are bored?", but if the user says "never!", your program will respond with an answer of the type "Please go on..."

Figure out what kind of test you can use for your program to know if it is reflecting the user input, or not, and output either the reflected sentence, or a canned answer.

Hints #1: you could compare the original list of words entered by the user, to the list of words generated after the reflection.

Test your program! It should really start showing some artificial intelligence!

Second level reflection: Switching second person to first person

  • What if the user says to the program "I don't like you"?
  • Right now your program will output "you don't like you?" which is not quite right. So we should try to fix this.
  • Go ahead, and make your program replace the 2nd person in the user's input by the first person. You will see that without doing a semantic analysis of the sentence, it is impossible to know whether "you" should be replaced by "I", or by "me". At this point, we will not worry about this, and simply replace "you" by "me" and this will have a higher probability of looking correct.
  • If your modification is correct, and the user enters "I don't like you", your program should output "you don't like me?".

Catching key words

  • You may have noticed that with the real Eliza program, when you say something like "No", or "never", the program picks up on this and responds something like "why are you so negative?".
  • Let's make your program pick up on a "NO" answer.
  • All you need is an if statement that will test whether the user's answer is one word only, and this word is "no".


    # check for reflection
    if words != newWords:
        # then output the reflected answer
        ...
    else:
        if len( words ) == 1 and words[0] =="no":
            print "you are begin very negative today!"
        else:
            # print canned answer


  • Note the and operator: it is a logical operator. It forces the whole expression of the if-statement to be true only if the two parts on each side of the "and" are true.

Random "negative canned" answers

Instead of your program always outputting "you are begin very negative today!" in the case explored in the previous section, make it select its response from a new series of canned negative responses (like "No?", "Really?", "You are awfully negative", "why not?", etc.)

Picking up on "No" and "Never"

  • What if we not only wanted our program to pick up on "No", but also on "Never"? All we need to do is change the if statement to read "if the user's answer contains 1 word only, and this word is "no" or "never"..."
  • Here is the test in python:
       if len( words )==1 and ( words[0]=="no" or words[0]=="never" ):
           index = random.randrange( len( cannedNegative ) )
           print cannedNegative[ index ]
       else:
           # print canned answer