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-io

or alternatively

cd php
composer install

Alternatively, 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:

ParameterTypeDescription
$progressInfoarrayContains job_id, progress (0-100), queue_position, estimate, job_state, success
$progressData?arrayPartial results (e.g., ['text' => '...'] for LLM streaming) or null

Cancellation Flow

  1. Set a cancellation flag in your database/UI (e.g., isTaskCanceled($taskId) returns true).
  2. The worker checks this flag inside the progress callback.
  3. If canceled, cancelRequest() is called to stop processing on the server. Handing over $jobId is optional, but it is recommended to pass it explicitly.
  4. 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:

OptionTypeDefaultDescription
api_serverstringhttps://aki.ioBase URL of the API
output_binary_formatstringbase64Output format for binary data (base64 or raw)
raise_exceptionsboolfalseThrow exceptions on errors
progress_intervalfloat0.2Polling interval for progress updates (seconds)
return_tool_call_dictboolfalseReturn tool calls as array instead of JSON string

Available Methods

Instance Methods of the Aki Class

MethodDescription
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

MethodDescription
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:

KeyTypeDescription
successboolIndicates whether the request was successful
text / images / audiomixedResult data, depending on the endpoint
job_idstringJob ID for asynchronous processing
errorstringError message when success = false
error_codeintHTTP status code on errors
num_generated_tokensintNumber of generated tokens (LLM)
compute_duration / total_durationfloatExecution 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.