Build Your Own AI Chatbot with ChatGPT API

Judy@webdecoded
5 min readMar 21, 2023

--

OpenAI's recent introduction of the ChatGPT API has made it very simple to build an AI chatbot and integrate it into a website. In this article, we will build a user interface for the chat, integrate the OpenAI API, and deploy the chat so that users can have a conversation.

chatbot futuristic ui mobile mockup

If you prefer to follow a video tutorial, here’s the link:

https://www.youtube.com/watch?v=WsYABsWMFqc

OpenAI

To be able to use the API you would have to:

  1. Create an account at https://platform.openai.com/
  2. Enable billing & get API keys at https://platform.openai.com/account/api-keys

Project Setup

We initialize the project by running this in terminal:

npx create-next-app@latest ai-chatbot --js --tailwind --src-dir

We navigate to the project:

cd ai-chatbot

Configure Environment Variables

The API key that we got in the first part from OpenAI, we can store that by creating a new .env.local file in the root of the project and adding the key in it:

NEXT_PUBLIC_OPENAI_KEY=YourKeyHere

We will install axios to fetch data and run our application:

npm install axios && npm run dev

Unless the port is taken this should start the application at http://localhost:3000/

Inside index.js which is our main page, we can call the API and fetch data.

First, let’s import the axios and inside the main component create the function:

// index.js
import axios from 'axios';

....
const sendMessage = (message) => {
const url = '<https://api.openai.com/v1/chat/completions>'; // OpenAI API endpint

const headers = {
'Content-type': 'application/json',
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_OPENAI_KEY}`
}

const data = {
model: "gpt-3.5-turbo-0301", // the model that we want to use
messages: [{ "role": "user", "content": message }]
};

setIsLoading(true);

axios.post(url, data, headers).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
})
}

This function sends a POST request to the OpenAI API endpoint with a message provided by the user. The response will contain the chatbot's reply, which can be displayed to the user. We are also passing headers that contains an API key that is getting loaded from environment variables.

We can now use the sendMessage function to display the chatbot's response. We can do this by creating a new state variable to store the chat messages and updating it with the chatbot's response. We can also display the chat messages in the UI as a chat log.

import { useState, useEffect } from "react";

export default function Home() {
const [inputValue, setInputValue] = useState('');
const [chatLog, setChatLog] = useState([]);
const [isLoading, setIsLoading] = useState(false);

const sendMessage = (message) => {
const url = '<https://api.openai.com/v1/chat/completions>';

const data = {
model: "gpt-3.5-turbo-0301",
messages: [{ "role": "user", "content": message }]
};

const headers = {
'Content-type': 'application/json',
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_OPENAI_KEY}`
}

setIsLoading(true);

axios.post(url, data, headers).then((response) => {
console.log(response);
setChatLog((prevChatLog) => [...prevChatLog, { type: 'bot', message: response.data.choices[0].message.content }])
setIsLoading(false);
}).catch((error) => {
setIsLoading(false);
console.log(error);
})
}

// rest of the component
}

Finally, we can add an input field for the user to type their message and a button to send it to the chatbot.

// index.js
...
return (
<form>
<input type="text" placeholder="Type your message..." value={inputValue} onChange={(e) => setInputValue(e.target.value)}/>
<button type="submit">Send</button>
</form>
)

After adding the input field and button, we can handle the submission of messages by calling the sendMessage function with the current value of the input field. We can also display the chat log in the UI by mapping over the chatLog state variable and rendering each message as a separate chat bubble:

import { useState, useEffect } from "react";
import axios from 'axios';

export default function Home() {
const [inputValue, setInputValue] = useState('');
const [chatLog, setChatLog] = useState([]);
const [isLoading, setIsLoading] = useState(false);

const sendMessage = (message) => {
const url = '<https://api.openai.com/v1/chat/completions>';

const data = {
model: "gpt-3.5-turbo-0301",
messages: [{ "role": "user", "content": message }]
};

const headers = {
'Content-type': 'application/json',
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_OPENAI_KEY}`
}

setIsLoading(true);

axios.post(url, data, headers).then((response) => {
console.log(response);
setChatLog((prevChatLog) => [...prevChatLog, { type: 'bot', message: response.data.choices[0].message.content }])
setIsLoading(false);
}).catch((error) => {
setIsLoading(false);
console.log(error);
})
}

const handleSubmit = (event) => {
event.preventDefault();

setChatLog((prevChatLog) => [...prevChatLog, { type: 'user', message: inputValue }])

sendMessage(inputValue);

setInputValue('');
}

return (
<div>
<div>
{chatLog.map((message, index) => (
<div key={index}>{message.message}</div>
)}
</div>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Type your message..." value={inputValue} onChange={(e) => setInputValue(e.target.value)}/>
<button type="submit">Send</button>
</form>
</div>
)

}

HandleSubmit will take the user input, append it to the messages displayed on the screen, and make a call to the API to get the data. It will also reset the user input field.

Finally, we can add some styling using Tailwind utility classes and the final result would be:

import { useState, useEffect } from "react";
import axios from 'axios';

export default function Home() {
const [inputValue, setInputValue] = useState('');
const [chatLog, setChatLog] = useState([]);
const [isLoading, setIsLoading] = useState(false);

const handleSubmit = (event) => {
event.preventDefault();

setChatLog((prevChatLog) => [...prevChatLog, { type: 'user', message: inputValue }])

sendMessage(inputValue);

setInputValue('');
}

const sendMessage = (message) => {
const url = '<https://api.openai.com/v1/chat/completions>';

const data = {
model: "gpt-3.5-turbo-0301",
messages: [{ "role": "user", "content": message }]
};

const headers = {
'Content-type': 'application/json',
'Authorization': `Bearer ${process.env.NEXT_PUBLIC_OPENAI_KEY}`
}

setIsLoading(true);

axios.post(url, data, headers).then((response) => {
console.log(response);
setChatLog((prevChatLog) => [...prevChatLog, { type: 'bot', message: response.data.choices[0].message.content }])
setIsLoading(false);
}).catch((error) => {
setIsLoading(false);
console.log(error);
})
}

return (
<div className="container mx-auto max-w-[700px]">
<div className="flex flex-col h-screen bg-gray-900">
<h1 className="bg-gradient-to-r from-blue-500 to-purple-500 text-transparent bg-clip-text text-center py-3 font-bold text-6xl">ChatGPT</h1>
<div className="flex-grow p-6">
<div className="flex flex-col space-y-4">
{
chatLog.map((message, index) => (
<div key={index} className={`flex ${
message.type === 'user' ? 'justify-end' : 'justify-start'
}`}>
<div className={`${
message.type === 'user' ? 'bg-purple-500' : 'bg-gray-800'
} rounded-lg p-4 text-white max-w-sm`}>
{message.message}
</div>
</div>
))
}
</div>
</div>
<form onSubmit={handleSubmit} className="flex-none p-6">
<div className="flex rounded-lg border border-gray-700 bg-gray-800">
<input type="text" className="flex-grow px-4 py-2 bg-transparent text-white focus:outline-none" placeholder="Type your message..." value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
<button type="submit" className="bg-purple-500 rounded-lg px-4 py-2 text-white font-semibold focus:outline-none hover:bg-purple-600 transition-colors duration-300">Send</button>
</div>
</form>
</div>
</div>
)
}

We now have a fully functional chatbot! Users can type messages, the chatbot will generate a response, and the conversation will be displayed in the UI as a chat log. However, there is always room for improvement. For example, we could add more features to the UI such as the ability to display images or video, text-to-speech and etc. Additionally, we could integrate the chatbot with other services such as a CRM system or a payment gateway. The possibilities are endless!

--

--