natural language toolkit chatbot utilities c 20012023 nltk project s steven bird stevenbird1gmail com url https www nltk org for license information see license txt based on an eliza implementation by joe strout joestrout net jeff epler jeplerinetnebr com and jez higgins jezjezuk co uk 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 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 generate a response to the user input type str str param str the string to be mapped rtype str check each pattern did the pattern match fix munged punctuation at the end hold a conversation with a chatbot natural language toolkit chatbot utilities c 2001 2023 nltk project s steven bird stevenbird1 gmail com url https 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 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 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 generate a response to the user input type str str param str the string to be mapped rtype str check each pattern did the pattern match pick a random response process wildcards fix munged punctuation at the end hold a conversation with a chatbot
import random
import re

reflections = {
    "i am": "you are",
    "i was": "you were",
    "i": "you",
    "i'm": "you are",
    "i'd": "you would",
    "i've": "you have",
    "i'll": "you will",
    "my": "your",
    "you are": "I am",
    "you were": "I was",
    "you've": "I have",
    "you'll": "I will",
    "your": "my",
    "yours": "mine",
    "you": "me",
    "me": "you",
}


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

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

    def _compile_reflections(self):
        sorted_refl = sorted(self._reflections, key=len, reverse=True)
        return re.compile(
            r"\b({})\b".format("|".join(map(re.escape, sorted_refl))), re.IGNORECASE
        )

    def _substitute(self, str):
        

        return self._regex.sub(
            lambda mo: self._reflections[mo.string[mo.start() : mo.end()]], str.lower()
        )

    def _wildcards(self, response, match):
        pos = response.find("%")
        while pos >= 0:
            num = int(response[pos + 1 : pos + 2])
            response = (
                response[:pos]
                + self._substitute(match.group(num))
                + response[pos + 2 :]
            )
            pos = response.find("%")
        return response

    def respond(self, str):
        

        
        for (pattern, response) in self._pairs:
            match = pattern.match(str)

            
            if match:
                resp = random.choice(response)  
                resp = self._wildcards(resp, match)  

                
                if resp[-2:] == "?.":
                    resp = resp[:-2] + "."
                if resp[-2:] == "??":
                    resp = resp[:-2] + "?"
                return resp

    
    def converse(self, quit="quit"):
        user_input = ""
        while user_input != quit:
            user_input = quit
            try:
                user_input = input(">")
            except EOFError:
                print(user_input)
            if user_input:
                while user_input[-1] in "!.":
                    user_input = user_input[:-1]
                print(self.respond(user_input))