Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

# Natural Language Toolkit: Chatbot Utilities 

# 

# Copyright (C) 2001-2012 NLTK Project 

# Authors: Steven Bird <sb@csse.unimelb.edu.au> 

# URL: <http://www.nltk.org/> 

# For license information, see LICENSE.TXT 

 

# Based on an Eliza implementation by Joe Strout <joe@strout.net>, 

# Jeff Epler <jepler@inetnebr.com> and Jez Higgins <jez@jezuk.co.uk>. 

from __future__ import print_function 

 

import string 

import re 

import random 

 

reflections = { 

  "am"     : "are", 

  "was"    : "were", 

  "i"      : "you", 

  "i'd"    : "you would", 

  "i've"   : "you have", 

  "i'll"   : "you will", 

  "my"     : "your", 

  "are"    : "am", 

  "you've" : "I have", 

  "you'll" : "I will", 

  "your"   : "my", 

  "yours"  : "mine", 

  "you"    : "me", 

  "me"     : "you" 

} 

 

class Chat(object): 

    def __init__(self, pairs, reflections={}): 

        """ 

        Initialize the chatbot.  Pairs is a list of patterns and responses.  Each 

        pattern is a regular expression matching the user's statement or question, 

        e.g. r'I like (.*)'.  For each such pattern a list of possible responses 

        is given, e.g. ['Why do you like %1', 'Did you ever dislike %1'].  Material 

        which is matched by parenthesized sections of the patterns (e.g. .*) is mapped to 

        the numbered positions in the responses, e.g. %1. 

 

        :type pairs: list of tuple 

        :param pairs: The patterns and responses 

        :type reflections: dict 

        :param reflections: A mapping between first and second person expressions 

        :rtype: None 

        """ 

 

        self._pairs = [(re.compile(x, re.IGNORECASE),y) for (x,y) in pairs] 

        self._reflections = reflections 

 

    # bug: only permits single word expressions to be mapped 

    def _substitute(self, str): 

        """ 

        Substitute words in the string, according to the specified reflections, 

        e.g. "I'm" -> "you are" 

 

        :type str: str 

        :param str: The string to be mapped 

        :rtype: str 

        """ 

 

        words = "" 

        for word in string.split(string.lower(str)): 

            if word in self._reflections: 

                word = self._reflections[word] 

            words += ' ' + word 

        return words 

 

    def _wildcards(self, response, match): 

        pos = string.find(response,'%') 

        while pos >= 0: 

            num = string.atoi(response[pos+1:pos+2]) 

            response = response[:pos] + \ 

                self._substitute(match.group(num)) + \ 

                response[pos+2:] 

            pos = string.find(response,'%') 

        return response 

 

    def respond(self, str): 

        """ 

        Generate a response to the user input. 

 

        :type str: str 

        :param str: The string to be mapped 

        :rtype: str 

        """ 

 

        # check each pattern 

        for (pattern, response) in self._pairs: 

            match = pattern.match(str) 

 

            # did the pattern match? 

            if match: 

                resp = random.choice(response)    # pick a random response 

                resp = self._wildcards(resp, match) # process wildcards 

 

                # fix munged punctuation at the end 

                if resp[-2:] == '?.': resp = resp[:-2] + '.' 

                if resp[-2:] == '??': resp = resp[:-2] + '?' 

                return resp 

 

    # Hold a conversation with a chatbot 

    def converse(self, quit="quit"): 

        input = "" 

        while input != quit: 

            input = quit 

            try: input = raw_input(">") 

            except EOFError: 

                print(input) 

            if input: 

                while input[-1] in "!.": input = input[:-1] 

                print(self.respond(input))