PHP
AKI.IO PHP Interface | AKI.IO Docs
AKI.IO provides an official PHP client library that wraps all available AKI.IO models and streaming functionality in an easy-to-use yet powerful PHP interface.
Installation via Composer
Install the aki-io PHP package via Composer with the following command:
composer require aki-io/aki-ioor alternatively
cd php
composer installAlternatively, the library can be included manually:
require_once 'path/to/src/Aki.php';
require_once 'path/to/src/functions.php';The package requires PHP 8.2 or higher and the extensions ext-curl and ext-json.
Simple LLM Chat Example
This is the simplest way to call the AKI.IO API. Pass input parameters as an array, call the API, and receive the results. The example below shows a chat request with instruct-chat context to the LLama3 8b Chat endpoint.
<?php
use AkiIO\Aki;
$aki = new Aki('llama3_8b_chat', 'your-api-key');
$result = $aki->doApiRequest([
'chat_context' => [
['role' => 'user', 'content' => 'Tell me a joke']
],
'max_gen_tokens' => 200,
]);
if ($result['success']) {
echo $result['text'];
}LLM Streaming Chat Example with Callbacks
To use the streaming functionality, the aki-io PHP package provides a callback mechanism. The $progressCallback(...) function is invoked whenever new chat output chunks are received. The main call doApiRequest(...) blocks until all data has been received and the function returns with the final result. This is a simple way to provide progress updates to the user without requiring a PHP async framework.
<?php
use AkiIO\Aki;
$aki = new Aki('llama3_8b_chat', 'your-api-key');
$outputPosition = 0;
$progressCallback = function ($progressInfo, $progressData) use (&$outputPosition) {
if ($progressData && isset($progressData['text'])) {
echo substr($progressData['text'], $outputPosition);
$outputPosition = strlen($progressData['text']);
}
};
$result = $aki->doApiRequest([
'chat_context' => [
['role' => 'user', 'content' => 'Write a short story']
],
], $progressCallback);Asynchronous Processing & Background Jobs
PHP executes synchronously by default. For long-running tasks (e.g., high-resolution image generation or long LLM contexts), blocking the web request is not recommended. Instead, dispatch the job to a background worker or CLI script. The aki-io client works identically in CLI environments. Below is an example of decoupling the submission from the processing.
1. Web Controller (Dispatch Job)
In your web application, store the task parameters and trigger a background process. Do not wait for the result here.
<?php
// web/index.php
use AkiIO\Aki;
// Store task in database...
$taskId = saveTaskToDB(['prompt' => 'Complex image...', 'status' => 'pending']);
// Trigger background worker (non-blocking)
exec("php worker.php {$taskId} > /dev/null &");
// Return immediate response to user
echo json_encode(['status' => 'processing', 'task_id' => $taskId]);CLI Worker (Process Job)
Run this script via CLI or a queue worker (e.g., Laravel Queue, Symfony Messenger). It handles the blocking API call without affecting web server timeouts.
Variant 1: Simple Blocking Worker
Use doApiRequest() for straightforward background processing. The worker blocks until the result is ready.
<?php
// worker.php
use AkiIO\Aki;
require_once 'vendor/autoload.php';
$taskId = $argv[1];
$task = getTaskFromDB($taskId);
$aki = new Aki('z_image_turbo', getenv('AKI_API_KEY'));
$result = $aki->doApiRequest([
'prompt' => $task['prompt'],
'width' => 1024,
'height' => 1024,
]);
if ($result['success']) {
saveResult($taskId, $result['images']);
updateTaskStatus($taskId, 'completed');
} else {
updateTaskStatus($taskId, 'failed', $result['error']);
}Variant 2: Worker with Progress Tracking & Cancellation
Use doApiRequestAwait() with a progress callback to enable real-time progress updates and optional cancellation. This variant requires the worker to stay active during processing.
<?php
// worker_with_progress.php
use AkiIO\Aki;
require_once 'vendor/autoload.php';
$taskId = $argv[1];
$task = getTaskFromDB($taskId);
$aki = new Aki('z_image_turbo', getenv('AKI_API_KEY'));
$result = $aki->doApiRequestAwait([
'prompt' => $task['prompt'],
'width' => 1024,
'height' => 1024,
], function ($progressInfo, $progressData) use ($taskId, $aki) {
// Update progress in your database/UI
updateTaskProgress($taskId, $progressInfo['progress']);
// Optional: Support external cancellation (e.g., via DB flag)
if (isTaskCanceled($taskId)) {
$aki->cancelRequest($progressInfo['job_id']);
}
});
if ($result['success']) {
saveResult($taskId, $result['images']);
updateTaskStatus($taskId, 'completed');
} else {
updateTaskStatus($taskId, 'failed', $result['error']);
}Progress Callback Parameters
The callback function receives two arguments:
| Parameter | Type | Description |
|---|---|---|
| $progressInfo | array | Contains job_id, progress (0-100), queue_position, estimate, job_state, success |
| $progressData | ?array | Partial results (e.g., ['text' => '...'] for LLM streaming) or null |
Cancellation Flow
- Set a cancellation flag in your database/UI (e.g., isTaskCanceled($taskId) returns true).
- The worker checks this flag inside the progress callback.
- If canceled, cancelRequest() is called to stop processing on the server. Handing over $jobId is optional, but it is recommended to pass it explicitly.
- The API returns a result with success = false and an appropriate error message.
Web Dispatcher (unchanged)
Both worker variants are triggered the same way from your web layer:
<?php
// web/index.php
$taskId = saveTaskToDB(['prompt' => 'Complex image...', 'status' => 'pending']);
// Trigger worker (choose variant: worker.php or worker_with_progress.php)
exec("php worker_with_progress.php {$taskId} > /dev/null &");
echo json_encode(['status' => 'processing', 'task_id' => $taskId]);3. Checking Job Status
If the API returns a job_id, you can store it to manage the task lifecycle (e.g., cancellation) even if the processing happens elsewhere.
<?php
use AkiIO\Aki;
$aki = new Aki('llama3_8b_chat', 'your-api-key');
// Example: Cancel a long-running job by ID
$aki->cancelRequest($storedJobId);⚠️ Timeouts: When running in a web context, ensure your PHP max_execution_time is sufficient or use the background job pattern above to avoid gateway timeouts.
Image Generation
The same patterns can be used for all AKI.IO endpoints. Here is an example for image generation:
<?php
use AkiIO\Aki;
$aki = new Aki('z_image_turbo', 'your-api-key');
$result = $aki->doApiRequest([
'prompt' => 'A cute robot on a beach',
'width' => 512,
'height' => 512,
]);
foreach ($result['images'] ?? [] as $idx => $imageData) {
$decoded = Aki::decodeBinary($imageData);
file_put_contents("image_{$idx}.png", $decoded[1]);
}Configuration Options
When creating a new Aki instance, the following options can be passed:
| Option | Type | Default | Description |
|---|---|---|---|
| api_server | string | https://aki.io | Base URL of the API |
| output_binary_format | string | base64 | Output format for binary data (base64 or raw) |
| raise_exceptions | bool | false | Throw exceptions on errors |
| progress_interval | float | 0.2 | Polling interval for progress updates (seconds) |
| return_tool_call_dict | bool | false | Return tool calls as array instead of JSON string |
Available Methods
Instance Methods of the Aki Class
| Method | Description |
|---|---|
| doApiRequest($params, $progressCallback = null) | Executes a synchronous API request with optional progress callback |
| doApiRequestAsync($params, $progressCallback) | Async request returning a Generator (requires symfony/http-client) |
| doApiRequestAwait($params, $progressCallback) | Blocking wrapper around async — returns final result (requires symfony/http-client) |
| initApiKey($apiKey = null) | Initializes and validates the API key |
| getEndpointList($apiKey = null) | Retrieves the list of available endpoints |
| getEndpointDetails($name, $apiKey = null) | Retrieves details for a specific endpoint |
| cancelRequest($jobId = null) | Cancels a running request |
| appendProgressInputParams($jobId, $params) | Appends parameters for progress updates |
| setApiKey($apiKey) | Sets a new API key |
Static Helper Methods
| Method | Description |
|---|---|
| encodeBinary($binaryData, $mediaFormat, $mediaType = null) | Encodes binary data to Base64 with MIME header |
| decodeBinary($base64Data) | Decodes Base64 to binary data [format, data] |
| checkIfValidBase64String($string) | Checks if a string is valid Base64 |
| checkIfValidJsonString($string) | Checks if a string is valid JSON |
| getVersion() | Returns the client version |
| detectMediaTypeFromFormat($mediaFormat) | Detects media type from format |
Return Values
All API calls return an associative array with the following keys:
| Key | Type | Description |
|---|---|---|
| success | bool | Indicates whether the request was successful |
| text / images / audio | mixed | Result data, depending on the endpoint |
| job_id | string | Job ID for asynchronous processing |
| error | string | Error message when success = false |
| error_code | int | HTTP status code on errors |
| num_generated_tokens | int | Number of generated tokens (LLM) |
| compute_duration / total_duration | float | Execution time in seconds |
Progress Callback Signature
The optional progress callback receives two parameters:
function (array $progressInfo, ?array $progressData): void$progressInfo contains:
- job_id: The job ID of the request
- progress: Progress percentage (0-100)
- queue_position: Position in the queue (-1 if not queued)
- estimate: Estimated remaining time in seconds (-1 if unknown)
- job_state: Current status (queued, running, done, canceled, lapsed)
- success: Bool indicating if the current status is successful
$progressData contains:
- Partially generated results (e.g., text for LLM streaming)
- null if no partial data is available yet
Running Tests
cd php
composer install
# Run all tests (requires valid API key)
AKI_API_KEY=your-key php tests/TestRunner.php⚠️ Note: doApiRequestAsync() and doApiRequestAwait() require the symfony/http-client package. Install it with: ▎ composer require symfony/http-client
Examples
Complete examples can be found in the examples/ directory of the repository:
- llm_simple_example.php – Basic LLM request
- llm_stream_example.php – LLM with streaming callback
- llm_async_example.php
- image_generation_example.php – Image generation
Important Notes
⚠️ API Key Security: Always keep your API key secret. Never expose it in publicly accessible client-side code. The PHP client interface is designed for server/backend usage.
⚠️ Binary Data: For endpoints that return binary data (images, audio), data is returned by default as Base64-encoded strings with MIME header. Use Aki::decodeBinary() to convert these to raw data.
The examples above demonstrate the available patterns for using the aki-io PHP library. Use the pattern that best fits your use case.
The same patterns can be used for all types of AKI.IO endpoints – only the input parameters to send and the returned progress-data and output-data vary depending on the endpoint type.
The expected input parameters are described in detail for LLMs here and for image generators here. Additional endpoint types will be available soon.