Hello everyone,
I would like to know if it is possible to stream the content of a message sent by an assistant as part of PHP code.
On the one hand, I have a code that allows me to stream the API response in “completion” mode.
On the other, I have code that allows me to retrieve the API response in assistant mode, but without streaming it.
I’d like to stream the assistant’s response, but so far I haven’t managed to do so.
Here’s the PHP code I use to retrieve the assistant’s response, without streaming it.
<?php
// OpenAI API Key
$OPENAI_API_KEY = [my API key];
// Retrieve POST parameters
$data = json_decode(file_get_contents('php://input'), true);
$thread = isset($data['thread']) ? $data['thread'] : null;
$message = isset($data['message']) ? $data['message'] : null;
// Check the "message" parameter
if ($message === null || trim($message) === '') {
http_response_code(400);
echo json_encode(["error" => "'message' parameter is required."]);
exit();
}
// If the thread is null, create a new thread
if (is_null($thread)) {
$thread = create_new_thread($OPENAI_API_KEY);
if (!$thread) {
http_response_code(500);
echo json_encode(["error" => "Error creating the thread."]);
exit();
}
}
// Send the message to the OpenAI API
$message_id = send_message_to_thread($OPENAI_API_KEY, $thread, $message);
if (!$message_id) {
http_response_code(500);
echo json_encode(["error" => "Error sending the message."]);
exit();
}
// Execute Plato's instructions
$run_id = execute_instructions($OPENAI_API_KEY, $thread);
if (!$run_id) {
http_response_code(500);
echo json_encode(["error" => "Error executing the instructions."]);
exit();
}
// Wait for the run to complete with a minimum delay
if (!check_run_status($OPENAI_API_KEY, $thread, $run_id)) {
http_response_code(500);
echo json_encode(["error" => "The run could not be completed within the allotted time."]);
exit();
}
// Retrieve the messages from the thread
$response_message = get_assistant_message($OPENAI_API_KEY, $thread);
if (!$response_message) {
http_response_code(500);
echo json_encode(["error" => "Error retrieving the messages."]);
exit();
}
// Create the final response
$response = [
"thread" => $thread,
"message" => $response_message
];
// Send the response
echo json_encode($response);
exit();
// Function to create a new thread
function create_new_thread($api_key) {
$url = "https://api.openai.com/v1/threads";
$headers = [
"Content-Type: application/json",
"Authorization: Bearer $api_key",
"OpenAI-Beta: assistants=v2"
];
$response = make_post_request($url, $headers);
if ($response && isset($response->id)) {
return $response->id;
}
return null;
}
// Function to send a message to a thread
function send_message_to_thread($api_key, $thread, $message) {
$url = "https://api.openai.com/v1/threads/$thread/messages";
$headers = [
"Content-Type: application/json",
"Authorization: Bearer $api_key",
"OpenAI-Beta: assistants=v2"
];
$data = json_encode([
"role" => "user",
"content" => $message
]);
$response = make_post_request($url, $headers, $data);
if ($response && isset($response->id)) {
return $response->id;
}
return null;
}
// Function to execute Plato's instructions
function execute_instructions($api_key, $thread) {
$url = "https://api.openai.com/v1/threads/$thread/runs";
$headers = [
"Content-Type: application/json",
"Authorization: Bearer $api_key",
"OpenAI-Beta: assistants=v2"
];
$data = json_encode([
"assistant_id" => "asst_kqqkrfa9Ib47th4pI8T9zx15",
"instructions" => "We are in a dialogue application that allows any philosophy student to discuss with a great philosopher of the past. You must embody Plato, adopting his thoughts, expressions, memories, so that the interlocutor can truly feel like they are conversing with the character you are."
]);
$response = make_post_request($url, $headers, $data);
if ($response && isset($response->id)) {
return $response->id;
}
return null;
}
// Function to check the status of a run
function check_run_status($api_key, $thread, $run_id) {
$url = "https://api.openai.com/v1/threads/$thread/runs/$run_id";
$headers = [
"Content-Type: application/json",
"Authorization: Bearer $api_key",
"OpenAI-Beta: assistants=v2"
];
// Initial delay
$delay = 0.1; // 100 ms
// Maximum wait time (in seconds)
$timeout = 10;
$start_time = microtime(true);
while (microtime(true) - $start_time < $timeout) {
$response = make_get_request($url, $headers);
if ($response && isset($response->status) && $response->status === "completed") {
return true;
}
usleep($delay * 1000000); // Delay in microseconds
}
return false;
}
// Function to retrieve messages from the thread and find the assistant's response
function get_assistant_message($api_key, $thread) {
$url = "https://api.openai.com/v1/threads/$thread/messages";
$headers = [
"Content-Type: application/json",
"Authorization: Bearer $api_key",
"OpenAI-Beta: assistants=v2"
];
$response = make_get_request($url, $headers);
if ($response && isset($response->data)) {
// Loop through the messages in normal order (from oldest to newest)
foreach ($response->data as $message) {
if ($message->role === "assistant" && isset($message->content[0]->text->value)) {
return $message->content[0]->text->value;
}
}
}
return null;
}
// Function to make a POST request
function make_post_request($url, $headers, $data = null) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response);
}
// Function to make a GET request
function make_get_request($url, $headers) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response);
}
?>
All I have to do is pass it a JSON as a POST, structured as follows:
{
“thread":[the thread, if one already exists],
“message“:”[my prompt]”
}
Thanks for your help.