# dialog.py # Make a simple dialog session between AI and users from re import * # Loads the regular expression module. # The main function should be commented out in order for this # agent to work as a module. And also, the lauching command at the end # of the source file should be commented out. ##def main(): ## 'Shrink is the top-level function, containing the main loop.' ## print introduce() ## while True: ## the_input = raw_input(agentName()+':>> ') ## if match('bye',the_input): ## print 'Goodbye!' ## return ## print respond(the_input) def introduce(): return "My name is Beau Fitness, and I'm a personal fitness advisor.\n\ I was programmed by Hyung-Joon Kim. If you need futhre information\n\ or help, please contact zoony23@u.washington.edu.\n\n\ How are you doing today?" def agentName(): return "Beau" NUM_TURN = 0 def respond(the_input): global NUM_TURN NUM_TURN += 1 wordlist = split(' ',remove_punctuation(the_input)) wordlist[0]=wordlist[0].lower() mapped_wordlist = you_me_map(wordlist) mapped_wordlist[0]= mapped_wordlist[0].capitalize() if wordlist[0]=='': return "Please say something." # Check if any positive/negative adjectives are included if any_word(wordlist, POS_WORDS): return rand_resp() # Random response if any_word(wordlist, NEG_WORDS): return alt_resp(1) # Cycling alternative response #1 # If weight is mentioned in the dialog, the following rules fire, # depending on the scale of the weight weight = adv(wordlist) if weight != False and weight > 199: return str(weight) + " pounds?" +\ " You definitely need to start workout." if weight != False and weight > 132: return "Oh, " + str(weight) +\ " pounds. Then, what's your biggest concern?" if weight != False and weight < 110: return "You think I am a jerk?" # Check if the agent got a question regarding the topic word if (wpred(wordlist[0]) or wordlist[0] == 'what') and find_topic_word(wordlist) != False: return "Why don't we make an appointment? I'll tell you in details." # Check if the agent got a question if wpred(wordlist[0]): return alt_resp(2) # Cycling alternative response #2 if wordlist[0:2] == ['i','have']: return "How long have you had " + stringify(mapped_wordlist[2:]) + '?' if 'because' in wordlist: return "Yeah, but that might not be the reason." if 'yes' in wordlist: return "Are you sure? Tell me the reason." if wordlist[0:2] == ['you','are']: return "Oh yeah, I am " + stringify(mapped_wordlist[2:]) + '.' if verbp(wordlist[0]): return "I will " + stringify(mapped_wordlist).lower() +\ " after finishing this conversation." if wordlist[0:3] == ['do','you','think'] and wordlist[3].lower() == 'i': return "You bet! " + stringify(mapped_wordlist[3:]) + '.' if wordlist[0:2]==['can','you'] or wordlist[0:2]==['could','you']: return "Absolutely, I " + wordlist[0] + ' ' +\ stringify(mapped_wordlist[2:]) + '.' # Memory feature : detect the presence of any word in the given topic # and remember the word for the latter conversation if find_topic_word(wordlist) != False: return alt_resp(3) # Cycling alternative response #3 if 'fat' in wordlist: return "I used to be 250 pounds, but I'm in good shape now." if 'no' in wordlist: return "Why not?" if 'maybe' in wordlist: return "Tell me yes or no! I'm not smart enough, man." # Memory feature : in case none of the above production rules fires, # the word which is mentioned earlier will be used to continue # the conversation. At least 5 turns of dialog should be passed # in order for the topic word to be used again. if len(MENTIONED) > 0 and (NUM_TURN)%6 == 1: return "By the way, you mentioned your " + MENTIONED + " earlier." +\ " Tell me more about that." if ('you' in mapped_wordlist or 'You' in mapped_wordlist) and\ not '?' in mapped_wordlist and len(wordlist) < 8: return stringify(mapped_wordlist) + '? ' +\ alt_resp(4) # Cycling alternative response #4 return punt() # Topic words which characterize the agent TOPIC_WORDLIST = ['workout', 'diet', 'weight', 'health', 'muscle', 'belly', 'body', 'exercise'] MENTIONED = '' # The function which enables the memory feature def find_topic_word(wordlist): '''Find the first occurence of a topic word in the input words. Remember which word is found by assigning it to the global variable 'MENTIONED'. Return the word if such a word was found, otherwise False.''' for word in TOPIC_WORDLIST: if word in wordlist: global MENTIONED MENTIONED = word return word return False # List of alternative responses alt_resps1 = [] alt_resps1.append("What's wrong?") alt_resps1.append("Tell me more if you don't mind.") alt_resps1.append("Don't be so negative. You're okay.") alt_resps2 = [] alt_resps2.append("Do you think I can answer that?") alt_resps2.append("I don't know. You tell me, now.") alt_resps2.append("Who in the word can answer that?") alt_resps3 = [] alt_resps3.append("Workout is the best way to keep you healthy.") alt_resps3.append("I promise that regular exercise will help your health a lot.") alt_resps3.append("Don't put it off. You can't buy your health. Start workout right away.") alt_resps4 = [] alt_resps4.append("I\'m confused. Tell me more.") alt_resps4.append("Please go on.") alt_resps4.append("I see. Just tell me more.") # List of random responses rand_resps = [] rand_resps.append("Good to hear that.") rand_resps.append("Good, so how can I help you?") rand_resps.append("Good, so what do you want to know from me?") rand_resps.append("You look great.") rand_resps.append("Don't lie to me. Tell me the truth.") rand_resps.append("Hey man, be honest.") # Index variables for cycling alternative responses RES_NUM1 = 0 RES_NUM2 = 0 RES_NUM3 = 0 RES_NUM4 = 0 # Return a cycling alternative response def alt_resp(which): global RES_NUM1 global RES_NUM2 global RES_NUM3 global RES_NUM4 if which == 1: RES_NUM1 += 1 if RES_NUM1 == 3: # all alt. resp. used, so reset the cycling index RES_NUM1 = 0 return alt_resps1[RES_NUM1] elif which == 2: RES_NUM2 += 1 if RES_NUM2 == 3: RES_NUM2 = 0 return alt_resps2[RES_NUM2] elif which == 3: RES_NUM3 += 1 if RES_NUM3 == 3: RES_NUM3 = 0 return alt_resps3[RES_NUM3] else : RES_NUM4 += 1 if RES_NUM4 == 3: RES_NUM4 = 0 return alt_resps4[RES_NUM4] from random import * # Return a random response def rand_resp(): return rand_resps[randint(1,100)%len(rand_resps)] import string def stringify(wordlist): 'Create a string from wordlist, but with spaces between words.' return string.join(wordlist) punctuation_pattern = compile(r"\,|\.|\?|\!|\;|\:") def remove_punctuation(text): 'Returns a string without any punctuation.' return sub(punctuation_pattern,'', text) def wpred(w): 'Returns True if w is one of the question words.' return (w in ['when','why','where','how','who']) def dpred(w): 'Returns True if w is an auxiliary verb.' return (w in ['do','can','should','would']) PUNTS = ['Keep going. I\'m listeing.', 'By the way, have you done regular exercise lately?', 'How much do you weigh?', 'Do you like junk foods?', 'Does that bother you?', 'Just tell me how you feel.'] punt_count = 0 def punt(): 'Returns one from a list of default responses.' global punt_count punt_count += 1 return PUNTS[punt_count % 6] CASE_MAP = {'i':'you', 'I':'you', 'me':'you','you':'me', 'my':'your','your':'my', 'yours':'mine','mine':'yours','am':'are'} def you_me(w): 'Changes a word from 1st to 2nd person or vice-versa.' try: result = CASE_MAP[w] except KeyError: result = w return result def you_me_map(wordlist): 'Applies YOU-ME to a whole sentence or phrase.' return map(you_me, wordlist) def verbp(w): 'Returns True if w is one of these known verbs.' return (w in ['go', 'have', 'be', 'try', 'eat', 'take', 'help', 'make', 'get', 'jump', 'write', 'type', 'fill', 'put', 'turn', 'compute', 'think', 'drink', 'blink', 'crash', 'crunch', 'add']) # Lists of adjectives which expresse the feeling POS_WORDS = ['excellent','awesome','great','good','fine','nice'] NEG_WORDS = ['terrible', 'horrible', 'awful', 'bad'] def any_word(w, wordlist): '''Return True if any of words in w is found in wordlist. Otherwise, return False.''' for word in w: if word in wordlist: return True return False WEIGHT = ['pounds', 'pound', 'lb', 'lbs'] def adv(w): '''Return the numeric value of the weights if it is found in the given word list.''' for word in w: if word in WEIGHT: return int(w[w.index(word)-1]) return False ##main() # Launch the program.