Search by

yasser-elgammal / green-ai-assistant

YasserElgammal

Green Framework AI Assistant Package

Package info

github.com/YasserElgammal/green-ai-assistant

pkg:composer/yasser-elgammal/green-ai-assistant

Fund package maintenance!

YasserElgammal

Buy Me A Coffee

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-10-14 21:01 UTC

This package is not auto-updated.

Last update: 2026-10-15 19:26:16 UTC


README

AI provider abstraction for the Green Framework. The package ships with Google Gemini, OpenAI, and xAI Grok providers for text generation, multi-turn chat, image analysis, and exception analysis.

Guides

Requirements

  • PHP 8.3 or newer
  • Green Framework / yasser-elgammal/green-core
  • An API key for the provider you want to use: Gemini, OpenAI, or xAI

Installation

Once the package is published on Packagist, install it with Composer:

composer require yasser-elgammal/green-ai-assistant

Configuration

Register AiServiceProvider using the service-provider mechanism of your Green Framework application:

use YasserElgammal\Green\Ai\AiServiceProvider;

// Add AiServiceProvider::class to your application's providers.

Create config/ai.php in the Green v3 application. Green loads it into its read-only configuration repository during bootstrap. Keep API keys in the environment rather than committing them:

<?php

use YasserElgammal\Green\Ai\Providers\Gemini\GeminiProvider;
use YasserElgammal\Green\Ai\Providers\GrokAI\GrokAiProvider;
use YasserElgammal\Green\Ai\Providers\OpenAI\OpenAiProvider;

return [
    'default' => 'gemini',
    'providers' => [
        'gemini' => [
            'driver' => GeminiProvider::class,
            'api_key' => getenv('GEMINI_API_KEY'),
            'model' => 'gemini-1.5-flash',
            'exception_model' => 'gemini-1.5-flash',
            'http' => [
                'timeout' => 30,
                'max_retries' => 3,
                'retry_delay_ms' => 1000,
            ],
        ],
        'openai' => [
            'driver' => OpenAiProvider::class,
            'api_key' => getenv('OPENAI_API_KEY'),
            'model' => 'gpt-4o-mini',
            'exception_model' => 'gpt-4o-mini',
            'http' => [
                'timeout' => 30,
                'max_retries' => 3,
                'retry_delay_ms' => 1000,
            ],
        ],
        'grok' => [
            'driver' => GrokAiProvider::class,
            'api_key' => getenv('XAI_API_KEY'),
            'model' => 'grok-4.7',
            'exception_model' => 'grok-4.7',
            'http' => [
                'timeout' => 30,
                'max_retries' => 3,
                'retry_delay_ms' => 1000,
            ],
        ],
    ],
];
GEMINI_API_KEY=your-api-key
OPENAI_API_KEY=your-api-key
XAI_API_KEY=your-api-key

If your application is not using the framework container, instantiate the manager directly:

use YasserElgammal\Green\Ai\Managers\AiManager;
use YasserElgammal\Green\Ai\Providers\Gemini\GeminiProvider;

$ai = new AiManager([
    'default' => 'gemini',
    'providers' => [
        'gemini' => [
            'driver' => GeminiProvider::class,
            'api_key' => getenv('GEMINI_API_KEY'),
            'model' => 'gemini-1.5-flash',
        ],
    ],
]);

All examples below assume $ai is an AiManagerInterface. In a Green application, resolve it from the container:

use YasserElgammal\Green\Ai\Contracts\AiManagerInterface;

$ai = $app->make(AiManagerInterface::class);

Text generation

$result = $ai->text()->generate(
    'Explain dependency injection in three short sentences.',
    [
        'temperature' => 0.3,
        'model' => 'gemini-1.5-flash', // Optional per-request override.
    ]
);

echo $result->getText();

Read response metadata and token usage:

$usage = $result->getUsage();

echo $result->getFinishReason() ?? 'unknown';
echo $usage->getPromptTokens();
echo $usage->getCompletionTokens();
echo $usage->getTotalTokens();

$rawProviderResponse = $result->getMetadata();

Chat

use YasserElgammal\Green\Ai\DTOs\Message;
use YasserElgammal\Green\Ai\DTOs\Role;

$messages = [
    new Message(Role::USER, 'My application processes invoices.'),
    new Message(Role::ASSISTANT, 'How can I help with the invoice workflow?'),
    new Message(Role::USER, 'Suggest three useful automation ideas.'),
];

$result = $ai->chat()->send($messages, [
    'model' => 'gemini-1.5-flash',
]);

echo $result->getText();

Messages can also be serialized:

$payload = array_map(
    static fn (Message $message): array => $message->toArray(),
    $messages
);

The current Gemini adapter maps assistant messages to Gemini's model role and all other roles to user. Dedicated system-instruction mapping is not currently implemented.

Exception analysis

The analyzer returns a root cause, human-readable explanation, recommended fix, and confidence score:

try {
    throw new RuntimeException('Unable to connect to the cache server.');
} catch (Throwable $exception) {
    $analysis = $ai->exceptions()->analyze($exception, [
        'environment' => 'production',
        'component' => 'cache',
    ]);

    echo $analysis->getRootCause();
    echo $analysis->getHumanExplanation();
    echo $analysis->getRecommendedFix();
    echo $analysis->getConfidenceScore();
}

Supply an alternative, sanitized trace through the context array:

$analysis = $ai->exceptions()->analyze($exception, [
    'trace' => $sanitizedTrace,
    'request_id' => $requestId,
]);

Exception messages, file paths, traces, and additional context are sent to the configured AI provider. Remove secrets and personal data first.

Image analysis

Analyze a local image, a public image URL, or a base64 data URL:

$result = $ai->image()->analyzeImage(
    '/path/to/image.jpg',
    'Describe this image and list the visible objects.',
    ['detail' => 'high'] // Used by OpenAI and Grok.
);

echo $result->getText();

Local images are encoded as base64. Gemini also downloads URL inputs and sends them inline. Inline images are limited to 20 MiB; larger Gemini inputs should use its Files API, which is not currently wrapped by this package.

Selecting a provider

$defaultProvider = $ai->provider();
$gemini = $ai->provider('gemini');

echo $gemini->getName(); // gemini

Check a capability before using a provider directly:

use YasserElgammal\Green\Ai\Contracts\Capabilities\TextGeneratorInterface;

if ($gemini->hasCapability(TextGeneratorInterface::class)) {
    $result = $gemini->generate('Write a concise release note.');
}

Supported capabilities

Capability Manager method Gemini OpenAI Grok
Text generation $ai->text() Supported Supported Supported
Chat $ai->chat() Supported Supported Supported
Exception analysis $ai->exceptions() Supported Supported Supported
Image analysis $ai->image() Supported Supported Supported
JSON generation $ai->json() Not implemented Not implemented Not implemented
Streaming $ai->stream() Not implemented Not implemented Not implemented

Calling an unsupported capability throws CapabilityNotSupportedException.

Error handling

All package-specific exceptions extend AiException:

use YasserElgammal\Green\Ai\Exceptions\AiException;
use YasserElgammal\Green\Ai\Exceptions\CapabilityNotSupportedException;
use YasserElgammal\Green\Ai\Exceptions\ProviderException;

try {
    $result = $ai->text()->generate('Hello');
} catch (CapabilityNotSupportedException $exception) {
    // The provider does not implement the requested capability.
} catch (ProviderException $exception) {
    // Missing credentials, provider errors, invalid responses, or HTTP failures.
} catch (AiException $exception) {
    // Invalid provider configuration or another package-level error.
}

The HTTP client retries transport failures, server errors, and HTTP 429 responses. Other 4xx errors fail immediately. Configure retry behavior under the provider's http key.

Adding a custom provider

A provider must implement ProviderInterface and the capability interfaces it supports. Extending AbstractProvider supplies configuration storage and capability detection:

use YasserElgammal\Green\Ai\Contracts\Capabilities\TextGeneratorInterface;
use YasserElgammal\Green\Ai\DTOs\GenerationResult;
use YasserElgammal\Green\Ai\DTOs\UsageStats;
use YasserElgammal\Green\Ai\Providers\AbstractProvider;

final class ExampleProvider extends AbstractProvider implements TextGeneratorInterface
{
    public function getName(): string
    {
        return 'example';
    }

    public function generate(string $prompt, array $options = []): GenerationResult
    {
        // Call the provider API here.
        return new GenerationResult(
            text: 'Generated response',
            usage: new UsageStats()
        );
    }
}

Register it in the configuration:

'default' => 'example',
'providers' => [
    'example' => [
        'driver' => ExampleProvider::class,
        'api_key' => getenv('EXAMPLE_API_KEY'),
    ],
],

Provider instances are created lazily and cached by AiManager for the manager's lifetime.

Development checks

composer validate --strict

# PowerShell
Get-ChildItem src -Recurse -Filter *.php | ForEach-Object { php -l $_.FullName }

Run the automated unit and Green v3 integration tests with:

composer test

The Gemini tests use a fake HTTP client and do not consume API quota. They validate request payloads and response mapping; a live API smoke test still requires a real Gemini key.

Security

  • Never commit provider API keys.
  • Sanitize exception traces and context before sending them to an external service.
  • Avoid logging request URLs because the current Gemini URL contains the API key.
  • Review the selected provider's data-handling and retention policies before sending sensitive content.

License

This package is open-sourced software licensed under the MIT License.