yasser-elgammal / green-ai-assistant
Green Framework AI Assistant Package
Package info
github.com/YasserElgammal/green-ai-assistant
pkg:composer/yasser-elgammal/green-ai-assistant
Requires
- php: ^8.3
- symfony/http-client: ^7.4
- yasser-elgammal/green-core: ^3.0
Requires (Dev)
- phpunit/phpunit: ^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
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
- Installation
- Configuration
- Text generation
- Chat
- Image analysis
- Exception analysis
- Selecting a provider
- Supported capabilities
- Error handling
- Adding a custom provider
- Development checks
- Security
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
modelrole and all other roles touser. 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.