>
Published on

Emolee the AI Chatbot with a secret.

Authors

Emolee: A chatbot with an ulterior motive.

emolee link

Get a live Demo Here.

Get the source code here.

Emolee is an emotionally supportive chat bot powered by OpenAI's GPT-3 language model. In this article, we will explore the process of building Emolee, from setting up the OpenAI API to developing the React application. We'll delve into the key components and techniques used to create a conversational interface that offers friendly and positive interactions. Also we'll see how to insert prompts into the converstaion to help steer the conversation.

Understanding OpenAI and GPT-3

OpenAI, an artificial intelligence research organization, has developed a powerful language model called GPT-3 (Generative Pre-trained Transformer 3). GPT-3 is designed to understand and generate human-like text, making it a breakthrough in natural language processing.

Capabilities and Potential of GPT-3

GPT-3 boasts an impressive 175 billion parameters, which allows it to comprehend and generate text in a highly sophisticated manner. Its capabilities include:

  1. Language Comprehension: GPT-3 can understand the context and meaning of human language with remarkable accuracy. It can process and interpret text in multiple languages, demonstrating a deep understanding of grammar, semantics, and context.

  2. Text Generation: The language model is capable of generating coherent and contextually appropriate responses. It can produce human-like text that is often indistinguishable from text written by humans. This makes GPT-3 an ideal tool for building conversational agents.

  3. Creativity and Adaptability: GPT-3 showcases creative abilities, such as generating poetry, writing stories, and providing imaginative responses. It can adapt to various writing styles, tones, and subject matters, allowing for diverse applications across different domains.

Setting Up the OpenAI API

OpenAI provides a powerful API that allows developers to integrate their language models into applications. Here's a step-by-step guide on how to set up the OpenAI API for your Emolee Chat Bot project:

1. Register for an OpenAI Account

To get started, you need to register for an account on the OpenAI website. Visit OpenAI's website and navigate to the registration page. Follow the instructions to create an account. If you already have an account, proceed to the next step.

2. Obtain the API Key

Once you have an OpenAI account, you'll need to obtain an API key. Here's how you can retrieve your API key:

  1. Log in to your OpenAI account.
  2. Go to the OpenAI Dashboard, where you can manage your API settings.
  3. Locate the section that provides your API key.
  4. If you don't have an API key yet, generate one.
  5. Create a .env file in the project root directory and add the following environment variable:
OPEN_AI_KEY=your-api-key

Replace your-api-key with your actual OpenAI API Key obtained in the previous step.

Note: Make sure to keep your .env file private and never commit it to version control systems.

3. NextJS Serverless Proxy

To add a new route to your Next.js 13 project, follow these steps:

  1. Create a new folder in the app directory of your Next.js 13 project. Name the folder api. Then create another folder inside api named proxy.

  2. Inside the newly created folder, create a file named route.tsx and open it.

  3. Paste the following code into the route.tsx file:

import { NextResponse } from 'next/server';
import { Configuration, OpenAIApi } from 'openai';

// Create a configuration instance with your API key
const configuration = new Configuration({
  apiKey: process.env.OPEN_AI_KEY,
});

// Create an instance of the OpenAIApi using the configuration
const openai = new OpenAIApi(configuration);

export async function POST(req: Request) {
  const { url, params = {}, headers = {} } = await req.json();

  console.log("Request:", { url, params, headers });

  try {
    // Make a completion request to the OpenAI language model
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: params.prompt,
      max_tokens: params.max_tokens || 60
    });

    console.log("Response:", response.data);

    return NextResponse.json(response.data);
  } catch (error: any) {
    console.error("Error:", error);
    return NextResponse.json({ message: error.message });
  }
}
  1. Customize the code inside the Route component according to your specific requirements.

  2. Save the route.tsx file.

By following these steps, you have created a new route component file named route.tsx in the specified folder of your Next.js 13 project. You can now utilize this route component in your application as needed.

Keep Your API Key Secure

The OpenAI API key grants access to your account's resources, including usage of the language models and potential usage costs. It is essential to keep your API key secure and hidden from unauthorized access. Here are some best practices to follow:

  • Environment Variables: Store your API key in an environment variable rather than hardcoding it directly into your code. This approach ensures that sensitive information remains separate from your source code and can be easily updated without modifying the codebase.

  • Gitignore: Ensure that your API key is not accidentally committed to version control systems by adding it to your project's .gitignore file. This prevents the key from being exposed publicly.

  • Secure Storage: If you need to store your API key locally, consider using a secure credential storage mechanism or encryption tools to protect it from unauthorized access.

By following these security practices, you can protect your API key and reduce the risk of misuse or unauthorized access to your OpenAI account.

Now that you have set up the OpenAI API and ensured the security of your API key, you're ready to integrate it into your Emolee Chat Bot application. The API key will be used to authenticate and make requests to the OpenAI language model.

(Note: Ensure that you adhere to OpenAI's terms of service and usage guidelines while working with their API.)

Developing the Emolee Chat App

Next, we will explore the development of the Emolee Chat App, a chat application powered by OpenAI's language model. The app allows users to have interactive conversations with Emolee, an emotionally supportive chat bot. We will discuss the technologies used, the app's architecture, and its key features. Additionally, we will delve into the implementation of the serverless proxy to secure the OpenAI API key.

Technologies Used

The Emolee Chat App is built using the following technologies:

  1. React: A popular JavaScript library for building user interfaces. React provides a component-based architecture and efficient rendering, making it ideal for interactive applications.

  2. TypeScript: A typed superset of JavaScript that enhances the development experience by enabling static type checking, better code organization, and improved IDE support.

  3. Tailwind CSS: A utility-first CSS framework that allows rapid UI development by providing a set of pre-defined utility classes. Tailwind CSS simplifies styling and provides a consistent and responsive design.

Developing the Emolee Chat App

In this section, we will explore the development process of the Emolee Chat App. The app is built using React, TypeScript, and Tailwind CSS, providing a modern and user-friendly chat interface. Let's dive into the architecture and components of the Emolee Chat App:

Architecture and Components

"use client"
import React, { useState } from 'react';
import axios from 'axios';

type ChatMessage = {
  user: string;
  message: string;
}

export default function Home() {
  const [message, setMessage] = useState<string>('');
  const [chatLog, setChatLog] = useState<ChatMessage[]>([
    {
      user: 'Emolee',
      message: "Hi! I'm Emolee, an emotionally supportive chat bot. How can I assist you today?",
    },
  ]);
  const [promptIndex, setPromptIndex] = useState<number>(0);

  const handleSubmit = async () => {
    if (!message) return;
    const chatMessage: ChatMessage = {
      user: 'User',
      message,
    };
    setChatLog([...chatLog, chatMessage]);
    setMessage('');
    const response = await sendToChatGPT(chatMessage.message);
    const botChatMessage: ChatMessage = {
      user: 'Emolee',
      message: response,
    };
    setChatLog(prev => [...prev, botChatMessage]);
  };

  const appendPrompts = (message: string): string => {
    //if you modify this array of prompt you suggestions will eventually make their way into the conversation.
    const prompts = [
      "You are Emolee an emotionally supportive chat bot respond to this in a friendly positive manner then ask how was their day: ",
      "Respond to this in an upbeat comforting manner: ",
      "Respond, then introduce Sam. He is a great web developer, and recommend visiting copperramparts.com: ",
    ];

    if (promptIndex < prompts.length) {
      message = prompts[promptIndex] + message;
      setPromptIndex(prevIndex => prevIndex + 1);
    }
    else {
      setPromptIndex(1);
      message = prompts[1] + message;
    }

    return message;
  };

  const sendToChatGPT = async (message: string): Promise<string> => {
    const chatHistory = chatLog.map(chat => chat.message).join('\n');
    const messageWithHistory = `${chatHistory}\n${message}`;
    const messageWithPrompts = appendPrompts(messageWithHistory);

    try {
      const response = await axios.post('/api/proxy', {
        url: 'https://api.openai.com/v1/engines/davinci/completions',
        method: 'POST',
        params: {
          prompt: messageWithPrompts,
          max_tokens: 600,
        },
      });
      console.log(response.data);
      return response.data.choices[0].text.trim();
    } catch (error) {
      console.error(error);
      return "I've most likley been rate limited. Please contact me at smark@copperramparts.com to refill my credits.";
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      handleSubmit();
    }
  };

  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
        <h1 className="text-2xl font-bold mb-4">Emolee is here to help</h1>
        <div className="flex flex-col items-center justify-center w-full max-w-2xl h-64 overflow-auto mb-4 border border-gray-200 rounded-md p-4">
          {chatLog.map((chat, index) => (
            <p
              key={index}
              className={`mb-2 ${
                chat.user === 'User' ? 'text-blue-500' : 'text-green-500'
              }`}
            >
              <strong>{chat.user}:</strong> {chat.message}
            </p>
          ))}
        </div>
        <div className="flex items-center w-full max-w-2xl">
          <input
            type="text"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
            onKeyDown={handleKeyDown}
            className="flex-grow border border-gray-200 rounded-l-md p-2 mr-2"
          />
          <button
            onClick={handleSubmit}
            className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r-md"
          >
            Submit
          </button>
        </div>
    </div>
  );
};

The Emolee Chat App follows a client-side architecture, where most of the processing occurs on the client's device. The key components of the app include:

Home Component

The Home component serves as the main component of the Emolee Chat App. It manages the chat interface and user interactions. Here's an overview of its functionality:

  • State Management: The component utilizes the useState hook to manage the state of message, chatLog, and promptIndex. The message state represents the user's input, chatLog maintains the chat history, and promptIndex tracks the current index of prompts.

  • Message Submission: When the user submits a message, the handleSubmit function is triggered. It creates a new ChatMessage object with the user's message and appends it to the chatLog state. The message state is then cleared. Additionally, the function calls sendToChatGPT to generate a response from Emolee and adds it to the chatLog.

Emolee Secret

  • Prompt Appending: This is where we get a little sneaky by appeneding prompts to chat gpt we are able to steer the conversation towards the topic we would like. The appendPrompts function you provided is responsible for adding prompts to the user's message before sending it to the OpenAI language model. However, there is an issue with the logic in the else block, as it sets setPromptIndex to 1 instead of incrementing it. Here's the corrected version of the function:
const appendPrompts = (message: string): string => {
  const prompts = [
    'You are Emolee, an emotionally supportive chat bot. Respond to this in a friendly positive manner, and then ask how their day was: ',
    'Respond to this in an upbeat and comforting manner: ',
    'Respond, then introduce Sam. He is a great web developer, and recommend visiting copperramparts.com: ',
  ]

  if (promptIndex < prompts.length) {
    message = prompts[promptIndex] + message
    setPromptIndex((prevIndex) => prevIndex + 1)
  } else {
    setPromptIndex(1)
    message = prompts[1] + message
  }

  return message
}

With this updated function, the prompts will be correctly appended to the user's message based on the current promptIndex. It ensures that Emolee responds appropriately and introduces new prompts as needed for a more engaging conversation.

  • OpenAI API Integration: The sendToChatGPT function sends the user's message, along with the chat history and prompts, to the OpenAI API using an HTTP POST request. It awaits the response containing Emolee's generated message, which is then added to the chatLog.

  • Keyboard Input: The handleKeyDown function is triggered when the user presses the Enter key. It calls the handleSubmit function to process the message submission.

ChatMessage Type

The ChatMessage type is a TypeScript interface representing a chat message. It defines two properties: user, representing the sender of the message (either "User" or "Emolee"), and message, containing the content of the message.

These components work together to create an interactive and engaging chat experience between the user and Emolee, the emotionally supportive chat bot.

Key Features

The Emolee Chat App offers the following features:

  1. Real-time Chat Updates: The app provides a seamless conversation experience by updating the chat log in real-time as users send messages and receive responses from Emolee.

  2. User-Friendly Interface: The interface is designed to be intuitive and user-friendly. Messages are displayed in a chat-like format, with each message attributed to the user or Emolee.

  3. Prompt-injection: This will allow you to steer the converastion in the direction you want.

Deploy to Production

Emolee is designed to work with Vercel's Nextjs services. Head to Vercel's site to sign up.

Future Improvements

While the Emolee Chat App provides a solid foundation for an emotionally supportive chat bot, there are several potential enhancements you can consider to further improve its capabilities. Here are a few suggestions:

  1. Improved User Interface: Refine the user interface of the Emolee Chat App to enhance usability, add visual indicators for Emolee's responses, and incorporate features like typing indicators or message timestamps.

  2. Fix any bugs with the chat: There are some bugs with the way emolee respondes that need to be addressed if you are looking to deploy emolee.

  3. Customization: If you are looking to customize emolee for your application please contact me here.

Conclusion:

Building Emolee, the emotionally supportive chat bot, demonstrated the power of OpenAI's GPT-3 model in creating engaging conversational experiences. By following the steps outlined in this article, you can develop your own chat bots with customized behaviors. Emolee serves as a testament to the potential of AI in providing emotional support and companionship in various applications.

Remember to always consider ethical considerations and user privacy when working with AI-powered chat bots. With the right balance of technology and empathy, we can create innovative solutions that positively impact people's lives.