Create your own ChatGPT clone using React and OpenAI APIs
Updated 4 months ago on July 28, 2024
Table of Contents
- Key findings
- Scheduling features and user interface
- Choice of color scheme
- Customizing a React application
- Adding global styles
- Loading media
- Component creation
- Component "Message
- Component "Input
- History component
- Clear component
- Creating a user interface
- Creating an application layout
- Obtaining an API key from OpenAI
- Preparing a request call to the OpenAI API
- Application testing
- Conclusion
- Frequently Asked Questions (FAQ) about creating a ChatGPT clone using React and OpenAI APIs
- What is the main purpose of using React to create a ChatGPT clone?
- How does the OpenAI API affect the functionality of the ChatGPT clone?
- Can I customize the ChatGPT clone to my needs?
- What are the prerequisites for creating a ChatGPT clone?
- How can I deal with OpenAI API errors or unexpected responses?
- How can I improve the performance of my ChatGPT clone?
- Is it possible to deploy a ChatGPT clone on a server?
- Can I use other machine learning models with the ChatGPT clone?
- How can I add more features to the ChatGPT clone?
- How do I secure the communication between the ChatGPT clone and the OpenAI API?
In this tutorial, we will look at how to create a custom Chatbot application that will allow us to ask questions and get quality answers. The bot will remember previous prompts, mimicking the conversation with contextualization.
Key findings
- Creating a chatbot using OpenAI ChatGPT and React : This tutorial provides step-by-step instructions for creating a custom chatbot application in React using OpenAI ChatGPT for advanced language processing. The chatbot remembers previous prompts, simulating a continuous, context-aware conversation.
- User Interface and Feature Implementation : The application has a user-friendly interface with components such as message box, input area, send button and conversation history. It demonstrates how to structure a React application, manage state and handle events to provide a seamless user experience.
- API call integration and data processing : The guide covers the process of making API calls to OpenAI's ChatGPT and processing data to display chatbot responses. It emphasizes the importance of protecting the API key, especially for production, and suggests improvements such as using Express for server-side operations and enabling persistent storage for conversation history.
env
. To get it, create an account on OpenAI, log in, go to the API keys section and generate a new API key.
Scheduling features and user interface
Our application will be based on React , and we will use OpenAI API for data access and CSS modules for styling. Using React will allow us to create a dynamic and responsive user interface, which will improve the overall user experience. The OpenAI API will allow us to access advanced language processing capabilities, providing data to create insightful interactions. In addition, CSS modules will allow us to support modular design, facilitating efficient development and customization of the application. The features we will be implementing include:- A special input area where users will be able to create hints by suggesting contextually relevant queries.
- Submit button , which will allow users to submit their requests to the API, initiating the conversation process.
- Message elements to be displayed as chat-style messages in the conversation window, improving chat interactivity.
- Message items to display ChatGPT responses that provide a conversational flow.
- History function , which will list all recent user prompts. This will also allow users to go back to previous conversations.
- The " Clear" button will allow you to delete the content you created, opening up a new page for new conversations.
Choice of color scheme
The design of the app prioritizes the ease of experiencing the content. This will allow us to provide several important benefits:- Users will be able to quickly grasp the information presented, leading to a more intuitive and user-friendly experience.
- It will also increase accessibility, ensuring that people of different backgrounds and abilities can easily navigate and engage with the content.
Customizing a React application
We will use create-react-app to create our app. Run npx create-react-app react-chatgpt
to create a new React project. Wait a minute for the setup to complete, and then change the working directory to the folder you just created using cd react-chatgpt
and run npm start
to start the developer server. This should open our project in the default browser. If it doesn't, go to http://localhost:3000 to open it manually. The React welcome screen should appear in front of us, as shown in the image below.Adding global styles
We will add a global style to create a unified visual appearance for all components of the application. Open index.css
and include the following styling rules:@import url ("https://fonts.googleapis.com/css2?family=Varela+Round&display=swap" ) ; * { margin : 0 ; padding : 0 ; box-sizing : border-box ; font-family : "Varela Round", sans-serif ; } body { background-color : #121212 ; }First, we'll import the Varela Round font and customize the entire application to use it. We will also remove all the preset margins and indents, and set the
box-sizing
on border-box
to make the application look the same in different browsers. Finally, we set the body background to a dark tone, which helps to highlight the application's content.Loading media
We will need a couple of avatars to represent the authors of messages from the user and the OpenAI API. This way they will be easier to distinguish between them. Create a new icons
folder inside src
catalog and include bot.png
и user.png
Icons.
You can download samples from the icon
catalog here, or use your own from sites like FlatIcon or Icons8, as long as you keep the above file names.
Component creation
First, we need a well-organized file structure that matches the design of the framework. Using the terminal, we will create the necessary folders and component files. Each component will have its own JavaScript file for functionality and CSS file for styling. Change the working directory in the folder src
by starting a folder cd src
and then run the following command:mkdir components && cd components && touch Message.js Message.module.css Input.js Input.module.css History.js History.module.css Clear.js Clear.module.cssThe above command will first create
/components/
folder, then change the working directory to it and create all the necessary files in it.Component "Message
Website Message
The component will display user prompts and API responses in the conversation, facilitating real-time communication between the user and the chatbot. Open Message.js.
file and include the following code:import bot from "../icons/bot.png" ; import user from "../icons/user.png" ; import styles from "./Message.module.css" ; export default function Message ( { role , content } ) { return ( < div className = { styles . wrapper } > < div > < div > < img src = { role === "assistant" ? bot : user } className = { styles . avatar } alt = "profile avatar" / > < / div > < div > < div > < div > < div > < p > < p > { content } < / p > < / div > < / div > < / div > ) ; }First we import the uploaded icons for avatars, and then import external CSS rules for styling. After that, we create a wrapper for
Message
A component that will contain both icons and text content. We're using part
parameter in the condition to display the corresponding avatar as an image src
. We also use content
which will be passed as a text response from the OpenAI API and a prompt for user input. Now let's design the component to look like a chat message! Open the component Message.module.css
file and include the following rules:.wrapper { display : grid ; grid-template-columns : 60 px auto ; grid-template-columns : 60 px auto ; min-height : 60 px ; padding : 20 px ; margin-bottom : 20 px ; border-radius : 10 px ; background-color : #1b1b1d ; } .avatar { width : 40 px ; height : 40 px ; }We'll split the layout into two columns, with avatars displayed in a fixed-width container on the right and text on the left. We'll then add padding and margins to the bottom of the post. We'll also give the message round borders and set a dark gray background. Finally, we'll set the avatar icon to a fixed width and height.
Component "Input
Website Entry
component will be an interface element designed to collect user requests and serve as the means by which users interact with the chatbot. Open Input.js.
file and include the following code:import styles from "./Input.module.css" ; export default function Input ( { value , onChange , onClick } ) { return ( < div className = { styles . wrapper } > < input className = { styles . text } placeholder = "Your request here..." value = { value } onChange = { onChange } / > < button className = { styles . btn } onClick = { onClick } > Go < / button > < / div > ) ; }First, we import an external stylesheet to design the component. We return a component wrapper that includes an input field for custom prompts and a button to submit to the API. We set a placeholder value to be displayed when the input form is empty, and create a file
significance
a requisite for storing the entered hint, and also onChange
which will be called when the input value is changed. For the button onClick
prop will be called as soon as the user clicks the button. Now let's style the component so that the input area looks beautiful and the user is encouraged by the prompts! Open the component Input.module.css
file and include the following rules:.wrapper { display : grid ; grid-template-columns : auto 100 px ; height : 60 px ; border-radius : 10 px ; background-color : #323236 ; } .text { border : none ; outline : none ; background : none ; padding : 20 px ; color : white ; font-size : 16 px ; } .btn { border : none ; border-radius : 0 10 px 10 px 0 ; font-size : 16 px ; font-weight : bold ; background-color : rgb ( 218 , 255 , 170 ) ; } .btn :hover { cursor : pointer ; background-color : rgb ( 200 , 253 , 130 ) ; }We set the wrapper to be divided into two columns, with a fixed width for the button and the rest of the available width dedicated to the input area. We also set a specific height for the component, set rounded borders for it, and set a dark gray background. For the input area, we'll remove the default borders, outline, and background and add some background. We'll set the text color to white and set a specific font size.
History component
Website History
The component displays a sequence of past interactions between the user and the chatbot, providing users with contextual help about their conversation. Open History.js.
file and include the following code:import styles from "./History.module.css" ; export default function History ( { question , onClick } ) { return ( < div className = { styles . wrapper } onClick = { onClick } > < p > { question . substring ( 0 , 15 ) } ... < / p > < / div > ) ; }First we import the external style rules for the component. Then we return a wrapper that will include text. The value of the text will be passed as
issue
prop from the user prompt, and only the first 15 characters of the text string will be displayed. Users will be allowed to click on history items, and we will pass the parameter onClick
to control the click behavior. Now let's style the component so that it is visually appealing and fits well in the sidebar! Open History.module.css
file and include the following rules:.wrapper { padding : 20 px ; margin-bottom : 20 px ; border-radius : 10 px ; background-color : #1b1b1d ; } .wrapper :hover { cursor : pointer ; background-color : #323236 ; }We'll set the backing, add a bottom indent, and set rounded corners for the story elements. We'll also set the background color to dark gray. When the user hovers over the element, it will turn into a pointer and the background color will change to a lighter shade of gray.
Clear component
Website Clear
The component will be a UI element designed to reset or clear the current conversation, giving users a quick way to start a new interaction without disconnecting from the current interface. Open Clear.js.
file and include the following code:import styles from "./Clear.module.css" ; export default function Clear ( { onClick } ) { return ( < button className = { styles . wrapper } onClick = { onClick } > Clear < / button > ) ; } ; }First, we import an external stylesheet to style the component. We return a button that will allow users to clear the contents of the application. We pass
onClick
to achieve the desired behavior. Now let's style the component to make it stand out and reduce the likelihood of accidental clicks! Open the component Clear.module.css
file and include the following rules:.wrapper { width : 100% ; height : 60 px ; background-color : #ff9d84 ; border : none ; border-radius : 10 px ; font-size : 16 px ; font-weight : bold ; } .wrapper :hover { cursor : pointer ; background-color : #ff886b ; }We'll set the button so that it fills the entire available column width, set a specific height, and set a soft red background color. We will also remove the default borders, set rounded corners, set a specific font size and make it bold. On hover, the cursor will change to a pointer and the background color will change to a darker shade of red.
Creating a user interface
In the previous section, we created all the necessary components. Now let's put them together and create the application's user interface. We will customize their functionality to create a functional and interactive chatbot interface with streamlined and reusable code. Open App.js.
file and include the following code:import { useState } from "react" ; import Message from "./components/Message" ; import Input from "./components/Input" ; import History from "./components/History" ; import Clear from "./components/Clear" ; import "./styles.css" ; export default function App ( ) { const [ input , setInput ] = useState ( "" ) ; const [ messages , setMessages ] = useState ( [ ] ) ; const [ history , setHistory ] = useState ( [ ] ) ; return ( < div className = "App" > < div className = "Column" > < h3 className = "Title" > Chat Messages < / h3 > < div className = "Content" > { messages . map ( ( ( el , i ) => { return < Message key = { i } role = { el . role } content = { el . content } / > > ; } ) } < / div > < Input value = { input } onChange = { ( e ) => setInput ( e . target . value ) } onClick = { input ? handleSubmit : undefined } / > < / div > < div className = "Column" > < h3 className = "Header" > History < / h3 > < div className = "Contents" > { history . map ( ( el , i ) => { return ( < History key = { i } question = { el . question } onClick = { ( ) => setMessages ( [ { role : "user" , content : history [ i ] . question } , { role : "assistant" , content : history [ i ] . answer } , ] ) } / > ) ; } ) } < / div > < Clear onClick = { clear } / > < / div > < / div > < / div > ) ; }First we import
useState
hook, which we will use to track the state of the data in the application. We then import all the components we created and the external stylesheet for styling. Then we create inlet
A state variable to store the user's request input, messages
to store the conversation between the user and ChatGPT, and history
to store the history of user prompts. We are also creating a main wrapper for the entire application that will contain two columns. Each column will have a header and a content wrapper that will include conversation messages, an input area, and a Send for the first column and history elements and Clear For the second column. Conversation messages will be generated by matching via messages
state variable and history elements - by matching through the history
state variable. We set the input onChange
update requisite inlet
state variable every time the user enters any value into the input form. As soon as the user presses the Send button, the user's request will be sent to the OpenAI API for processing and receiving a response. For history elements we set the value onClick
props for messages
the state variable is updated to the specific request and response. Finally, for Clear we pass the button onClick
Write a function that will clear the message and history values by clearing the application data.Creating an application layout
In this section, we will arrange the user interface components to create an intuitive structure for effective user interaction. Open App.css.
and include the following styling rules:.App { display : grid ; grid-template-columns : auto 200 px ; gap : 20 px ; max-width : 1000 px ; margin : 0 auto ; min-height : 100 vh ; padding : 20 px ; } .Column { color : white ; } .Title { padding : 20 px ; margin-bottom : 20 px ; border-radius : 10 px ; color : black ; background-color : rgb ( 218, 255, 170 ) ; } .Content { height : calc ( 100 vh - 200 px ) ; overflow-y : scroll ; margin-bottom : 20 px ; } ::-webkit-scrollbar { display : none ; }We divided the main app wrapper into two columns separated by a gap using CSS grid layout , and set a fixed width for the left column for the story elements. We then positioned the wrapper so that it never exceeded a certain width, centered it on the screen, made it use the full height of the screen viewing area, and added a backing within it. For the contents of each column, we set the text color to white. For the column headers, we'll set the padding, add a bottom margin, and set rounded corners. We'll also set the background color of the header element to lime green and the text color to black. We'll also design the columns themselves, setting a rule that the content should not exceed a certain height, and set the content to scroll if it goes beyond the height. We also add an indentation from the bottom border. We also hide the scrollbars so we don't have to change their style to override the defaults for each browser. This rule is optional and we can choose not to follow it.
Obtaining an API key from OpenAI
If you have not already configured your own sandbox API key in the introduction to this guide, be sure to create an account on the OpenAI website. Then log in, go to the API keys section, and generate a new API key..env
file in the root of the project and insert a value for the following key as shown below:REACT_APP_OPENAI_API_KEY = paste-your-code-here
Preparing a request call to the OpenAI API
Using the OpenAI API, our chatbot will be able to send text requests to the OpenAI server, which will process them and generate human-like responses. This is accomplished by utilizing a powerful language model that has been trained on a variety of text sources. By providing the model with the conversation history and current user prompt, our chatbot will receive context-aware responses from the API. In this section, we will prepare the request and implement the API call to receive the response and set the data into the state variable we defined earlier. Open App.js.
and add the following code:// imported modules ... export default function App ( ) { // useState variables ... const handleSubmit = async ( ) => { const prompt = { role : "user" , content : input, } ; setMessages ( [ ... messages , prompt ] ) ; await fetch ( "https://api.openai.com/v1/chat/completions" , { method : "POST" , headers : { Authorization : ` Bearer ${ process . env . REACT_APP_OPENAI_API_API_KEY } ` , "Content-Type" : "application/json", } , body : JSON . stringify ( { model : "gpt-3.5-turbo" , messages : [ ... messages, prompt ], } ), } ) . then ( ( ( data ) => data . json ( ) ) . then ( data ) => { const res = data . choices [ 0 ] . message . content ; setMessages ( ( messages ) => [ ... messages , { role : "helper", content : res, }, ] ) ; setHistory ( history ) => [ ... history , { question : input, answer : res } ] ) ; setInput ( "" ) ; } ) ; } ; const clear = ( ) => { setMessages ( [ ] ) ; setHistory ( [ ] ) ; } } ; return < div className = "App" > // return elements ... ; }First, we'll create a separate
handleSubmit
function that will be executed after the user enters a query into the input form and clicks the button Send Button. Inside handleSubmit
First, we're going to create give me a hint
variable that will play the role of user
and the message itself as an object. The role is important because when storing messages we need to know which ones are user messages. Then we update messages
state variable with a user prompt. Next, we create the actual get
calling the api.openai.com/v1/chat/completions endpoint to access data from the OpenAI API. We specify that this is POST
request and set the authorization token and content type in the headers. For body
parameters, we specify which API model to use, and pass the messages
variable as content from the user. After receiving the response, we store it in the variable res
variable. We add an object consisting of a role assistant
and the very answer to message
state variable. We're also updating history
state variable with the object, s issue
and corresponding response
as keys. After receiving the response and updating the state variables, we clear the inlet
state variable to prepare the input form for the next user request. Finally, we create a simple variable clear
to clean up messages
и history
state variables, allowing the user to clear the application data.Application testing
By now we should have created a fully functional chat app! The only thing left to do is to test it. First, let's try to ask ChatGPT one question.Conclusion
In this tutorial, we learned how to create a user-friendly UI, how to structure code with components, how to work with states, how to make API calls, and how to process the resulting data. With the combination of the advanced natural language processing capabilities of the OpenIAI API and the flexibility of React, you will now be able to create complex chatbot applications that can be tweaked to your liking. Note that this guide stores the API key on the frontend, which may not be safe for production. If you want to deploy the project, it is recommended that you create an Express server and use the API key there. Also, if you want the history prompts to be available after the next run, you can store and then read them from local storage or even connect a database to your application and store and read the data from there.Frequently Asked Questions (FAQ) about creating a ChatGPT clone using React and OpenAI APIs
What is the main purpose of using React to create a ChatGPT clone?
React is a popular JavaScript library for creating user interfaces, especially for single-page applications. It is used to handle the presentation layer in web and mobile applications. React allows you to create simple views for each application state and efficiently update and display the right components when data changes. In the context of creating a ChatGPT clone, React provides a flexible and efficient way to structure the chat interface, manage state changes such as incoming and outgoing messages, and handle user interaction.
How does the OpenAI API affect the functionality of the ChatGPT clone?
The OpenAI API is the core engine that provides the conversational capabilities of the ChatGPT clone. It provides access to the GPT-3 model, a state-of-the-art machine learning model for natural language processing tasks. When you send user input to the API, it returns a generated message that mimics a human-like response. This interaction is at the heart of the chat functionality in the ChatGPT clone.
Can I customize the ChatGPT clone to my needs?
Absolutely. The beauty of creating your own ChatGPT clone is the ability to customize it to your needs. You can change the user interface, add additional features, or even integrate it with other services or APIs. The provided code serves as a starting point, and you can experiment and do things your own way.
What are the prerequisites for creating a ChatGPT clone?
To create a ChatGPT clone, you need a basic understanding of JavaScript and React. You also need a development environment with Node.js and npm (Node Package Manager). In addition, you need access to the OpenAI API, which requires an API key that can be obtained by registering on the OpenAI website.
How can I deal with OpenAI API errors or unexpected responses?
The OpenAI API may periodically return errors or unexpected responses for various reasons, such as network problems, invalid requests, or API limitations. You can handle these situations by implementing error handling logic in your code. This may include retrying the request, showing an error message to the user, or logging the error for further investigation.
How can I improve the performance of my ChatGPT clone?
There are several ways to optimize the performance of your ChatGPT clone. One is to implement efficient state management in React components to minimize unnecessary rendering. Another is to leverage the OpenAI API, for example, by limiting the frequency of requests or reducing the amount of data sent in each request.
Is it possible to deploy a ChatGPT clone on a server?
Yes, you can deploy your ChatGPT clone on a server to make it available on the Internet. To do this, you need to package the application in a format suitable for deployment, create a server environment, and configure the server to serve the application. There are many hosting providers that can simplify this process, such as Vercel, Netlify, or Heroku.
Can I use other machine learning models with the ChatGPT clone?
Although the provided code is designed to work with the OpenAI API, you can modify it to use other machine learning models if you wish. To do this, you need to replace API calls with API calls of the model you have chosen and, possibly, adjust the logic of data processing according to the new model.
How can I add more features to the ChatGPT clone?
Adding additional features to a ChatGPT clone involves writing additional code and integrating it with the existing code base. Some potential features may include support for multiple chats, user authentication, message history, or even multimedia messaging. The possibilities are limited only by your imagination and coding skills.
How do I secure the communication between the ChatGPT clone and the OpenAI API?
Securing the communication between your ChatGPT clone and the OpenAI API is very important to protect your API key and the data being transmitted. This can be achieved by using HTTPS for all requests to the API, which encrypts the data in transit. In addition, you must store your API key securely and not disclose it in client-side code.
Related Topics
More Press
Let's get in touch!
Please feel free to send us a message through the contact form.
Drop us a line at request@nosota.com / Give us a call over nosota.skype