Build A ChatBot With ChatGPT And React
Published: 2023-10-13 15:40:27

by [Daniel Onyebuchi](https://blog.openreplay.com/authors/daniel-onyebuchi)

<blockquote><em>
As AI technology advances, chatbots have become a powerful tool for improving user interactions. By combining ChatGPT with user-friendly frameworks like React, developers can create intelligent and dynamic chatbots that engage users in natural and meaningful conversations. This article will show you how to create an AI chatbot using ChatGPT and React, setting up the development environment, customizing the chatbot's user interface, and managing responses from the ChatGPT API.
</em></blockquote>

<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>

Let's start with the setup. This involves importing dependencies and installing the tools and software the app will need.

Some tools and software that we will use to build the simple chatbot are:

1. **Node.js and npm:** Install Node.js, which includes npm (Node Package Manager), from the official [website](https://nodejs.org/). npm will be used to manage dependencies and run scripts for the project.

2. **Create a new React App using Vite:** Open your terminal and create a new React app by running the command below
```
npm create vite@latest app -- --template react
```
Navigate to the app directory using this command in your terminal:
```
cd app
```
Then, run:
```
npm install
```

3. **Install `chat-ui-kit-react`:**  This is a UI kit library for building chat interfaces in React applications. To install it, use the following command:
```
npm install @chatscope/chat-ui-kit-react
```
To learn more about the `chat-ui-kit-react` library, you can read the documentation [here](https://chatscope.io/storybook/react/)

We'll also require some dependencies that will be used in styling the components. The dependencies will be imported on the `App.jsx` file. You can find it by

* Expanding the app folder.
* Clicking on the src folder.
* Navigating to `App.jsx`.
* On `App.jsx`, delete the template and leave only the parent element. This is what the `App.jsx` file should look like.
```javascript
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {

 return (
   <>      
   </>
 )
}

export default App
```
Import the following components:
```javascript
import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
import { MainContainer, ChatContainer, MessageList, Message, MessageInput, TypingIndicator } from '@chatscope/chat-ui-kit-react'
```

## Creating Chat UI
`chat-ui-kit-react` provides components to create a chat interface. We will build the components that include all our chat functionalities in our `App.jsx` file.
```javascript
return (
 <>
   {/* A container for the chat window */}
   <div style={{ position: "relative", height: "100vh", width: "700px" }}>
     {/* All components are wrapped in the MainContainer */}
     <MainContainer>
       {/* All chat logic will be contained in the ChatContainer */}
       <ChatContainer>
         {/* Shows all our messages */}
         <MessageList></MessageList>
       </ChatContainer>
     </MainContainer>
   </div>
 </>
);
```
Further styling can be applied by editing the `Index.css` file or adding inline styles.

### Manage Messages State
The `MessageList` component is used to display all of our various messages. We need to store these messages in an array using `useState` and initialize it with one message.
```javascript
// State to store chat messages
const [chatMessages, setChatMessages] = useState([
 {
   message: "Hello, I am ChatGPT!",
   sender: "ChatGPT",
 },
]);
```

To display these messages in our UI, we can achieve this by mapping over the array and rendering each message.
```javascript
<MessageList>
 {/* Map through chat messages and render each message */}
 {chatMessages.map((message, i) => {
   return <Message key={i} model={message} />;
 })}
</MessageList>;
```

For a better layout, we can apply some styling to messages from ChatGPT so that the responses are aligned to the left.
```javascript
<MessageList>
 {/* Map through chat messages and render each message */}
 {chatMessages.map((message, i) => {
   return (
     <Message
       key={i}
       model={message}
       style={message.sender === "ChatGPT" ? { textAlign: "left" } : {}}
     />
   );
 })}
</MessageList>;
```

We can view our Chatbot by running this command on the terminal.
```
npm run dev
```

Our UI should look like this:
![-](https://blog.openreplay.com/images/build-a-chatbot-with-chatgpt-and-react/images/image1.png)

###  Handling user input
`MessageInput` component enables users to input messages for processing. Additionally, we can implement a function named `handleUserMessage` to manage the user's entered messages. This component should be added after the `MessageList` component.
```javascript
<MessageInput placeholder='Type Message here' onSend={handleUserMessage}/>
```

Now, let's create the `handleUserMessage` function. This function will serve two roles:
1. Creating a new user object that will contain:
i. The message from the user.
ii. A description of the user as the sender.
iii. Indication of the message direction as outgoing. This means the message will be displayed on the left side of the chat UI.
2. Updating chat messages with the new user message.
```javascript
// Function to handle user messages
const handleUserMessage = async (userMessage) => {
 // Create a new user message object
 const newUserMessage = {
   message: userMessage,
   sender: "user",
   direction: "outgoing",
 };

 // Update chat messages state with the new user message
 const updatedChatMessages = [...chatMessages, newUserMessage];
 setChatMessages(updatedChatMessages);
};
```

## Set Up ChatGPT API
To set up ChatGPT API to process user messages, we can follow these steps:
### Obtaining an API key from OpenAI
* Visit the [OpenAI website](https://platform.openai.com/) and create an account.
* Log in to your account and click on your profile name or icon to access the menu.
* From the menu, select the 'View API Keys' option.
* Click on the 'Create New Secret Key' button.
* Once the API key is generated, copy and paste it somewhere safe. 
**Note:** The key will not be displayed again, so store it securely.
### Setting up ChatGPT API access
We can store the API key as a variable above the `App` function.
```javascript
const OPENAI_API_KEY = "YOUR API KEY"; //Replace with your generated openai api key
```


<CTA_Middle_Programming />



## Process Message with ChatGPT API
After the `handleUserMessage` function, we will create an asynchronous function called `processUserMessageToChatGPT`. This function captures the user's message, sends it to ChatGPT, and returns a response from ChatGPT. The steps involved are as follows:

1. **Preparing the messages in the required format for the API**: Messages are categorized into three roles: User, Assistant, and System. "User" represents messages input by the user, and "Assistant" refers to messages from ChatGPT.
```javascript
async function processUserMessageToChatGPT(messages) {
 // Prepare the messages in the required format for the API
 let apiMessages = messages.map((messageObject) => {
   let role = "";
   if (messageObject.sender === "ChatGPT") {
     role = "assistant";
   } else {
     role = "user";
   }
   return { role: role, content: messageObject.message };
 });
}
```

2. **Create a System message for ChatGPT:** A system message is a special message that provides instructions or context to the language model before processing user messages. It helps guide the behavior and response of the model during the conversation. 
For instance, a system message could include instructions like: 
* "Explain all concepts like Shakespeare."
* "You are a customer support representative for a tech company."
You can improve the system message prompt for specific chatbot use cases across different industries, such as Travel, Technology, etc. 
```javascript
// System message for ChatGPT
const systemMessage = {
 role: "system",
 content: "Explain all concept like a Professor in Biochemistry",
};
```

3. **Prepare the API request body:** This is used as a container for the conversation messages and system instructions, and it is sent to the OpenAI API for processing by the ChatGPT model.
```javascript
const apiRequestBody = {
 model: "gpt-3.5-turbo",
 messages: [
   systemMessage, // System message should be in front of user messages
   ...apiMessages,
 ],
};
```

4. Send the user message to ChatGPT API and return the response. 
```javascript
await fetch("https://api.openai.com/v1/chat/completions", {
 method: "POST",
 // Set the request headers, including the authorization, using the API key.
 headers: {
   Authorization: "Bearer " + OPENAI_API_KEY, // Replace OPENAI_API_KEY with the actual API key.
   "Content-Type": "application/json",
 },
 // Convert the API request body object into a JSON string and send it as the request body.
 body: JSON.stringify(apiRequestBody),
})
 // Once the API response is received, convert it to JSON format.
 .then((data) => {
   return data.json();
 })
 // After converting to JSON, extract the chatbot's response message from the API response.
 .then((data) => {
   // Update the chat messages.
   setChatMessages([
     ...messages,
     {
       message: data.choices[0].message.content,
       sender: "ChatGPT",
     },
   ]);
 });
```

**Note:** Remember to include a space after "Bearer" in the Authorization header; otherwise, API calls may fail.

We can now call the `processUserMessageToChatGPT` function in the `handleUserMessage` function.
```javascript
await processUserMessageToChatGPT(updatedChatMessages);
```

### Managing loading states while waiting for the API response
We can set a typing indicator to display while the chatbot is processing a response.
Firstly, we'll create a state to indicate typing and set it to false.
```javascript
// State to manage the typing indicator of the chatbot
const [isChatbotTyping, setIsChatbotTyping] = useState(false);
```

In the `handleUserMessage` function, you can set the indicator to true. This line should be added before calling the `processUserMessageToChatGPT` function.
```javascript
// Set the typing indicator for the chatbot
setIsChatbotTyping(true);
```
Once the response has been received from ChatGPT, within the `processUserMessageToChatGPT` function, you can set the state to false after updating the chat messages.
```javascript
// Set the typing indicator to false after getting the response
setIsChatbotTyping(false);
```

You can display the indicator in the UI when it's true by utilizing the `typingIndicator` property. 
```javascript
<MessageList
 // Display a typing indicator when the chatbot is processing a response.
 typingIndicator={
   isChatbotTyping ? <TypingIndicator content="ChatGPT is thinking" /> : null
 }
>
 {/* Map through chat messages and render each message */}
 {chatMessages.map((message, i) => {
   return (
     // Render each individual chat message as a <Message> component.
     <Message
       key={i}
       model={message}
       // Add additional styling to align the chatbot's response to the left.
       style={message.sender === "ChatGPT" ? { textAlign: "left" } : {}}
     />
   );
 })}
</MessageList>;
```

The Final `App.jsx` file should look like this:
```javascript
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
import {
 MainContainer,
 ChatContainer,
 MessageList,
 Message,
 MessageInput,
 TypingIndicator,
} from "@chatscope/chat-ui-kit-react";

const OPENAI_API_KEY = "YOUR API KEY";

function App() {
 // State to manage the typing indicator of the chatbot
 const [isChatbotTyping, setIsChatbotTyping] = useState(false);

 // State to store chat messages
 const [chatMessages, setChatMessages] = useState([
   {
     message: "Hello, I am ChatGPT!",
     sender: "ChatGPT",
   },
 ]);

 // Function to handle user messages
 const handleUserMessage = async (userMessage) => {
   // Create a new user message object
   const newUserMessage = {
     message: userMessage,
     sender: "user",
     direction: "outgoing",
   };

   // Update chat messages state with the new user message
   const updatedChatMessages = [...chatMessages, newUserMessage];
   setChatMessages(updatedChatMessages);

   // Set the typing indicator for the chatbot
   setIsChatbotTyping(true);

   // Process user message with ChatGPT
   await processUserMessageToChatGPT(updatedChatMessages);
 };

 // Function to send the user message to ChatGPT API
 async function processUserMessageToChatGPT(messages) {
   // Prepare the messages in the required format for the API
   let apiMessages = messages.map((messageObject) => {
     let role = "";
     if (messageObject.sender === "ChatGPT") {
       role = "assistant";
     } else {
       role = "user";
     }
     return { role: role, content: messageObject.message };
   });

   // System message for ChatGPT
   const systemMessage = {
     role: "system",
     content: "Explain all concept like a Professor in Biochemistry",
   };

   // Prepare the API request body
   const apiRequestBody = {
     model: "gpt-3.5-turbo",
     messages: [
       systemMessage, // System message should be in front of user messages
       ...apiMessages,
     ],
   };

   // Send the user message to ChatGPT API
   await fetch("https://api.openai.com/v1/chat/completions", {
     method: "POST",
     headers: {
       Authorization: "Bearer " + OPENAI_API_KEY,
       "Content-Type": "application/json",
     },
     body: JSON.stringify(apiRequestBody),
   })
     .then((data) => {
       return data.json();
     })
     .then((data) => {
       // Update chat messages with ChatGPT's response
       setChatMessages([
         ...messages,
         {
           message: data.choices[0].message.content,
           sender: "ChatGPT",
         },
       ]);
       // Set the typing indicator to false after getting the response
       setIsChatbotTyping(false);
     });
 }

 return (
   <>
     {/* A container for the chat window */}
     <div style={{ position: "relative", height: "100vh", width: "700px" }}>
       <MainContainer>
         <ChatContainer>
           {/* Display chat messages and typing indicator */}
           <MessageList
             typingIndicator={
               isChatbotTyping ? (
                 <TypingIndicator content="ChatGPT is thinking" />
               ) : null
             }
           >
             {/* Map through chat messages and render each message */}
             {chatMessages.map((message, i) => {
               return (
                 <Message
                   key={i}
                   model={message}
                   style={
                     message.sender === "ChatGPT" ? { textAlign: "left" } : {}
                   }
                 />
               );
             })}
           </MessageList>
           {/* Input field for the user to type messages */}
           <MessageInput
             placeholder="Type Message here"
             onSend={handleUserMessage}
           />
         </ChatContainer>
       </MainContainer>
     </div>
   </>
 );
}

export default App;
```

Your AI ChatBot, with its full functionality, is now complete.

![-](https://blog.openreplay.com/images/build-a-chatbot-with-chatgpt-and-react/images/image2.gif)

## Common Errors and How to Fix Them
Errors may occur during the installation of the `chat-ui-kit-react` library. You may encounter errors such as:
```
npm ERR! code 1
npm ERR! path C:\Users\work\Documents\vs code\app\node_modules\esbuild
npm ERR! command failed
npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node install.js
npm ERR! node:child_process:828
npm ERR!     err = new Error(msg);
npm ERR!           ^
npm ERR!
npm ERR! Error: Command failed: C:\Program Files\nodejs\node.exe 
```

Here's how you can resolve it:
* Remove the node modules
```
rmdir /s /q node_modules
```

* Install the latest npm
```
npm install -g npm@latest  
```

* Finally, reinstall the package
```
npm install @chatscope/chat-ui-kit-react
```

Errors may also occur when making requests to the API. This is the [documentation](https://platform.openai.com/docs/guides/error-codes/api-errors) on the meaning of the different errors you may encounter.

## Conclusion
Setting up the development environment, Creating the chatbot user interface, and handling user messages using the ChatGPT API are vital steps in building an effective chatbot. With the power of AI, chatbots can significantly enhance user interactions and customer service in various industries.

So, go ahead and explore the world of AI chatbots with ChatGPT and React, and unlock new possibilities for seamless and interactive user engagements!