PHPackages                             mhrlife/phpai-kit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. mhrlife/phpai-kit

ActiveLibrary

mhrlife/phpai-kit
=================

PHP library for OpenAI communication with advanced tool function support

v0.0.8(5mo ago)9302MITPHPPHP ^8.1

Since Nov 24Pushed 5mo agoCompare

[ Source](https://github.com/mhrlife/phpai-kit)[ Packagist](https://packagist.org/packages/mhrlife/phpai-kit)[ RSS](/packages/mhrlife-phpai-kit/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (9)Versions (7)Used By (0)

PHPAi-Kit
=========

[](#phpai-kit)

A powerful PHP library for OpenAI communication with advanced tool function support, automatic JSON Schema generation, and structured output parsing.

Features
--------

[](#features)

- **Tool Functions with Attributes**: Decorate functions with `#[Tool]` to make them AI-callable
- **Automatic JSON Schema**: Automatically converts PHP classes to OpenAI-compatible JSON Schema
- **Structured Output**: Type-safe output models using OpenAI's `response_format` with JSON Schema
- **Agent Execution Loop**: Handles tool calls automatically until task completion
- **PHPDoc Support**: Enhanced type inference from PHPDoc annotations (`@var array`, etc.)
- **Type Safety**: Full PHP 8.1+ type support with PHPStan level 5
- **Works with OpenRouter**: Compatible with OpenAI API and OpenRouter

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- OpenAI API key

Installation
------------

[](#installation)

```
composer require mhrlife/phpai-kit
```

Quick Start
-----------

[](#quick-start)

### 1. Define Your Models

[](#1-define-your-models)

```
use Mhrlife\PhpaiKit\Attributes\Tool;

// Input parameter class
class WeatherParams {
    public string $location;
    public ?string $unit = 'celsius';
}

// Output model class
class WeatherReport {
    public string $location;
    public float $temperature;
    public string $description;
}
```

### 2. Create Tool Functions

[](#2-create-tool-functions)

```
#[Tool("get_weather", "Get current weather for a location")]
function getWeather(WeatherParams $params): array {
    // Your implementation
    return [
        'location' => $params->location,
        'temperature' => 22.5,
        'description' => 'Sunny',
    ];
}
```

### 3. Create and Run Agent

[](#3-create-and-run-agent)

```
use OpenAI;

$openai = OpenAI::factory()
    ->withApiKey($apiKey)
    ->make();

$agent = \Mhrlife\PhpaiKit\create_agent(
    $openai,
    tools: [getWeather(...)],
    output: WeatherReport::class
);

$report = $agent->run("What's the weather in Paris?");

echo "Temperature: {$report->temperature}°C\n";
```

Core Concepts
-------------

[](#core-concepts)

### Tool Functions

[](#tool-functions)

Tool functions are regular PHP functions decorated with the `#[Tool]` attribute:

```
#[Tool("function_name", "Description for AI")]
function myTool(InputClass $params): mixed {
    // Function must accept exactly one parameter (a class)
    // Return value can be any serializable type
}
```

**Requirements:**

- Must have exactly one parameter
- Parameter must be a class (not scalar type)
- Must have `#[Tool]` attribute with name and description

### Automatic Schema Generation

[](#automatic-schema-generation)

The library automatically converts your PHP classes to JSON Schema:

```
class SearchParams {
    public string $query;           // Required string
    public ?int $limit = 10;        // Optional int with default
    /** @var array */
    public array $filters = [];     // Array type from PHPDoc
}
```

**Supported Types:**

- Scalar types: `string`, `int`, `float`, `bool`
- Arrays with PHPDoc: `array`, `Type[]`
- Nested objects: Any class type
- Enums: String and integer-backed enums
- Union types: `string|int`
- Nullable types: `?string`, `string|null`

**Enum Support:**

The library automatically extracts enum values for OpenAI schema constraints:

```
enum Status: string {
    case PENDING = 'pending';
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';
}

class TaskParams {
    public string $title;
    public Status $status;          // Enum values are extracted as constraints
}
```

Generates schema with enum constraint:

```
{
    "type": "object",
    "properties": {
        "status": {
            "type": "string",
            "enum": ["pending", "active", "inactive"]
        }
    }
}
```

### Structured Output

[](#structured-output)

Define output models to get type-safe responses:

```
class AnalysisResult {
    public string $summary;
    public int $score;
    public array $tags;
}

$agent = create_agent(
    $openai,
    tools: $tools,
    output: AnalysisResult::class
);

$result = $agent->run("Analyze this text...");
// $result is instance of AnalysisResult
```

Advanced Usage
--------------

[](#advanced-usage)

### Using AgentBuilder

[](#using-agentbuilder)

For more control, use the fluent builder API:

```
use Mhrlife\PhpaiKit\Agent\AgentBuilder;

$agent = (new AgentBuilder($openai))
    ->withModel('gpt-4o-mini')
    ->withTools([tool1(...), tool2(...)])
    ->withOutput(OutputClass::class)
    ->build();
```

### Observability with Callbacks

[](#observability-with-callbacks)

Add callbacks for tracing, logging, and monitoring. **Important**: Callbacks must be passed to `agent->run()`, not at agent creation time.

```
use function Mhrlife\PhpaiKit\Callbacks\create_langfuse_callback;

// Create agent WITHOUT callbacks
$agent = create_agent(
    $openai,
    tools: [getWeather(...)]
);

// Pass callbacks at runtime for proper trace hierarchy
$result = $agent->run(
    "What's the weather in Paris?",
    callbacks: [create_langfuse_callback()]
);
```

**Why pass callbacks to run()?**This ensures all LLM calls and tool executions are properly nested within a single trace. Each `agent->run()` creates one trace with nested spans for generations and tool calls.

**Built-in Callbacks:**

**Langfuse Tracing** - Complete observability with OpenTelemetry:

```
use function Mhrlife\PhpaiKit\Callbacks\{
    initialize_langfuse,
    create_langfuse_callback
};

// Optional: Initialize once with credentials
initialize_langfuse(
    publicKey: 'pk-...',
    secretKey: 'sk-...'
);

// Or use environment variables:
// LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY

// Pass callback to each run
$agent->run($message, callbacks: [create_langfuse_callback()]);
```

**Custom Callbacks:**Implement the `AgentCallback` interface:

```
use Mhrlife\PhpaiKit\Callbacks\AgentCallback;

class MyCallback implements AgentCallback {
    public function onRunStart(array $context): void {
        // Called when agent starts
        // $context: ['model' => string, 'input' => mixed, 'has_output_class' => bool]
    }

    public function onRunEnd(array $context): void {
        // Called when agent completes
        // $context: ['output' => mixed, 'total_iterations' => int]
    }

    public function onGenerationStart(array $context): void {
        // Called before each LLM call
        // $context: ['iteration' => int, 'messages' => array, 'model' => string]
    }

    public function onGenerationEnd(array $context): void {
        // Called after each LLM call
        // $context: ['finish_reason' => string, 'content' => string, 'tool_calls' => array, 'usage' => object]
    }

    public function onToolCallStart(array $context): void {
        // Called before tool execution
        // $context: ['tool_name' => string, 'arguments' => array, 'tool_call_id' => string]
    }

    public function onToolCallEnd(array $context): void {
        // Called after tool execution
        // $context: ['tool_name' => string, 'arguments' => array, 'result' => mixed, 'tool_call_id' => string]
    }

    public function onError(array $context): void {
        // Called on errors
        // $context: ['error' => string, 'exception' => Throwable]
    }
}

// Use your custom callback
$agent->run($message, callbacks: [new MyCallback()]);
```

### Multiple Tools

[](#multiple-tools)

Register multiple tools to give your agent more capabilities:

```
#[Tool("search_web", "Search the web")]
function searchWeb(SearchParams $params): array { /* ... */ }

#[Tool("calculate", "Perform calculations")]
function calculate(CalcParams $params): array { /* ... */ }

$agent = create_agent(
    $openai,
    tools: [searchWeb(...), calculate(...)],
    output: ResultClass::class
);
```

### Complex Types with PHPDoc

[](#complex-types-with-phpdoc)

Use PHPDoc for advanced type definitions:

```
class AdvancedParams {
    /**
     * List of user IDs to process
     * @var array
     */
    public array $userIds;

    /**
     * Optional configuration map
     * @var array|null
     */
    public ?array $config = null;
}
```

Error Handling
--------------

[](#error-handling)

The library throws specific exceptions for different error types:

```
use Mhrlife\PhpaiKit\Exceptions\{AgentException, ToolException, SchemaException};

try {
    $result = $agent->run("Your prompt");
} catch (ToolException $e) {
    // Tool execution failed
} catch (SchemaException $e) {
    // Schema generation failed
} catch (AgentException $e) {
    // Agent runtime error
}
```

Vector Database with Filtering
------------------------------

[](#vector-database-with-filtering)

Store and search documents using vector embeddings with Redis:

```
use Mhrlife\PhpaiKit\VectorDB\{
    RedisVectorDB, Document, DocumentSearch, IndexConfig,
    Filter, FilterOp, FilterableField, FilterFieldType, NumericRange
};

// Create vector DB with filterable fields
$vectorDB = new RedisVectorDB('my_index', $embeddingClient, $redis);
$vectorDB->createIndex(new IndexConfig(
    dimensions: 1536,
    distanceMetric: 'COSINE',
    filterableFields: [
        new FilterableField('category', FilterFieldType::Tag),
        new FilterableField('year', FilterFieldType::Numeric),
    ]
));

// Store documents with metadata
$vectorDB->storeDocumentsBatch([
    new Document('go', 'Go is a fast compiled language', ['category' => 'backend', 'year' => 2009]),
    new Document('php', 'PHP is a flexible language', ['category' => 'backend', 'year' => 1995]),
]);

// Search with filters
$results = $vectorDB->searchDocuments(new DocumentSearch(
    query: 'fast programming language',
    topK: 3,
    filters: [
        new Filter('category', FilterOp::Eq, 'backend'),
    ]
));

// Range filter example
$results = $vectorDB->searchDocuments(new DocumentSearch(
    query: 'programming language',
    topK: 3,
    filters: [
        new Filter('year', FilterOp::Range, new NumericRange(2000, 2010)),
    ]
));
```

**Filter Operators:**

- `FilterOp::Eq` - Exact tag match
- `FilterOp::In` - Match any in list (array value)
- `FilterOp::Contains` - Text contains
- `FilterOp::Range` - Numeric range (use `NumericRange`)
- `FilterOp::Gte` - Greater than or equal
- `FilterOp::Lte` - Less than or equal

**Field Types:**

- `FilterFieldType::Tag` - Exact match (categories, tags)
- `FilterFieldType::Text` - Full-text search
- `FilterFieldType::Numeric` - Numeric range queries

Examples
--------

[](#examples)

See the `examples/` directory for complete working examples:

- `examples/test_without_api.php` - Test all features without API calls (recommended first)
- `examples/weather_example.php` - Full weather tool example with OpenAI API
- `examples/langfuse_tracing_example.php` - Complete example with Langfuse tracing
- `examples/vector_search_example.php` - Vector search with filtering
- `examples/image_input.php` - Image analysis with vision capabilities

Run the non-API example to see all features in action:

```
php examples/test_without_api.php
```

For Langfuse tracing:

```
export LANGFUSE_PUBLIC_KEY="pk-..."
export LANGFUSE_SECRET_KEY="sk-..."
php examples/langfuse_tracing_example.php
```

### Image Analysis with Vision

[](#image-analysis-with-vision)

The agent supports vision capabilities for image analysis. You can pass images to the agent in multiple ways:

**Example 1: Base64 Encoded Image**

```
$agent = create_agent($openai);

$base64Image = "data:image/png;base64,iVBORw0KGgoAAAANS...";

$response = $agent->run([
    ['role' => 'user', 'content' => [
        [
            'type' => 'text',
            'text' => 'Describe this image in detail.'
        ],
        [
            'type' => 'image_url',
            'image_url' => ['url' => $base64Image]
        ]
    ]],
]);

echo $response;
```

**Example 2: Image from URL**

```
$response = $agent->run([
    ['role' => 'user', 'content' => [
        [
            'type' => 'text',
            'text' => 'What is in this image?'
        ],
        [
            'type' => 'image_url',
            'image_url' => [
                'url' => 'https://example.com/image.png'
            ]
        ]
    ]],
]);

echo $response;
```

**Example 3: Local File to Base64**

```
// Load local image and convert to base64
$imagePath = '/path/to/image.png';
$imageData = file_get_contents($imagePath);
$base64Image = 'data:image/png;base64,' . base64_encode($imageData);

$response = $agent->run([
    ['role' => 'user', 'content' => [
        [
            'type' => 'text',
            'text' => 'Analyze this image.'
        ],
        [
            'type' => 'image_url',
            'image_url' => ['url' => $base64Image]
        ]
    ]],
]);

echo $response;
```

**Supported Image Formats:**

- PNG
- JPG/JPEG
- GIF
- WebP

See `examples/image_input.php` for complete working examples with all three approaches.

Architecture
------------

[](#architecture)

The library is organized into clear components:

- **Attributes**: `#[Tool]` decorator for marking functions
- **Schema**: JSON Schema generation from PHP classes
- **Tools**: Tool registration and execution
- **Agent**: Main agent with execution loop
- **Output**: Structured output parsing

Development
-----------

[](#development)

### Run Tests

[](#run-tests)

```
composer test
```

The test suite includes comprehensive unit tests for:

- **TypeMapper**: PHP to JSON Schema type conversion
- **SchemaGenerator**: Automatic schema generation from classes
- **ToolRegistry**: Tool registration and management
- **ToolDefinition**: OpenAI format conversion
- **ToolExecutor**: Tool execution and parameter handling
- **OutputParser**: Structured output parsing

All 117 tests pass successfully.

### Run Static Analysis

[](#run-static-analysis)

```
composer lint
```

### Format Code

[](#format-code)

```
composer format
```

### Check Formatting

[](#check-formatting)

```
composer format:check
```

How It Works
------------

[](#how-it-works)

1. **Registration**: Tools are registered with their metadata extracted via reflection
2. **Schema Generation**: Parameter classes are converted to JSON Schema automatically
3. **Execution Loop**:
    - Agent sends request with tool definitions
    - OpenAI responds with tool calls
    - Library executes tools and sends results back
    - Loop continues until completion
4. **Output Parsing**: Final response is parsed into typed output model

License
-------

[](#license)

MIT

Author
------

[](#author)

Mohammad Hoseinirad

Contributing
------------

[](#contributing)

Contributions are welcome! Please ensure code passes PHPStan level 5 and follows PSR-12 formatting.

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance70

Regular maintenance activity

Popularity14

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 75% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

5

Last Release

169d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c8a7fc63b3b1bb7651da64099c5b20ffc5eb091cf83eebef730102cc55a8420c?d=identicon)[Amhr](/maintainers/Amhr)

---

Top Contributors

[![mhrlife](https://avatars.githubusercontent.com/u/6649177?v=4)](https://github.com/mhrlife "mhrlife (3 commits)")[![fateme48984](https://avatars.githubusercontent.com/u/20993907?v=4)](https://github.com/fateme48984 "fateme48984 (1 commits)")

###  Code Quality

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mhrlife-phpai-kit/health.svg)

```
[![Health](https://phpackages.com/badges/mhrlife-phpai-kit/health.svg)](https://phpackages.com/packages/mhrlife-phpai-kit)
```

###  Alternatives

[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.5k311.5k5](/packages/theodo-group-llphant)[drupal/core-dev

require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.

2021.0M277](/packages/drupal-core-dev)[keepsuit/laravel-opentelemetry

OpenTelemetry integration for laravel

142347.8k](/packages/keepsuit-laravel-opentelemetry)[concrete5/core

Concrete core subtree split

19159.3k48](/packages/concrete5-core)[mage-os/module-automatic-translation

Automatic AI content translation for Mage-OS.

277.1k](/packages/mage-os-module-automatic-translation)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
