Creating a LINE bot w/ Flask - Conversate with your Bot

Creating a LINE bot w/ Flask - Conversate with your Bot

In 1966, there was a bot named ELIZA, a psychotherapist who has the ability to communicate with a patient. She was written by Joseph Weizenbaum to mimic the rogerian physician, Carl Rodgers, well-known for rhetorically answering his patients. Here is an example of ELIZA in action:

ELIZA: Is something bothering you ?
YOU: Men are all alike.
ELIZA: What is the connection, do you suppose ?
YOU: They are always bugging us about something or other.
ELIZA: Can you hink of a specific example ?
YOU: Well, my boyfriend made me come here.
ELIZA: Is it important that your boyfriend made you came here ?
YOU: He says I'm depressed much of the time.
ELIZA: I'm sorry to hear that you are depressed.
YOU: It's true. I am unhappy.
ELIZA: Can you explain what made you unhappy ?
...

As you could see, this is quite phenomenal given that it was written in the '70s and it is capable of attempting the Turing Test. Now, shall we implement this in our bot? But first, dependencies.

# Install nltk package
pip install nltk

nltk.chat.eliza

ELIZA is built on pattern recognition. So each response is returned based on certain keywords within the user's input. There are two variables that need to be addressed: (1) a dict of reflections for pronoun substitution (e.g. I <-> you etc.), and (2) a tuple of response pairs, i.e. a regex matcher and a list of possible responses. This is already written in the nltk package, all we have to do is make some tweaks and implement it using the LINE Messaging API.

After installing the nltk package, we need to create a nltk.chat.util.Chat object and override the converse() method. The original method works as an infinite loop and outputs the response string to STDOUT.

import nltk

class ElizaBot(nltk.chat.util.Chat):
    """
    Inherit from `nltk.chat.eliza.eliza_chatbot` module and 
    override the converse method.
    """
    def converse(
        self, 
        user_input, 
        quit=["goodbye", "good bye", "bye", "see you"]
    ):
        """Override the original converse model of the nltk.util.Chat class
        """
        # If user ends conversation, return one of escapes
        if user_input.lower() in self._escapes:
            return random.choice(self._escapes)
        # Chat with ELIZA otherwise
        while user_input[-1] in "!.":
            user_input = user_input[:-1]
        response = self.respond(user_input)

        return response

Now we could add the bot object to our main function of our bot, and see the results. If you haven't got a LINE bot, create one following the steps here.

...
# Initialize chatbot instance
bot = chat.ElizaBot()

# Text message handler
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    # Retrieve user metadata
    user_id = event.source.user_id
    user_msg = event.message.text

    # Log user metadata
    print(f"\nUser: {user_id}")
    print(f"Message: {user_msg}\n")

    # Generate response
    resp = bot.converse(user_msg)

    # Reply user
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=resp)
    )

There are also other "characters" in the nltk.chat module such as SunTzu, Zen, and a teenage junky Iesha. By experimenting these different characters, you might notice that there is a lack of realism in some ways because these "models" actually have no understanding of languages. Of course, we could use neural conversational language models, but that's for another day.

References