Build a ChatBot with ChatGPT and React
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.
Discover how at OpenReplay.com.
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:
-
Node.js and npm: Install Node.js, which includes npm (Node Package Manager), from the official website. npm will be used to manage dependencies and run scripts for the project.
-
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
- 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
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 theApp.jsx
file should look like.
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:
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.
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.
// 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.
<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.
<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:
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.
<MessageInput placeholder='Type Message here' onSend={handleUserMessage}/>
Now, let’s create the handleUserMessage
function. This function will serve two roles:
- 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.
- Updating chat messages with the new user message.
// 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 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.
const OPENAI_API_KEY = "YOUR API KEY"; //Replace with your generated openai api key
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:
- 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.
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 };
});
}
- 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.
// System message for ChatGPT
const systemMessage = {
role: "system",
content: "Explain all concept like a Professor in Biochemistry",
};
- 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.
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 and return the response.
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.
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.
// 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.
// 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.
// 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.
<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:
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.
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 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!
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.