AIpi PHP 1.4 is here with fallback models and new event callbacks
1 month ago
1
Simple lightweight PHP library for interacting with common AI models, that provides universal interface.
🤖 Multimodel support. Unified API for all models.
🛰️ Fallback models — define multiple models and vendors to auto-switch on API failure.
🔧 Tools support & agentic - autoresolve tool calls with callbacks.
🚀 Extendable - easy to add your own models and tools.
⚡ No dependencies, just native PHP. cURL required.
📦 No composer required! But composer compatible.
You can choose to use the autoloader or include the full source at once.
Using the autoloader:
require_once'src/autoload.php';
Or include full source at once:
require_once'src/loadall.php';
Or using composer:
composer require skito/aipi
/* ******************** *//* Let's start with GPT *//* ******************** */$thread = newAIpi\Thread('openai-gpt-4o', 'my_openai_key');
$thread->AddMessage(newAIpi\Message('Hi, who are you?'));
$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n"; // Hello! I'm an AI language model created by OpenAI.print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
/* ************************************* *//* Now let's switch the Thread to Sonnet *//* ************************************* */$thread->ChangeModel('anthropic-claude-3-5-sonnet-latest', 'my_anthropic_key');
$thread->AddMessage(newAIpi\Message('Is that true?'));
$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n"; // I want to be direct with you. I'm Claude, an AI created by Anthropic.print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
// Debug full communication// print_r($thread->messages);
useAIpi\Thread;
useAIpi\Message;
useAIpi\Tools\FunctionCall;
/** ************************** *//** Define simple weather tool *//** ************************** */$weatherInfo = newFunctionCall(
// Name'get_weather_info',
// Description'Get weather info by city name and country code.',
// Accepted properties
[
'city' => 'string',
'countryCode' => 'string',
],
// Property attributes
[
'required' => ['city', 'countryCode'],
'descriptions' => [
'city' => 'The city name.',
'countryCode' => 'The country code.',
]
],
// Callback functionfunction($args) {
return ['weather' => 'sunny'];
}
);
// or alternatively// $weatherInfo = new FunctionCall('get_weather_info')// ->WithDescription('Get weather info by city name and country code.')// ->WithProperties(['city' => 'string', 'countryCode' => 'string'])// ...// ->WithCallback(function($args) {// return ['weather' => 'sunny'];// });/** ********************************** *//** Create a new thread with the tool *//** ********************************** */$thread = newThread('openai-gpt4o', 'my_openai_key');
$thread->AddTool($weatherInfo);
$thread->AddMessage(newMessage('You are a helpful assistant that can get weather info.', MessageRole::SYSTEM));
$thread->AddMessage(newMessage('What is the weather right now in LA?', MessageRole::USER));
$message = $thread->Run();
if ($message)
{
echo'ASSISTANT: '.$message->content."\r\n";
print_r($thread->GetUsage());
}
else
{
echo$thread->GetLastError();
}
// Debug full communication// print_r($thread->messages);
useAIpi\Thread;
useAIpi\Message;
useAIpi\Tools\FunctionCall;
/** ********************************** *//** Create a new thread with the tool *//** ********************************** */$thread = newThread('openai-gpt4o', 'my_openai_key');
// Load OpenMeto tool from the toolbox$thread->AddTool(newAIpi\Toolbox\OpenMeteo());
$thread->AddMessage(newMessage('You are a helpful assistant that can get weather info.', MessageRole::SYSTEM));
$thread->AddMessage(newMessage('What is the weather right now in LA?', MessageRole::USER));
$message = $thread->Run();
if ($message)
{
echo'ASSISTANT: '.$message->content."\r\n";
print_r($thread->GetUsage());
}
else
{
echo$thread->GetLastError();
}
// Debug full communication// print_r($thread->messages);
Depending on the model, you can work with binary data or links.
/* ************//* GPT vision *//* ************/useAIpi\Thread;
useAIpi\Message;
$thread = newThread('openai-gpt-4o', 'my_openai_key');
$thread->AddMessage(newMessage('What\'s on the photo?'));
// Send photo link$url = 'https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg';
$thread->AddMessage(newMessage($url, ['type' => MessageType::LINK]));
// or alternatively send as binary data// $src = file_get_contents($url);// $thread->AddMessage(new Message($src, ['type' => MessageType::FILE, 'media_type' => 'image/jpeg']));$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n"; // The photo features a fluffy orange tabby cat sitting ...print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
/* ***************//* Claude vision *//* ***************/useAIpi\Thread;
useAIpi\Message;
useAIpi\MessageType;
$thread = newThread('anthropic-claude-3-5-sonnet-latest', 'my_anthropic_key');
$thread->AddMessage(newMessage('What\'s on the photo?'));
// Claude work with file uploads$src = file_get_contents('https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg');
$thread->AddMessage(newMessage($src, ['type' => MessageType::FILE]));
$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n"; // This is a photo of a fluffy orange/ginger cat that appears to be covering its face...print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
/* ***************//* Gemini vision *//* ***************/useAIpi\Thread;
useAIpi\Message;
useAIpi\MessageType;
$thread = newAIpi\Thread('google-gemini-1.5-flash', 'my_google_key');
$thread->AddMessage(newMessage('What\'s on the photo?'));
// Gemini work with file uploads$src = file_get_contents('https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg');
$thread->AddMessage(newMessage($src, ['type' => MessageType::FILE]));
$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n"; // That's a fluffy ginger cat grooming itself...print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
$thread = newAIpi\Thread('openai-text-embedding-3-large', 'my_openai_key');
$thread->AddMessage(newAIpi\Message('The quick brown fox jumps over the lazy dog.'));
$message = $thread->Run();
if ($message)
{
echo$message->content."\r\n";
print_r($thread->GetUsage());
echo"\r\n\r\n";
}
elseecho$thread->GetLastError();
For more examples, please refer to the models docs and the demo folder.
Currently supported: chat/completitions, vision, image generation, audio generation, audio transcription, document vision, embeddings, moderations.
Tools are definitions of functions that can be called by the AI model. You can make your own tool definitions such as Tools/FunctionCall to be used in the thread.
Toolbox is a collection of predefined tool configurations. You can use the ones that come with this package ormake your own.
You have different options to create a new thread and message.
/***************//* Constructor *//***************/$thread = newAIpi\Thread($model, $key, [$options]);
$thread = newAIpi\Thread('openai-gpt-4o', $key, ['temperature' => 0.5, 'top_p' => 1]); // According to the model options/***********//* Running *//***********/// Returns Message object or null if error$thread->Run();
// If there are tools and the model is requesting additional input, // the thread will call the tools and continue with the iteration,// until the model is ready with the response$thread->Run($autocomplete=true);
/******************************//* Define as many as you want *//******************************/$thread->AddFallbackModel('openai-gpt-4.1', $key); // keep the same options as the primary model$thread->AddFallbackModel('anthropic-claude-sonnet-4-5', $key, ['temperature' => 0.1]); // change the temperature if fallback occurs
You can add your own models by creating a new class that extends AIpi\ModelBase and implementing the Call method.
Learn more here: Add Models
NOTE Most models are using common vendor API. If there is new generation model not yet updated in this library you can manually add it to the list with supported models inside the Models folder.
For any feedback, requests, questions or issues, please open an issue on GitHub.
For DMs dimita7atanasov