{"id":22051316,"url":"https://github.com/skito/aipi-php","last_synced_at":"2026-01-22T12:44:44.160Z","repository":{"id":264846477,"uuid":"894461737","full_name":"skito/aipi-php","owner":"skito","description":"Universal API client for common AI models","archived":false,"fork":false,"pushed_at":"2025-11-19T17:10:29.000Z","size":78,"stargazers_count":38,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-11-19T19:08:17.486Z","etag":null,"topics":["anthropic","artificial-intelligence","google-deepmind","large-language-models","openai","php","xai"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skito.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-26T11:54:31.000Z","updated_at":"2025-11-19T17:10:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"b278c6a9-f028-49e6-8568-9f003be005ea","html_url":"https://github.com/skito/aipi-php","commit_stats":null,"previous_names":["skito/aipi-php"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/skito/aipi-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skito%2Faipi-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skito%2Faipi-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skito%2Faipi-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skito%2Faipi-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skito","download_url":"https://codeload.github.com/skito/aipi-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skito%2Faipi-php/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28663099,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anthropic","artificial-intelligence","google-deepmind","large-language-models","openai","php","xai"],"created_at":"2024-11-30T15:08:36.350Z","updated_at":"2026-01-22T12:44:44.154Z","avatar_url":"https://github.com/skito.png","language":"PHP","funding_links":[],"categories":["LLMs \u0026 AI APIs","LLM Clients \u0026 Adapters"],"sub_categories":["Recommended core stack"],"readme":"# AIpi - Universal API client for common AI models\n![GitHub release (latest by date)](https://img.shields.io/badge/php-%3E%3D7.4-blue)\n![GitHub release (latest by date)](https://img.shields.io/badge/-OpenAI-16a180)\n![GitHub release (latest by date)](https://img.shields.io/badge/-Anthropic-ebdbbc)\n![GitHub release (latest by date)](https://img.shields.io/badge/-Google%20DeepMind-4286f5)\n![GitHub release (latest by date)](https://img.shields.io/badge/-xAI-050505)\n\nSimple lightweight PHP library for interacting with common AI models, that provides universal interface.\n\n🤖 Multimodel support. Unified API for all models.\u003cbr\u003e\n🛰️ Fallback models — define multiple models and vendors to auto-switch on API failure.\u003cbr\u003e\n🔧 Tools support \u0026 agentic - autoresolve tool calls with callbacks.\u003cbr\u003e\n🚀 Extendable - easy to add your own models and tools.\u003cbr\u003e\n⚡ No dependencies, just native PHP. cURL required.\u003cbr\u003e\n📦 No composer required! But composer compatible.\u003cbr\u003e\n\u003cbr\u003e\n\n**Quick links**\n- [Setup](#setup)\n- [Quick start](#quick-start)\n- [Tools and Toolbox](#tools-and-toolbox)\n- [Constructors and common options](#constructors-and-common-options)\n- [Supported models](#supported-models)\n- [Requests and support](#requests-and-support)\n\n\u003cbr\u003e\n\n## Setup\nYou can choose to use the autoloader or include the full source at once.\n\nUsing the autoloader:\n```php\nrequire_once 'src/autoload.php';\n```\nOr include full source at once:\n```php\nrequire_once 'src/loadall.php';\n```\nOr using composer:\n```bash\ncomposer require skito/aipi\n```\n\n\u003cbr\u003e\n\n## Quick start\n\n### [BASIC USAGE]\n```php\n/* ******************** */\n/* Let's start with GPT */\n/* ******************** */\n$thread = new AIpi\\Thread('openai-gpt-4o', 'my_openai_key');\n$thread-\u003eAddMessage(new AIpi\\Message('Hi, who are you?'));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\"; // Hello! I'm an AI language model created by OpenAI.\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n\n\n/* ************************************* */\n/* Now let's switch the Thread to Sonnet */\n/* ************************************* */\n$thread-\u003eChangeModel('anthropic-claude-3-5-sonnet-latest', 'my_anthropic_key');\n$thread-\u003eAddMessage(new AIpi\\Message('Is that true?'));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\"; // I want to be direct with you. I'm Claude, an AI created by Anthropic.\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n\n\n// Debug full communication\n// print_r($thread-\u003emessages);\n```\n\n**COMMUNICATION SEQUENCE**\n```\n1. [APP] (message)--\u003e [AI MODEL]\n2. [APP] \u003c--(message) [AI MODEL]\n```\n\u003cbr\u003e\n\n### [WITH TOOLS]\nUse tools for agentic behaviour.\n\n#### Custom tool example\n```php\nuse AIpi\\Thread;\nuse AIpi\\Message;\nuse AIpi\\Tools\\FunctionCall;\n\n/** ************************** */\n/** Define simple weather tool */\n/** ************************** */\n$weatherInfo = new FunctionCall(\n    // Name\n    'get_weather_info',\n    // Description\n    'Get weather info by city name and country code.',\n    // Accepted properties\n    [   \n        'city' =\u003e 'string',\n        'countryCode' =\u003e 'string',\n    ],\n    // Property attributes\n    [\n        'required' =\u003e ['city', 'countryCode'],\n        'descriptions' =\u003e [\n            'city' =\u003e 'The city name.',\n            'countryCode' =\u003e 'The country code.',\n        ]\n    ],\n    // Callback function\n    function($args) {\n        return ['weather' =\u003e 'sunny'];\n    }\n);\n\n// or alternatively\n// $weatherInfo = new FunctionCall('get_weather_info')\n//    -\u003eWithDescription('Get weather info by city name and country code.')\n//    -\u003eWithProperties(['city' =\u003e 'string', 'countryCode' =\u003e 'string'])\n//    ...\n//    -\u003eWithCallback(function($args) {\n//        return ['weather' =\u003e 'sunny'];\n//    });\n    \n\n/** ********************************** */\n/** Create a new thread with the tool */\n/** ********************************** */\n$thread = new Thread('openai-gpt4o', 'my_openai_key');\n$thread-\u003eAddTool($weatherInfo);\n$thread-\u003eAddMessage(new Message('You are a helpful assistant that can get weather info.', MessageRole::SYSTEM));\n$thread-\u003eAddMessage(new Message('What is the weather right now in LA?', MessageRole::USER));\n$message = $thread-\u003eRun();\nif ($message)\n{\n    echo 'ASSISTANT: '.$message-\u003econtent.\"\\r\\n\";\n    print_r($thread-\u003eGetUsage());\n}\nelse \n{\n    echo $thread-\u003eGetLastError();\n}\n\n\n// Debug full communication\n// print_r($thread-\u003emessages);\n```\n\n#### Toolbox example\n```php\nuse AIpi\\Thread;\nuse AIpi\\Message;\nuse AIpi\\Tools\\FunctionCall;\n\n/** ********************************** */\n/** Create a new thread with the tool */\n/** ********************************** */\n$thread = new Thread('openai-gpt4o', 'my_openai_key');\n\n// Load OpenMeto tool from the toolbox\n$thread-\u003eAddTool(new AIpi\\Toolbox\\OpenMeteo());\n\n$thread-\u003eAddMessage(new Message('You are a helpful assistant that can get weather info.', MessageRole::SYSTEM));\n$thread-\u003eAddMessage(new Message('What is the weather right now in LA?', MessageRole::USER));\n$message = $thread-\u003eRun();\nif ($message)\n{\n    echo 'ASSISTANT: '.$message-\u003econtent.\"\\r\\n\";\n    print_r($thread-\u003eGetUsage());\n}\nelse \n{\n    echo $thread-\u003eGetLastError();\n}\n\n\n// Debug full communication\n// print_r($thread-\u003emessages);\n```\n\n**COMMUNICATION SEQUENCE**\n```\n1. [APP] (message)--\u003e [AI MODEL]\n2. [APP] \u003c-----(call) [AI MODEL]\n3. [APP] (result)---\u003e [AI MODEL]\n4. [APP] \u003c--(message) [AI MODEL]\n```\n\u003cbr\u003e\n\n### [VISION]\nDepending on the model, you can work with binary data or links.\n\n#### GPT\n```php\n/* ************/\n/* GPT vision */\n/* ************/\nuse AIpi\\Thread;\nuse AIpi\\Message;\n\n$thread = new Thread('openai-gpt-4o', 'my_openai_key');\n$thread-\u003eAddMessage(new Message('What\\'s on the photo?'));\n\n// Send photo link\n$url = 'https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg';\n$thread-\u003eAddMessage(new Message($url, ['type' =\u003e MessageType::LINK]));\n\n// or alternatively send as binary data\n// $src = file_get_contents($url);\n// $thread-\u003eAddMessage(new Message($src, ['type' =\u003e MessageType::FILE, 'media_type' =\u003e 'image/jpeg']));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\"; // The photo features a fluffy orange tabby cat sitting ...\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n```\n\n#### Claude\n```php\n/* ***************/\n/* Claude vision */\n/* ***************/\nuse AIpi\\Thread;\nuse AIpi\\Message;\nuse AIpi\\MessageType;\n\n$thread = new Thread('anthropic-claude-3-5-sonnet-latest', 'my_anthropic_key');\n$thread-\u003eAddMessage(new Message('What\\'s on the photo?'));\n\n// Claude work with file uploads\n$src = file_get_contents('https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg');\n$thread-\u003eAddMessage(new Message($src, ['type' =\u003e MessageType::FILE]));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\"; // This is a photo of a fluffy orange/ginger cat that appears to be covering its face...\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n```\n\n#### Gemini\n```php\n/* ***************/\n/* Gemini vision */\n/* ***************/\nuse AIpi\\Thread;\nuse AIpi\\Message;\nuse AIpi\\MessageType;\n\n$thread = new AIpi\\Thread('google-gemini-1.5-flash', 'my_google_key');\n$thread-\u003eAddMessage(new Message('What\\'s on the photo?'));\n\n// Gemini work with file uploads\n$src = file_get_contents('https://onlinejpgtools.com/images/examples-onlinejpgtools/orange-tabby-cat.jpg');\n$thread-\u003eAddMessage(new Message($src, ['type' =\u003e MessageType::FILE]));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\"; // That's a fluffy ginger cat grooming itself...\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n```\n\u003cbr\u003e\n\n### [Embeddings]\n```php\n$thread = new AIpi\\Thread('openai-text-embedding-3-large', 'my_openai_key');\n$thread-\u003eAddMessage(new AIpi\\Message('The quick brown fox jumps over the lazy dog.'));\n\n$message = $thread-\u003eRun();\nif ($message) \n{\n    echo $message-\u003econtent.\"\\r\\n\";\n    print_r($thread-\u003eGetUsage());\n    echo \"\\r\\n\\r\\n\";\n}\nelse echo $thread-\u003eGetLastError();\n```\n\u003cbr\u003e\n\n### [MORE EXAMPLES]\nFor more examples, please refer to the models docs and the [demo](demo) folder.\u003cbr\u003e\nCurrently supported: ``chat/completitions``, ``vision``, ``image generation``, ``audio generation``, ``audio transcription``, ``document vision``, ``embeddings``, ``moderations``.\n\n\u003cbr\u003e\n\n## Tools and Toolbox\nTools 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.\n\nToolbox is a collection of predefined tool configurations. You can use the ones that come with this package ormake your own.\n\nLearn more here: [Add Tools](docs/add_tools.md)\n\n\u003cbr\u003e\n\n## Constructors and common options\nYou have different options to create a new thread and message.\n\n### Thread\n```php\n\n/***************/\n/* Constructor */\n/***************/\n$thread = new AIpi\\Thread($model, $key, [$options]);\n$thread = new AIpi\\Thread('openai-gpt-4o', $key, ['temperature' =\u003e 0.5, 'top_p' =\u003e 1]); // According to the model options\n\n\n/***********/\n/* Running */\n/***********/\n\n// Returns Message object or null if error\n$thread-\u003eRun(); \n\n// If there are tools and the model is requesting additional input, \n// the thread will call the tools and continue with the iteration,\n// until the model is ready with the response\n$thread-\u003eRun($autocomplete=true); \n\n```\n\n### Message\n```php\n/***************/\n/* Constructors */\n/***************/\n$message = new AIpi\\Message($content, [$roleOrAttributes]); // default role is user\n$message = new AIpi\\Message('Hello!', AIpi\\MessageRole::USER);\n$message = new AIpi\\Message('Hello!', ['type' =\u003e AIpi\\MessageType::TEXT]);\n$message = new AIpi\\Message('Hello!', ['role' =\u003e AIpi\\MessageRole::USER, 'type' =\u003e AIpi\\MessageType::TEXT]);\n```\n\n### Fallback models\n```php\n/******************************/\n/* Define as many as you want */\n/******************************/\n$thread-\u003eAddFallbackModel('openai-gpt-4.1', $key); // keep the same options as the primary model\n$thread-\u003eAddFallbackModel('anthropic-claude-sonnet-4-5', $key, ['temperature' =\u003e 0.1]); // change the temperature if  fallback occurs\n```\n\n### Events\n```php\n/************************************************/\n/* Callback when message is added to the thread */\n/************************************************/\n$thread-\u003eOnMessage(function($e) {            \n    $thread = $e-\u003ethread ?? null;\n    $message = $e-\u003emessage ?? null;\n    $usage = $e-\u003eusage ?? null;\n    $model = $e-\u003emodel ?? $thread-\u003eGetModel();\n\n    // Continue callback logic ...\n});\n\n\n/******************************************/\n/* Callback when model/vendor is switched */\n/******************************************/\n$thread-\u003eOnModelChange(function($e) {            \n    $thread = $e-\u003ethread ?? null;    \n    $model = $e-\u003emodel ?? $thread-\u003eGetModel();\n\n    // Continue callback logic ...\n});\n```\n\u003cbr\u003e\n\n## Supported models\nSupported models by vendors.\n\n**OpenAI** [(examples)](docs/openai.md)\n- openai-gpt-5.2-codex\n- openai-gpt-5.2-pro\n- openai-gpt-5.2-chat-latest\n- openai-gpt-5.2\n- openai-gpt-5.1-codex-max\n- openai-gpt-5.1-codex-mini\n- openai-gpt-5.1-codex\n- openai-gpt-5.1-chat-latest\n- openai-gpt-5.1\n- openai-gpt-5\n- openai-gpt-5-pro\n- openai-gpt-5-mini\n- openai-gpt-5-nano\n- openai-gpt-5-chat-latest\n- openai-gpt-4.5-preview (depricated)\n- openai-gpt-4\n- openai-gpt-4-turbo\n- openai-gpt-4-turbo-preview\n- openai-gpt-4.1\n- openai-gpt-4o\n- openai-chatgpt-4o-latest\n- openai-gpt-4o-mini\n- openai-gpt-4.1-mini\n- openai-gpt-4.1-nano\n- openai-o1\n- openai-o1-pro\n- openai-o1-mini\n- openai-o1-preview\n- openai-o3\n- openai-o3-mini\n- openai-o4-mini\n- openai-gpt-4o-mini-search-preview\n- openai-gpt-4o-search-preview\n- openai-gpt-3.5-turbo\n- openai-text-embedding-3-large\n- openai-text-embedding-3-small\n- openai-text-embedding-ada-002\n- openai-dall-e-3\n- openai-dall-e-2\n- openai-gpt-image-1\n- openai-tts-1\n- openai-tts-1-hd\n- openai-gpt-4o-mini-tts\n- openai-whisper-1\n- openai-gpt-4o-transcribe\n- openai-gpt-4o-mini-transcribe\n- openai-omni-moderation-latest\n- openai-text-moderation-latest\n- openai-text-moderation-stable\n\n**Anthropic** [(examples)](docs/anthropic.md)\n- anthropic-claude-sonnet-4-5\n- anthropic-claude-opus-4-1\n- anthropic-claude-sonnet-4-0\n- anthropic-claude-opus-4-0\n- anthropic-claude-3-7-sonnet-latest\n- anthropic-claude-3-5-sonnet-latest\n- anthropic-claude-3-5-haiku-latest\n- anthropic-claude-3-opus-latest\n\n**Google DeepMind** [(examples)](docs/google.md)\n- google-gemini-3-pro-preview\n- google-gemini-3-flash-preview\n- google-gemini-2.5-pro\n- google-gemini-2.5-flash\n- google-gemini-2.5-flash-lite\n- google-gemini-2.5-flash-lite-preview-06-17\n- google-gemini-2.5-flash-preview-05-20\n- google-gemini-2.5-flash-exp-native-audio-thinking-dialog\n- google-gemini-2.5-flash-preview-native-audio-dialog\n- google-gemini-2.5-flash-preview-tts\n- google-gemini-2.5-pro-preview-05-06\n- google-gemini-2.5-pro-preview-tts\n- google-gemini-2.0-flash\n- google-gemini-2.0-flash-preview-image-generation\n- google-gemini-2.0-flash-lite\n- google-imagen-3.0-generate-002 \n- google-veo-2.0-generate-001\n- google-text-embedding-004\n- google-gemini-1.5-pro\n- google-gemini-1.5-flash-8b \n- google-gemini-1.5-flash\n\n**xAI** [(examples)](docs/xai.md)\n- xai-grok-4-1-fast-non-reasoning-latest\n- xai-grok-4-1-fast-reasoning-latest\n- xai-grok-code-fast\n- xai-grok-4-latest\n- xai-grok-4-fast-non-reasoning-latest\n- xai-grok-4-fast-reasoning-latest\n- xai-grok-3-latest\n- xai-grok-3-fast-latest\n- xai-grok-3-mini-latest\n- xai-grok-3-mini-fast-latest\n- xai-grok-2-vision-latest\n- xai-grok-2-latest\n- xai-grok-vision-beta\n- xai-grok-beta\n- xai-embedding-beta\n\u003cbr\u003e\n\n### Add Models\nYou can add your own models by creating a new class that extends `AIpi\\ModelBase` and implementing the `Call` method.\nLearn more here: [Add Models](docs/add_models.md)\n\n**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.\n\n\u003cbr\u003e\n\n## Requests and support\nFor any feedback, requests, questions or issues, please open an issue on GitHub.\u003cbr\u003e\nFor DMs [dimita7atanasov](https://x.com/dimita7atanasov)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskito%2Faipi-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskito%2Faipi-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskito%2Faipi-php/lists"}