Create a ChatBot using AI, ChatGPT and PHP

Camilo Herrera
winkhosting
Published in
9 min readOct 12, 2023

--

Photo by Phillip Glickman on Unsplash

Hello, welcome to this new guide with fresh and diverse content for our elegant, friendly, and always well-dressed audience. Due to all the noise caused by AI in recent months, we decided to explore the possibility of implementing a customer support and service bot using this new tool, particularly ChatGPT created by OpenAI.

In this post, we will create a proof of concept to determine how far we can go. Below are the requirements for this project:

Requirements

  • Open an account at openai.com. By default, they will provide you with $5 USD in credit for testing. After this, I recommend preparing your credit card or your parents’ credit card… (it will be a nice surprise to discover that your child is investing their credit in the future of artificial intelligence).
  • Create an API Key from your OpenAI account.
  • Have a PHP development environment on your PC. We will use PHP 8.2, including a web server.
  • Maintain good posture while sitting in your desk chair. This is very important!

Opening our OpenAI account and creating an API Key

Go to https://openai.com and follow the steps on the portal to open your account. An additional step of authentication (by sending a text message to your phone) will be necessary. Keep this in mind.

Once you complete the account opening process, go to the option in the top menu and click on your account name in the top right corner. Then, click on the “View API Keys” option.

OpenAI API Keys option

The section with the title “API Keys” will be displayed. There, click on the “+ Create new secret key” button, assign an optional name to the new secret key, and click “Create secret key.” The new key will be displayed on the screen.

Copy the text (starting with sk-…) and save it in a secure place. You will need this key to authenticate your requests and use the OpenAI API. Finally, click the “Done” button.

Preparing our development environment and files

In our PHP development environment, we will create a directory, in this case, we’ll call it “ai-chatbot,” and inside it, we will create the following files:

  • index.html: This will be the entry point to our chat and will handle the GUI (Graphical User Interface).
  • ChatBot.php: Our class responsible for the interaction routines with the ChatGPT API.
  • requestmanager.php: This file will receive requests from index.html and return the results of the interaction with ChatGPT.
  • test-data.json: This file will contain simulated information related to the service our ChatBot will provide. It can be anything; in this case, we will use information about computer components.

The file structure would be as follows:

Our project files

We will start by creating our GUI, which will be a basic chat form with a section to view the conversation and a text box with its respective button to send messages. We will build the interface using my beloved Bulma CSS, and it will look like this:

Our chat GUI

The content of the index.html file is as follows:

index.html

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello A.I. Bot!</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
<script type="module">
window.addEventListener('load', (event) => {

document.querySelector(".sendMessage").addEventListener('click', (event) => {

event.currentTarget.classList.add('is-loading');
event.currentTarget.disabled = true;

document.querySelector(".result").parentElement.classList.add("is-hidden");
document.querySelector(".error").parentElement.classList.add("is-hidden");

let currHour = new Date();

const userMsgTemplate = `<div class="columns">
<div class="column is-one-third"></div>
<div class="column">
<div class="notification is-success">
<h6 class="subtitle is-6">${currHour.getHours() + ":" + currHour.getMinutes()}</h6>
${document.querySelector(".message").value}
</div>
</div>
</div>`


let chatBox = document.querySelector(".messageHistory");

chatBox.innerHTML += userMsgTemplate;
chatBox.scrollIntoView(false);

const payload = JSON.stringify({
"message": document.querySelector(".message").value
});

document.querySelector(".message").value = "";

fetch('requestmanager.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: payload,
}).then(response => response.json())
.then(data => {

let currHour = new Date();

data.responseMessage = data.responseMessage.replace("\n", "<br>");

let aiMsgTemplate = `<div class="columns">
<div class="column">
<div class="notification is-info">
<h6 class="subtitle is-6">${currHour.getHours() + ":" + currHour.getMinutes()}</h6>
${data.responseMessage}
</div>
</div>
<div class="column is-one-third"></div>
</div>`

chatBox.innerHTML += aiMsgTemplate;
chatBox.scrollIntoView(false);

})
.catch((error) => {
console.error('Error:', error);
}).finally(() => {
document.querySelector(".sendMessage").classList.remove('is-loading');
document.querySelector(".sendMessage").disabled = false;
});
});

});
</script>
</head>

<body>
<section class="section">
<div class="container">
<div class="columns box">
<div class="column">
<div class="columns">
<div class="column has-text-centered">
<h1 class="title">
Hello A.I. Bot!
</h1>
</div>
</div>
<div class="columns">
<div class="column">
<div class="card-content" style="height:600px;overflow:auto;flex-grow: 1;flex-shrink: 1;">
<div class="content messageHistory">


</div>
</div>
</div>
</div>


<div class="columns">
<div class="column">
<input class="input message" type="text" placeholder="Type your message">
</div>
<div class="column is-narrow">
<button class="button is-info sendMessage">
Send
</button>
</div>
</div>

</div>
</div>
<div class="columns box is-hidden">
<div class="column result"></div>
</div>
<div class="columns box is-hidden">
<div class="column notification is-danger error has-text-centered">
</div>
</div>
</div>
</section>
</body>

</html>

With JavaScript, we will create an event handler for the send button identified with the class “sendMessage.” Inside it, we will create the routine to send the message using POST through the Fetch API to our requestmanager.php file. We will await the response and use it to display the received message in the chat box identified with the class “messageHistory.”

Now, let’s create our JSON file that will simulate a custom data source to be used in case the visitor asks a question related to the products our bot sells.

The content of the file will be as follows:

test-data.json

{
"cpu": [
{
"brand": "AMD",
"model": "AMD Ryzen 5 5600X",
"price": "USD 158"
},
{
"brand": "AMD",
"model": "AMD Ryzen 9 5950X",
"price": "USD 799"
},
{
"brand": "Intel",
"model": "Core i5-12600K",
"price": "USD 179"
}
],
"memory": [
{
"brand": "Corsair",
"model": "VENGEANCE DDR5 1x32GB",
"price": "USD 159"
},
{
"brand": "G.SKILL",
"model": "Trident Z5 RGB Series DDR5 1x16GB",
"price": "USD 104"
}
]
}

We will use some CPU and RAM models for testing.

Now, let’s move on to the class responsible for interacting with the OpenAI API; this is where the fun begins.

You should look like this by now.

ChatBot.php

<?php

/**
* ChatBot Class
*/
class ChatBot
{
/**
* @var string The authorization token for the API
*/
private $authorization;

/**
* @var string The endpoint URL for the OpenAI.com API
*/
private $endpoint;

/**
* ChatBot constructor.
*/
public function __construct()
{
// This token is not real, in case you were thinking what I'm thinking...
$this->authorization = 'sk-bkd04ADr2TXXDGugb2NEWuH3BlbkFJFavL1XJbMZcFIegY5qY';
$this->endpoint = 'https://api.openai.com/v1/chat/completions';
}

/**
* Send a message to the API and return the response.
*
* @param string $message The message to send
* @return string The response message
* @throws Exception If there is an error in sending the message via cURL
*/
public function sendMessage(string $message): string
{
// Read sample data from our JSON file
$jsonSampleData = file_get_contents("test-data.json");

// Prepare data for sending
$data = [
'messages' => [
[
'role' => 'system',
'content' => 'You are a kind and helpful customer service member at a PC components store.
If the user asks how to buy, refer them to our website at https://medium.com/winkhosting.
If the user asks anything about CPUs or RAM, use exclusively the cpu or ram input in the following JSON string to suggest options:' . $jsonSampleData
],
[
'role' => 'user',
'content' => $message
],
],
'model' => 'gpt-3.5-turbo'
];

// Set headers for the API request
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->authorization,
];

// Send the request to the API using cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->endpoint);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

// Check for errors in the API response
if (curl_errno($ch)) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception('Error sending the message: ' . $error);
}

curl_close($ch);

// Parse the API response
$arrResult = json_decode($response, true);
$resultMessage = $arrResult["choices"][0]["message"]["content"];

// Return the response message
return $resultMessage;
}
}

As you can see, our class has only one method that receives a statement/question and takes care of sending the information to the corresponding endpoint on openai.com to receive a response (https://api.openai.com/v1/chat/completions).

In the configuration of our API request (the $data array), we will use the “gpt-3.5-turbo” model. This is recommended in terms of cost-effectiveness, but if you have enough funds and courage, you can use the gpt-4 model, which is the latest one with better performance and responsiveness.

To learn more about the available models, you can visit this link: https://platform.openai.com/docs/models

Also, in the same configuration, we will instruct our AI about the role (“system” role) it should play, which is to be a “kind and helpful customer service member,” and provide other instructions regarding the information it should provide when asked about components like RAM and CPU.

Important: Providing clear instructions will result in fewer errors while interacting with a visitor.

If you’re paying attention, you’ll also notice that we load the content of our dummy file into a variable called $jsonSampleData and add it to the content of the role our AI will have. This is done so that it has access to the information and can deliver responses based on the list of products within it.

System Role

[
'role' => 'system',
'content' => 'You are a kind and helpful customer service member at a PC components store.
If the user asks how to buy, refer them to our website at https://medium.com/winkhosting.
If the user asks anything about CPUs or RAM, use exclusively the cpu or ram input in the following JSON string to suggest options:' . $jsonSampleData
]

The user message will be added to the $data array associated with the “user” role like this:

User Role

[
'role' => 'user',
'content' => $message
]

Once we have our request payload ready to send, we will execute it using cURL. If everything goes well, we will receive the response from our AI in JSON format. We will transform it into an associative array (thanks to PHP’s magic), and our response will be in the $arrResult[“choices”][0][“message”][“content”] entry. Then we extract the text and return it.

With our class ready, let’s move on to the file responsible for receiving requests from our interface and returning the response to the user.

The responsibility of this file will be to receive a text string (the message) via a POST request from index.html, deliver the message to our AI, and return the response as follows:

requestmanager.php

<?php

// Include the definition of the ChatBot class to be used for our query.
require("ChatBot.php");

// Decode the parameters received from the index.html file and store them in the $paramsFetch array.
$paramsFetch = json_decode(
file_get_contents("php://input"),
true
);

$ChatBot = new ChatBot();

// Send the message to our AI.
$resMessage = $ChatBot->sendMessage($paramsFetch["message"]);

// Next, we return the response in JSON format and exit the execution.
$jsonResponse = json_encode(array("responseMessage" => $resMessage));
echo $jsonResponse;
exit;

This script includes the ChatBot class, receives the message, and calls sendMessage(). The returned response is converted to JSON and printed to be returned to index.html.

And that’s it! If everything works as it should, and there are no errors, you can start interacting with your AI:

Our bot!

Access the URL of your project in your development environment, in my case http://localhost/ai-chatbot/.

Our bot working

Write a question or message for the AI and start interacting with it.

Thank you for reaching this point, and remember that at Winkhosting.co, we are much more than just hosting!

P.S. The PHP code used for this guide was created with the help of AI. 😉

--

--