In this blog, we’ll walk through how to use the OpenAI Assistant API with PHP, making it easier to create a chatbot. While OpenAI provides extensive documentation for working with their API in Node.js or Python, resources for PHP developers are a bit harder to come by. To address this, I’ve created a simple PHP library, openapi.php, that allows you to interact with the OpenAI Assistant API to send messages and receive responses.

The code handles creating threads, sending user messages, and polling the OpenAI API for responses.

We start with the index.php file for our simple chatbot interface. It includes a textarea for user input and uses JavaScript (with jQuery) to send the request to the openapi.php file. Make sure to use your ASSISTANT ID which you get from openAi platform.

index.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Chatbot</title>
    <style>
        #responseText {
            white-space: pre-wrap; /* Preserve whitespace and line breaks */
        }
    </style>
</head>
<body>
    <h1>Simple Chatbot</h1>
    <div>
        <textarea id="message" rows="4" cols="50" placeholder="Type your message..."></textarea><br>
        <button id="sendBtn">Send</button>
    </div>
    <div id="response">
        <h2>Response:</h2>
        <pre id="responseText"></pre>
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        $('#sendBtn').on('click', function() {
            const message = $('#message').val();
            if ($.trim(message) === '') {
                alert('Please enter a message.');
                return;
            }

            const responseText = $('#responseText');
            responseText.text('typing...'); // Show loading message

            const startTime = performance.now(); // Start timing

            $.ajax({
                url: 'openai.php',
                type: 'POST',
                contentType: 'application/json',
                data: JSON.stringify({
                    fn: 'send',
                    aid: 'YOUR ASSISTANT API ',
                    msg: message
                }),
                success: function(data) {
                    const endTime = performance.now(); // End timing
                    const duration = endTime - startTime;

                    responseText.text(`Response: ${JSON.stringify(data, null, 2)}\nTime taken: ${duration} ms`);
                },
                error: function(xhr, status, error) {
                    const endTime = performance.now(); // End timing
                    const duration = endTime - startTime;

                    responseText.text(`Error: ${xhr.statusText}\nTime taken: ${duration} ms`);
                }
            });
        });
    </script>
</body>
</html>
PHP

When the user types a message and clicks the “Send” button, the script captures the message and sends it to the OpenAI API. While waiting for a response, a “typing…” message is displayed. Once the response is received from the API, it’s displayed on the page along with the time taken to get the reply.

If there’s an error during the process, an error message is shown instead. The response and error handling are neatly presented in the same section of the page, giving users immediate feedback.

Next is openai.php file handles all the backend processes required to interact with the OpenAI Assistant API. It manages creating threads, sending messages, and receiving responses from the API.

openai.php
<?php
// Replace with your actual API key
// const API_KEY = 'YOUR SECRET API KEY';

header('Content-Type: application/json');
header('OpenAI-Beta: assistants=v2');

try {
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (!$input || !isset($input['fn']) || $input['fn'] !== 'send'){
        throw new Exception('Invalid request');
    }

    $assistantId = $input['aid'];
    $message = $input['msg'];
    $threadId = $input['tid'] ?: createThread()['id'];
    
    createMessage($threadId, $message);
    $runId = run($assistantId, $threadId)['id'];

    $maxRetries = 10;
    $retryInterval = 1; // Reduced polling interval

    $status = 'in_progress';

    // Poll the status of the run
    for ($i = 0; $i < $maxRetries; $i++) {
        $responseRun = getRun($threadId, $runId);
        $status = getStatus($responseRun);

        if ($status === 'completed' || $status === 'failed') {
            $responseMessage = getMessage($threadId, $runId);
            $content = getContentText($responseMessage, $runId);
            echo json_encode([
                'tid' => $threadId,
                'rid' => $runId,
                'sts' => $status,
                'msg' => $content,
            ]);
            exit; // Exit early if the status is complete or failed
        }
        
        usleep($retryInterval * 1000000); // Sleep in microseconds
    }

    echo json_encode([
        'tid' => $threadId,
        'rid' => $runId,
        'sts' => $status,
        'msg' => 'Response still in progress.',
    ]);

} catch (Exception $e) {
    echo json_encode(['error' => $e->getMessage()]);
}

function doApi($method, $url, $data = []) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . API_KEY,
        'OpenAI-Beta: assistants=v2'
    ]);

    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    } elseif ($method === 'GET') {
        curl_setopt($ch, CURLOPT_HTTPGET, true);
    }

    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        error_log('Curl error: ' . curl_error($ch)); // Log errors
        curl_close($ch);
        return null;
    }
    curl_close($ch);

    return json_decode($response, true);
}

function createThread() {
    $url = 'https://api.openai.com/v1/threads';
    return doApi('POST', $url);
}

function createMessage($threadId, $message) {
    $url = 'https://api.openai.com/v1/threads/' . $threadId . '/messages';
    return doApi('POST', $url, [
        'role' => 'user',
        'content' => $message,
    ]);
}

function run($assistantId, $threadId) {
    $url = 'https://api.openai.com/v1/threads/' . $threadId . '/runs';
    return doApi('POST', $url, [
        'assistant_id' => $assistantId,
    ]);
}

function getRun($threadId, $runId) {
    $url = 'https://api.openai.com/v1/threads/' . $threadId . '/runs/' . $runId;
    return doApi('GET', $url);
}

function getMessage($threadId, $runId) {
    $url = 'https://api.openai.com/v1/threads/' . $threadId . '/messages';
    return doApi('GET', $url);
}

function getStatus($responseRun) {
    if (isset($responseRun['last_error'])) {
        return 'failed';
    }
    return $responseRun['status'];
}

function getContentText($responseMessage, $runId) {
    foreach ($responseMessage['data'] as $message) {
        if ($message['run_id'] === $runId) {
            return $message['content'][0]['text']['value'] ?? 'Content not found.';
        }
    }
    return 'Content not found.';
}
?>
PHP

In this script:

Make sure to replace the placeholder API key with your own secret API key to enable this script to work properly with OpenAI.

I hope this guide helps you out! With this setup, you can develop any complex chatbot using the OpenAI Assistant API with PHP. Whether you’re building a simple interaction or a more advanced conversational system, this approach will give you the flexibility and power to scale your chatbot’s capabilities.