m-tech-stack / laravel-ai-engine
A comprehensive Laravel package for multi-AI engine integration with credit management, streaming, interactive chat components, and advanced features
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- illuminate/cache: ^10.0|^11.0
- illuminate/http: ^10.0|^11.0
- illuminate/queue: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- openai-php/client: ^0.8
- symfony/http-client: ^6.0|^7.0
Requires (Dev)
- mockery/mockery: ^1.4
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2025-08-18 01:45:21 UTC
README
A comprehensive Laravel package for multi-AI engine integration with advanced job queue processing, intelligent rate limiting, credit management, streaming, analytics, and enterprise-grade features.
Features
🚀 Core AI Integration
- Multi-Engine Support: OpenAI, Anthropic, Gemini, Stable Diffusion, ElevenLabs, FAL AI, and more
- Streaming Responses: Real-time AI output streaming with SSE support
- Content Types: Text generation, image creation, video generation, audio processing
- Templates: Reusable prompt templates with variable substitution
âš¡ Advanced Job Queue System
- Background Processing: Queue AI requests for asynchronous processing
- Batch Operations: Process multiple AI requests efficiently in batches
- Long-Running Tasks: Handle expensive operations (video generation, large batches) with progress tracking
- Webhook Notifications: Reliable webhook delivery with retry mechanisms
- Job Status Tracking: Real-time job progress monitoring and status updates
🎯 Intelligent Rate Limiting
- Queue-Based Rate Limiting: Smart rate limiting integrated with job queue system
- User-Specific Limits: Per-user rate limiting for multi-tenant applications
- Automatic Job Delays: Rate-limited jobs are automatically delayed and retried
- Batch Intelligence: Intelligent splitting of batch requests when rate limited
- Configurable Delays: Exponential backoff with jitter to prevent thundering herd
🧠Conversation Memory
- Persistent Conversations: Store and manage conversation history across sessions
- Context-Aware Responses: AI responses that remember previous conversation context
- Message Management: User and assistant message tracking with metadata
- Conversation Settings: Configurable conversation parameters (max messages, temperature, etc.)
- Auto-Title Generation: Automatic conversation title generation from first user message
- Message Trimming: Automatic conversation history trimming to stay within limits
💰 Enterprise Features
- Credit System: Built-in usage tracking and billing management
- Interactive Actions: Buttons, forms, quick replies, and other interactive elements in AI responses
- Automatic Failover: Circuit breaker pattern with automatic provider switching for reliability
- WebSocket Streaming: Real-time AI response streaming with WebSocket support
- Advanced Analytics: Comprehensive usage monitoring, cost tracking, and performance analytics
- Memory Storage: Multiple storage drivers (Redis, Database, File, MongoDB) for conversation persistence
- Event System: Real-time events and listeners for streaming, failover, and analytics
- Console Commands: Management commands for monitoring, health checks, and system administration
- Retry & Fallback: Automatic retry mechanisms with fallback engines
- Caching: Response caching to reduce costs and improve performance
- Error Handling: Robust error handling and logging
- Laravel Integration: Seamless Laravel integration with Artisan commands
Installation
composer require m-tech-stack/laravel-ai-engine
Publish the configuration file:
php artisan vendor:publish --tag=ai-engine-config
Run the migrations:
php artisan migrate
Configuration
Add your AI service API keys to your .env
file:
# OpenAI OPENAI_API_KEY=your_openai_api_key OPENAI_ORGANIZATION=your_org_id # Anthropic ANTHROPIC_API_KEY=your_anthropic_api_key # Gemini GEMINI_API_KEY=your_gemini_api_key # Stability AI STABILITY_API_KEY=your_stability_api_key # Default engine AI_ENGINE_DEFAULT=openai # Credit system AI_CREDITS_ENABLED=true AI_DEFAULT_CREDITS=100.0 # Caching AI_CACHE_ENABLED=true AI_CACHE_TTL=3600 # Rate limiting AI_RATE_LIMITING_ENABLED=true AI_RATE_LIMITING_APPLY_TO_JOBS=true
Quick Start
Unified Engine Facade (Bupple-Style API)
The unified Engine
facade provides a simple, elegant API inspired by Bupple's Laravel AI Engine:
use LaravelAIEngine\Facades\Engine; // Simple chat completion $response = Engine::send([ ['role' => 'user', 'content' => 'Hello, how are you?'] ]); echo $response->content; // "Hello! I'm doing well, thank you for asking..." // Stream responses in real-time $stream = Engine::stream([ ['role' => 'user', 'content' => 'Tell me a story about Laravel'] ]); foreach ($stream as $chunk) { echo $chunk; // Output each chunk as it arrives }
Fluent Engine Configuration
// Configure engine, model, and parameters with method chaining $response = Engine::engine('openai') ->model('gpt-4o') ->temperature(0.8) ->maxTokens(1000) ->user('user-123') ->send([ ['role' => 'system', 'content' => 'You are a helpful assistant'], ['role' => 'user', 'content' => 'Explain quantum computing'] ]); // Stream with configuration $stream = Engine::engine('anthropic') ->model('claude-3-5-sonnet-20240620') ->temperature(0.7) ->stream([ ['role' => 'user', 'content' => 'Write a poem about AI'] ]);
Memory Management (Bupple-Style)
// Add messages to conversation memory Engine::memory() ->conversation('conv-123') ->addUserMessage('Hello!') ->addAssistantMessage('Hi there! How can I help you?'); // Get conversation context $messages = Engine::memory() ->conversation('conv-123') ->getMessages(); // Set parent context like Bupple Engine::memory() ->conversation('conv-123') ->setParent('conversation', 'parent-conv-456'); // Send with automatic conversation context $response = Engine::conversation('conv-123') ->send([ ['role' => 'user', 'content' => 'What did we discuss earlier?'] ]);
Multiple Memory Storage Drivers
// Use Redis for high-performance storage Engine::memory('redis') ->conversation('conv-123') ->addUserMessage('Hello from Redis!'); // Use file storage for simple persistence Engine::memory('file') ->conversation('conv-456') ->addUserMessage('Hello from file storage!'); // Use database storage (default) Engine::memory('database') ->conversation('conv-789') ->addUserMessage('Hello from database!');
Advanced Memory Operations
// Create conversation with metadata Engine::memory() ->createConversation('conv-123', [ 'title' => 'Customer Support Chat', 'user_id' => 'user-456', 'metadata' => ['department' => 'support'] ]); // Get conversation statistics $stats = Engine::memory() ->conversation('conv-123') ->getStats(); // Clear conversation history Engine::memory() ->conversation('conv-123') ->clear(); // Check if conversation exists $exists = Engine::memory() ->conversation('conv-123') ->exists();
Interactive Actions
Add interactive buttons, forms, and other UI elements to AI responses:
use LaravelAIEngine\Facades\Engine; use LaravelAIEngine\DTOs\InteractiveAction; // Create interactive buttons $actions = [ InteractiveAction::button('approve', 'Approve Request', [ 'action' => ['type' => 'callback', 'callback' => 'handleApproval'] ]), InteractiveAction::button('reject', 'Reject Request', [ 'action' => ['type' => 'callback', 'callback' => 'handleRejection'] ], 'Reject this request', ['variant' => 'danger']) ]; // Send response with actions $response = Engine::send([ ['role' => 'user', 'content' => 'Please review this request'] ]); $responseWithActions = $response->withActions($actions); // Create quick reply actions $quickReplies = [ InteractiveAction::quickReply('yes', 'Yes', 'Yes, I agree'), InteractiveAction::quickReply('no', 'No', 'No, I disagree'), InteractiveAction::quickReply('maybe', 'Maybe', 'I need more information') ]; // Create form action $formAction = InteractiveAction::form('feedback', 'Submit Feedback', [ ['name' => 'rating', 'type' => 'select', 'label' => 'Rating', 'options' => [1,2,3,4,5]], ['name' => 'comment', 'type' => 'textarea', 'label' => 'Comment', 'required' => true] ]); // Create link action $linkAction = InteractiveAction::link('docs', 'View Documentation', 'https://docs.example.com', 'Learn more about this feature', true); // Create file upload action $uploadAction = InteractiveAction::fileUpload('upload', 'Upload File', ['image/*', 'application/pdf'], 5242880, false, 'Upload supporting documents');
Advanced Interactive Actions
// Create card with embedded actions $cardAction = InteractiveAction::card('product', 'Product Recommendation', 'Based on your preferences, we recommend this product.', 'https://example.com/product-image.jpg', [ InteractiveAction::button('buy', 'Buy Now', [ 'action' => ['type' => 'url', 'url' => 'https://store.example.com/buy'] ]), InteractiveAction::button('details', 'View Details', [ 'action' => ['type' => 'callback', 'callback' => 'showProductDetails'] ]) ] ); // Create confirmation action $confirmAction = InteractiveAction::confirm('delete', 'Delete Item', 'Are you sure you want to delete this item? This action cannot be undone.', ['item_id' => 123] ); // Create menu/dropdown action $menuAction = InteractiveAction::menu('category', 'Select Category', [ ['value' => 'tech', 'label' => 'Technology'], ['value' => 'business', 'label' => 'Business'], ['value' => 'health', 'label' => 'Health'] ]);
Executing Interactive Actions
// Execute an action when user interacts $action = Engine::createAction([ 'id' => 'approve_request', 'type' => 'button', 'label' => 'Approve', 'data' => [ 'action' => [ 'type' => 'callback', 'callback' => 'handleApproval' ] ] ]); $response = Engine::executeAction($action, [ 'request_id' => 123, 'user_id' => 456 ]); if ($response->success) { echo "Action executed successfully: " . $response->message; } else { echo "Action failed: " . $response->message; } // Validate action before execution $errors = Engine::validateAction($action, ['request_id' => 123]); if (empty($errors)) { $response = Engine::executeAction($action, ['request_id' => 123]); } // Get supported action types $supportedTypes = Engine::getSupportedActionTypes(); // Returns: ['button', 'quick_reply', 'form', 'link', 'file_upload', etc.]
Action Event Handling
// Listen for action events in your EventServiceProvider Event::listen('ai.action.button.clicked', function ($data) { $action = $data['action']; $payload = $data['payload']; // Handle button click Log::info('Button clicked', ['action_id' => $action->id]); }); Event::listen('ai.action.form.submit', function ($data) { $formId = $data['form_id']; $payload = $data['payload']; // Handle form submission // Process form data... }); Event::listen('ai.action.callback', function ($data) { $callback = $data['callback']; $action = $data['action']; $payload = $data['payload']; // Handle custom callback if ($callback === 'handleApproval') { // Process approval logic return ['status' => 'approved', 'timestamp' => now()]; } });
Custom Action Handlers
use LaravelAIEngine\Contracts\ActionHandlerInterface; use LaravelAIEngine\DTOs\InteractiveAction; use LaravelAIEngine\DTOs\ActionResponse; class CustomActionHandler implements ActionHandlerInterface { public function handle(InteractiveAction $action, array $payload = []): ActionResponse { // Custom action handling logic return ActionResponse::success( $action->id, $action->type, 'Custom action executed successfully', $payload ); } public function validate(InteractiveAction $action, array $payload = []): array { // Custom validation logic return []; } public function supports(string $actionType): bool { return $actionType === 'custom'; } public function priority(): int { return 50; } } // Register custom handler app(ActionManager::class)->registerHandler(new CustomActionHandler());
Basic Text Generation (Traditional API)
use LaravelAIEngine\Facades\AIEngine; // Simple text generation $response = AIEngine::engine('openai') ->model('gpt-4o') ->generate('Write a blog post about Laravel'); echo $response->content;
With User and Credit Management
$response = AIEngine::engine('openai') ->model('gpt-4o') ->forUser($user->id) ->generate('Explain quantum computing'); if ($response->isSuccess()) { echo "Content: " . $response->content; echo "Credits used: " . $response->creditsUsed; } else { echo "Error: " . $response->error; }
Streaming Responses
$stream = AIEngine::engine('anthropic') ->model('claude-3-5-sonnet') ->generateStream('Write a story about AI'); foreach ($stream as $chunk) { echo $chunk; // Output each chunk as it arrives }
Image Generation
$response = AIEngine::engine('openai') ->model('dall-e-3') ->generateImage('A futuristic city at sunset', count: 2); foreach ($response->files as $imageUrl) { echo "<img src='{$imageUrl}' alt='Generated image'>"; }
Video Generation
$response = AIEngine::engine('stable_diffusion') ->model('sd3-large') ->generateVideo('A cat playing piano in a jazz club'); echo "Video URL: " . $response->getFirstFile();
Audio Processing
// Text to speech $response = AIEngine::engine('eleven_labs') ->model('eleven_multilingual_v2') ->generateAudio('Hello, this is a test of text to speech'); // Speech to text $response = AIEngine::engine('openai') ->model('whisper-1') ->audioToText('/path/to/audio/file.mp3'); echo "Transcription: " . $response->content;
Advanced Features
Error Handling and Retry
$response = AIEngine::engine('openai') ->model('gpt-4o') ->withRetry(maxAttempts: 3, backoff: 'exponential') ->fallbackTo('anthropic') ->generate('Complex prompt that might fail');
Caching
// Enable caching for this request $response = AIEngine::engine('openai') ->model('gpt-4o') ->cache(enabled: true, ttl: 7200) ->generate('Expensive computation'); // Check if response was cached if ($response->isCached()) { echo "This response was served from cache!"; }
Rate Limiting
// Check remaining requests $remaining = AIEngine::engine('openai')->getRemainingRequests(); echo "Remaining requests: {$remaining}"; // The engine will automatically handle rate limiting $response = AIEngine::engine('openai') ->model('gpt-4o') ->rateLimit(enabled: true) ->generate('Your prompt');
Content Moderation
$response = AIEngine::engine('openai') ->model('gpt-4o') ->withModeration(level: 'strict') ->generate('User-generated content');
Templates
// Define templates in config/ai-engine.php 'templates' => [ 'blog_post' => 'Write a {tone} blog post about {topic} targeting {audience}.', 'email_subject' => 'Create an email subject line for {product} targeting {demographic}.', ], // Use templates $response = AIEngine::template('blog_post') ->with([ 'tone' => 'professional', 'topic' => 'Laravel development', 'audience' => 'developers' ]) ->options(['engine' => 'anthropic', 'model' => 'claude-3-5-sonnet']) ->generate();
Job Queue System
The package includes a comprehensive job queue system for processing AI requests asynchronously, handling batch operations, and managing long-running tasks with intelligent rate limiting.
Background Processing
Queue individual AI requests for background processing:
use LaravelAIEngine\Services\QueuedAIProcessor; $processor = app(QueuedAIProcessor::class); // Queue a simple AI request $jobId = $processor->queueRequest( request: $aiRequest, callbackUrl: 'https://example.com/callback', queue: 'ai-processing', userId: 'user-123' // For user-specific rate limiting ); echo "Job queued with ID: {$jobId}";
Batch Processing
Process multiple AI requests efficiently in batches:
// Queue a batch of requests $batchId = $processor->queueBatch( requests: [$request1, $request2, $request3], callbackUrl: 'https://example.com/batch-callback', stopOnError: false, // Continue processing even if some requests fail queue: 'batch-processing', userId: 'user-123' ); // Check batch status $status = $processor->getJobStatus($batchId); echo "Batch progress: {$status['progress_percentage']}%";
Long-Running Tasks
Handle expensive operations like video generation with progress tracking:
// Queue a long-running task $jobId = $processor->queueLongRunningTask( request: $videoRequest, taskType: 'video_generation', callbackUrl: 'https://example.com/video-callback', progressCallbacks: ['https://example.com/progress'], queue: 'video-processing', userId: 'user-123' ); // Monitor progress $progress = $processor->getJobProgress($jobId); echo "Progress: {$progress['percentage']}% - {$progress['message']}";
Job Status Tracking
Monitor job status and progress in real-time:
use LaravelAIEngine\Services\JobStatusTracker; $tracker = app(JobStatusTracker::class); // Get job status $status = $tracker->getStatus($jobId); echo "Status: {$status['status']}"; // queued, processing, completed, failed, rate_limited // Check if job is running if ($tracker->isRunning($jobId)) { $progress = $tracker->getProgress($jobId); echo "Progress: {$progress['percentage']}%"; } // Get job statistics $stats = $tracker->getStatistics($userId); echo "Total jobs: {$stats['total_jobs']}"; echo "Completed: {$stats['completed_jobs']}";
OpenRouter Fallback Integration
The package includes comprehensive OpenRouter support as a fallback engine, providing access to multiple AI models through a unified API with competitive pricing and high availability.
Using OpenRouter as Fallback
OpenRouter serves as an excellent fallback engine because it provides access to multiple AI providers (OpenAI, Anthropic, Google, Meta, Mistral, etc.) through a single API:
use LaravelAIEngine\Facades\AIEngine; // Configure OpenRouter as fallback for primary engines $response = AIEngine::engine('openai') ->model('gpt-4o') ->fallbackTo('openrouter') // Will use OpenRouter if OpenAI fails ->withRetry(3) ->generate('Your prompt here');
OpenRouter Configuration
Add OpenRouter configuration to your .env
file:
# OpenRouter API Configuration OPENROUTER_API_KEY=your_openrouter_api_key OPENROUTER_SITE_URL=https://yourapp.com OPENROUTER_SITE_NAME="Your App Name"
Available OpenRouter Models
OpenRouter provides access to popular models from multiple providers:
// Use latest GPT-5 models through OpenRouter (August 2025) $response = AIEngine::engine('openrouter') ->model('openai/gpt-5') // GPT-5 - Latest generation AI model ->generate('Your prompt'); $response = AIEngine::engine('openrouter') ->model('openai/gpt-5-mini') // GPT-5 Mini - Efficient latest model ->generate('Your prompt'); // Latest Gemini 2.5 models with thinking capabilities (March 2025) $response = AIEngine::engine('openrouter') ->model('google/gemini-2.5-pro') // Gemini 2.5 Pro - Most intelligent AI with thinking ->generate('Your prompt'); $response = AIEngine::engine('openrouter') ->model('google/gemini-2.5-pro-experimental') // Gemini 2.5 Pro Experimental ->generate('Your prompt'); // Claude 4 models - World's best coding models $response = AIEngine::engine('openrouter') ->model('anthropic/claude-4-opus') // Claude 4 Opus - World's best coding model ->generate('Your prompt'); $response = AIEngine::engine('openrouter') ->model('anthropic/claude-4-sonnet') // Claude 4 Sonnet - Advanced reasoning ->generate('Your prompt'); // Free Models - Perfect for testing and cost-effective usage $response = AIEngine::engine('openrouter') ->model('meta-llama/llama-3.1-8b-instruct:free') // Llama 3.1 8B - Free tier ->generate('Your prompt'); $response = AIEngine::engine('openrouter') ->model('google/gemma-2-9b-it:free') // Gemma 2 9B - Free tier ->generate('Your prompt'); $response = AIEngine::engine('openrouter') ->model('mistralai/mistral-7b-instruct:free') // Mistral 7B - Free tier ->generate('Your prompt');
Automatic Fallback Configuration
The package automatically configures OpenRouter as the primary fallback for all engines:
// In config/ai-engine.php - automatically configured 'error_handling' => [ 'fallback_engines' => [ 'openai' => ['openrouter', 'anthropic', 'gemini'], 'anthropic' => ['openrouter', 'openai', 'gemini'], 'gemini' => ['openrouter', 'openai', 'anthropic'], 'openrouter' => ['openai', 'anthropic', 'gemini'], ], ],
Queue-Based Fallback
OpenRouter fallback works seamlessly with the job queue system:
use LaravelAIEngine\Services\QueuedAIProcessor; $processor = app(QueuedAIProcessor::class); // If primary engine fails, jobs automatically fallback to OpenRouter $jobId = $processor->queueRequest( request: $aiRequest, callbackUrl: 'https://example.com/callback', userId: 'user-123' ); // Monitor fallback usage in job status $status = $processor->getJobStatus($jobId); if (isset($status['fallback_used'])) { echo "Used fallback engine: {$status['fallback_engine']}"; }
Cost-Effective Fallback Strategy
OpenRouter often provides competitive pricing and can serve as a cost-effective fallback:
// OpenRouter models with competitive pricing (2025 latest models) $models = [ // Free Models (Perfect for Testing & Development) 'meta-llama/llama-3.1-8b-instruct:free' => 0.0, // Llama 3.1 8B - Free 'meta-llama/llama-3.2-3b-instruct:free' => 0.0, // Llama 3.2 3B - Free 'google/gemma-2-9b-it:free' => 0.0, // Gemma 2 9B - Free 'mistralai/mistral-7b-instruct:free' => 0.0, // Mistral 7B - Free 'qwen/qwen-2.5-7b-instruct:free' => 0.0, // Qwen 2.5 7B - Free 'microsoft/phi-3-mini-128k-instruct:free' => 0.0, // Phi-3 Mini - Free 'openchat/openchat-3.5-1210:free' => 0.0, // OpenChat 3.5 - Free // GPT-5 Models (Latest Generation - August 2025) 'openai/gpt-5' => 5.0, // Premium GPT-5 - Latest generation 'openai/gpt-5-mini' => 2.5, // GPT-5 Mini - Efficient latest model 'openai/gpt-5-nano' => 1.0, // GPT-5 Nano - Ultra-efficient // Gemini 2.5 Models (Latest Generation - March 2025) 'google/gemini-2.5-pro' => 3.0, // Most intelligent AI with thinking 'google/gemini-2.5-pro-experimental' => 3.2, // Experimental version // Claude 4 Models (Latest Generation) 'anthropic/claude-4-opus' => 4.5, // Premium Claude 4 - World's best coding 'anthropic/claude-4-sonnet' => 3.5, // Claude 4 Sonnet - Advanced reasoning // Previous Generation Models (Still Competitive) 'openai/gpt-4o-2024-11-20' => 2.3, // Latest GPT-4o version 'anthropic/claude-3.5-sonnet-20241022' => 2.1, // Latest Claude 3.5 Sonnet 'google/gemini-2.0-flash' => 1.9, // Previous Gemini generation 'meta-llama/llama-3.3-70b-instruct' => 1.3, // Latest Llama 3.3 'deepseek/deepseek-r1' => 0.4, // Latest DeepSeek R1 ];
Benefits of OpenRouter as Fallback
- High Availability: Access to multiple providers reduces downtime
- Model Diversity: Access to models not available through direct APIs
- Competitive Pricing: Often lower costs than direct API access
- Unified Interface: Single API for multiple providers
- Rate Limit Resilience: Higher rate limits through unified API
- Geographic Availability: Better global coverage
Conversation Memory
The package provides comprehensive conversation memory support for building chat applications and maintaining context across AI interactions.
Creating and Managing Conversations
use LaravelAIEngine\Services\ConversationManager; $conversationManager = app(ConversationManager::class); // Create a new conversation $conversation = $conversationManager->createConversation( userId: 'user-123', title: 'Customer Support Chat', systemPrompt: 'You are a helpful customer support assistant.', settings: [ 'max_messages' => 100, 'temperature' => 0.7, 'auto_title' => true ] ); // Get conversation by ID $conversation = $conversationManager->getConversation($conversationId); // Get all conversations for a user $conversations = $conversationManager->getUserConversations('user-123');
Context-Aware AI Generation
use LaravelAIEngine\Services\AIEngineService; use LaravelAIEngine\Enums\EngineEnum; use LaravelAIEngine\Enums\EntityEnum; $aiEngine = app(AIEngineService::class); // Generate response with conversation context $response = $aiEngine->generateWithConversation( message: 'What was my previous question?', conversationId: $conversation->conversation_id, engine: EngineEnum::OPENAI, model: EntityEnum::GPT_4O, userId: 'user-123' ); // The AI will have access to the full conversation history echo $response->content; // "Your previous question was about..."
Manual Message Management
// Add user message $userMessage = $conversationManager->addUserMessage( $conversationId, 'Hello, I need help with my order', ['metadata' => 'support_ticket_123'] ); // Add assistant message with AI response $assistantMessage = $conversationManager->addAssistantMessage( $conversationId, 'I\'d be happy to help with your order!', $aiResponse );
Conversation Settings and Management
// Update conversation settings $conversationManager->updateConversationSettings($conversationId, [ 'max_messages' => 200, 'temperature' => 0.8, 'auto_title' => false ]); // Get conversation statistics $stats = $conversationManager->getConversationStats($conversationId); // Returns: total_messages, user_messages, assistant_messages, created_at, last_activity // Clear conversation history $conversationManager->clearConversationHistory($conversationId); // Delete conversation (marks as inactive) $conversationManager->deleteConversation($conversationId);
Advanced Conversation Features
Auto-Title Generation
// Conversations with auto_title enabled automatically generate titles $conversation = $conversationManager->createConversation( userId: 'user-123', settings: ['auto_title' => true] ); // After first user message, title is auto-generated $conversationManager->addUserMessage($conversationId, 'What is machine learning?'); // Title becomes: "What is machine learning?"
Message Trimming
// Conversations automatically trim old messages when limit is reached $conversation = $conversationManager->createConversation( userId: 'user-123', settings: ['max_messages' => 50] ); // When 51st message is added, oldest message is automatically deleted
Context Retrieval
// Get conversation context for AI requests $context = $conversationManager->getConversationContext($conversationId); // Returns array of messages in format: [{'role': 'user', 'content': '...'}, ...] // Enhanced AI request with context $enhancedRequest = $conversationManager->enhanceRequestWithContext( $baseRequest, $conversationId );
Database Schema
The conversation memory system uses two main tables:
ai_conversations
conversation_id
(string, unique identifier)user_id
(string, user identifier)title
(string, nullable, conversation title)system_prompt
(text, nullable, system instructions)settings
(json, conversation configuration)is_active
(boolean, soft deletion flag)last_activity_at
(timestamp, last message time)
ai_messages
conversation_id
(string, foreign key)role
(enum: user, assistant, system)content
(text, message content)metadata
(json, additional message data)tokens_used
(integer, nullable, token count)credits_used
(decimal, nullable, credit cost)sent_at
(timestamp, message timestamp)
Intelligent Rate Limiting
The package includes sophisticated rate limiting that integrates seamlessly with the job queue system.
Queue-Based Rate Limiting
Jobs automatically check rate limits before processing and are intelligently delayed when limits are exceeded:
// Rate limiting is automatically applied to all queued jobs $jobId = $processor->queueRequest($request, userId: 'user-123'); // If rate limited, the job will be automatically delayed and retried // You can monitor this via job status $status = $tracker->getStatus($jobId); if ($status['status'] === 'rate_limited') { echo "Job delayed due to rate limiting"; echo "Will retry at: {$status['retry_at']}"; }
User-Specific Rate Limiting
Support for per-user rate limiting in multi-tenant applications:
// Each user has their own rate limit counters $jobId1 = $processor->queueRequest($request, userId: 'user-123'); $jobId2 = $processor->queueRequest($request, userId: 'user-456'); // Users don't affect each other's rate limits
Batch Rate Limiting
Intelligent handling of rate limits in batch operations:
// When processing batches, the system automatically splits requests // Some requests process immediately, others are delayed $batchId = $processor->queueBatch($requests, userId: 'user-123'); $status = $tracker->getStatus($batchId); echo "Processable requests: {$status['processable_requests']}"; echo "Delayed requests: {$status['delayed_requests']}";
Rate Limiting Configuration
Configure rate limiting behavior:
// In config/ai-engine.php 'rate_limiting' => [ 'enabled' => true, 'apply_to_jobs' => true, // Enable rate limiting for queued jobs 'per_engine' => [ 'openai' => ['requests' => 100, 'per_minute' => 1], 'anthropic' => ['requests' => 50, 'per_minute' => 1], ], ],
Synchronous Batch Processing
For immediate batch processing (non-queued):
$batch = AIEngine::batch() ->add('openai', 'gpt-4o', 'First prompt') ->add('anthropic', 'claude-3-5-sonnet', 'Second prompt') ->add('gemini', 'gemini-1.5-pro', 'Third prompt'); $results = $batch->process(); foreach ($results as $index => $response) { echo "Result {$index}: " . $response->content . "\n"; }
Webhook Notifications
The package includes reliable webhook delivery with automatic retries and exponential backoff:
Queued Webhook Delivery
use LaravelAIEngine\Services\WebhookManager; $webhookManager = app(WebhookManager::class); // Send webhook notification with automatic retry $webhookManager->sendWebhookQueued( url: 'https://example.com/webhook', data: [ 'job_id' => $jobId, 'status' => 'completed', 'result' => $response->toArray() ], maxRetries: 3, queue: 'webhooks' );
Webhook Configuration
Configure webhook behavior in your job callbacks:
// When queueing jobs, provide callback URLs $jobId = $processor->queueRequest( request: $aiRequest, callbackUrl: 'https://example.com/ai-callback', userId: 'user-123' ); // The system will automatically send webhooks when jobs complete
Database Setup
Run the migration to create the job status tracking table:
php artisan migrate
This creates the ai_job_statuses
table for persistent job tracking with the following structure:
Schema::create('ai_job_statuses', function (Blueprint $table) { $table->string('job_id')->primary(); $table->string('user_id')->nullable()->index(); $table->enum('status', ['queued', 'processing', 'completed', 'failed', 'rate_limited']); $table->json('data')->nullable(); $table->integer('progress_percentage')->default(0); $table->string('progress_message')->nullable(); $table->timestamp('started_at')->nullable(); $table->timestamp('completed_at')->nullable(); $table->timestamps(); $table->index(['user_id', 'status']); $table->index('created_at'); });
Configuration Reference
Environment Variables
# Core AI Engine AI_DEFAULT_ENGINE=openai AI_DEFAULT_MODEL=gpt-4o AI_TIMEOUT=30 # OpenAI OPENAI_API_KEY=your_openai_key # Anthropic ANTHROPIC_API_KEY=your_anthropic_key # Google Gemini GOOGLE_AI_API_KEY=your_google_key # OpenRouter OPENROUTER_API_KEY=your_openrouter_key OPENROUTER_SITE_URL=https://yourapp.com OPENROUTER_SITE_NAME="Your App Name" # Credit System AI_CREDITS_ENABLED=true AI_DEFAULT_CREDITS=100.0 # Caching AI_CACHE_ENABLED=true AI_CACHE_TTL=3600 # Rate Limiting AI_RATE_LIMITING_ENABLED=true AI_RATE_LIMITING_APPLY_TO_JOBS=true AI_RATE_LIMIT_DRIVER=redis # Job Queue QUEUE_CONNECTION=redis
Advanced Configuration
// config/ai-engine.php return [ 'job_queue' => [ 'default_queue' => 'ai-processing', 'long_running_queue' => 'ai-long-running', 'webhook_queue' => 'webhooks', 'status_cache_ttl' => 3600, 'cleanup_completed_jobs_after' => 86400, // 24 hours ], 'rate_limiting' => [ 'enabled' => env('AI_RATE_LIMITING_ENABLED', true), 'apply_to_jobs' => env('AI_RATE_LIMITING_APPLY_TO_JOBS', true), 'driver' => env('AI_RATE_LIMIT_DRIVER', 'cache'), 'per_engine' => [ 'openai' => ['requests' => 100, 'per_minute' => 1], 'anthropic' => ['requests' => 50, 'per_minute' => 1], 'gemini' => ['requests' => 60, 'per_minute' => 1], ], ], 'webhooks' => [ 'max_retries' => 3, 'retry_delay' => 60, // seconds 'timeout' => 30, ], ];
Cost Estimation
// Estimate cost before making request $estimate = AIEngine::engine('openai') ->model('gpt-4o') ->estimateCost('Long prompt that will use many tokens...'); echo "Estimated credits: " . $estimate['credits']; // Estimate cost for multiple operations $estimate = AIEngine::estimateCost([ ['engine' => 'openai', 'model' => 'gpt-4o', 'prompt' => 'Text generation'], ['engine' => 'openai', 'model' => 'dall-e-3', 'prompt' => 'Image generation', 'parameters' => ['image_count' => 2]], ]); echo "Total estimated credits: " . $estimate['total_credits'];
Credit Management
User Credits
use LaravelAIEngine\Services\CreditManager; $creditManager = app(CreditManager::class); // Check user credits $credits = $creditManager->getUserCredits($userId, EngineEnum::OPENAI, EntityEnum::GPT_4O); echo "Balance: " . $credits['balance']; // Add credits $creditManager->addCredits($userId, EngineEnum::OPENAI, EntityEnum::GPT_4O, 100.0); // Set unlimited credits $creditManager->setUnlimitedCredits($userId, EngineEnum::OPENAI, EntityEnum::GPT_4O); // Check if user has low credits if ($creditManager->hasLowCredits($userId)) { // Send low credit notification }
Usage Statistics
$stats = $creditManager->getUsageStats($userId); echo "Total requests: " . $stats['total_requests']; echo "Total credits used: " . $stats['total_credits_used'];
Analytics
use LaravelAIEngine\Services\AnalyticsManager; $analytics = app(AnalyticsManager::class); // Get usage statistics $stats = $analytics->getUsageStats([ 'user_id' => $userId, 'engine' => 'openai', 'from_date' => now()->subDays(30), ]); // Get cost analysis $costs = $analytics->getCostAnalysis([ 'user_id' => $userId, 'from_date' => now()->subMonth(), ]); // Get performance metrics $performance = $analytics->getPerformanceMetrics([ 'engine' => 'openai', 'from_date' => now()->subWeek(), ]);
Artisan Commands
# Test all configured engines php artisan ai:test-engines # Sync latest models from providers php artisan ai:sync-models # Generate usage report php artisan ai:usage-report --user=123 --days=30 # Clear AI response cache php artisan ai:clear-cache --engine=openai
Events
The package dispatches several events you can listen to:
// Listen for AI request completion Event::listen(\LaravelAIEngine\Events\AIRequestCompleted::class, function ($event) { // Handle completion Log::info('AI request completed', [ 'user_id' => $event->request->userId, 'engine' => $event->request->engine->value, 'credits_used' => $event->response->creditsUsed, ]); }); // Listen for errors Event::listen(\LaravelAIEngine\Events\AIRequestFailed::class, function ($event) { // Handle error Log::error('AI request failed', [ 'error' => $event->exception->getMessage(), 'engine' => $event->request->engine->value, ]); });
Enterprise Features
🎯 Interactive Actions
Add interactive elements to AI responses for enhanced user engagement:
use LaravelAIEngine\Facades\Engine; use LaravelAIEngine\DTOs\InteractiveAction; use LaravelAIEngine\Enums\ActionTypeEnum; // Generate AI response with interactive actions $response = Engine::send('What would you like to do next?'); // Add interactive buttons $response->addAction(new InteractiveAction( id: 'continue_chat', type: ActionTypeEnum::BUTTON, label: 'Continue Conversation', data: ['action' => 'continue'] )); $response->addAction(new InteractiveAction( id: 'new_topic', type: ActionTypeEnum::BUTTON, label: 'New Topic', data: ['action' => 'new_topic'] )); // Add quick reply options $response->addAction(new InteractiveAction( id: 'quick_reply', type: ActionTypeEnum::QUICK_REPLY, label: 'Yes, please!', data: ['reply' => 'yes'] )); // Execute action when triggered $actionResponse = Engine::executeAction($action, $payload);
🔄 Automatic Failover
Ensure high availability with automatic provider failover:
use LaravelAIEngine\Facades\Engine; // Execute with automatic failover $response = Engine::executeWithFailover( callback: fn($provider) => Engine::engine($provider)->send('Hello world'), providers: ['openai', 'anthropic', 'gemini'], strategy: 'priority', // or 'round_robin' options: ['timeout' => 30] ); // Check provider health $health = Engine::getProviderHealth('openai'); // Returns: ['status' => 'healthy', 'failure_count' => 0, 'last_check' => '...'] // Get system health overview $systemHealth = Engine::getSystemHealth();
🌊 WebSocket Streaming
Real-time AI response streaming with WebSocket support:
use LaravelAIEngine\Facades\Engine; // Start streaming server Engine::streamResponse( sessionId: 'user-session-123', generator: function() { yield 'Hello '; yield 'world '; yield 'from AI!'; }, options: ['chunk_size' => 10] ); // Stream with interactive actions Engine::streamWithActions( sessionId: 'user-session-123', generator: $responseGenerator, actions: [ ['type' => 'button', 'label' => 'Continue', 'action' => 'continue'] ] ); // Get streaming statistics $stats = Engine::getStreamingStats();
📊 Advanced Analytics
Comprehensive usage monitoring and analytics:
use LaravelAIEngine\Facades\Engine; // Track custom events Engine::trackRequest([ 'engine' => 'openai', 'model' => 'gpt-4o', 'tokens' => 150, 'cost' => 0.003, 'user_id' => auth()->id() ]); // Get dashboard data $dashboard = Engine::getDashboardData([ 'date_from' => '2024-01-01', 'date_to' => '2024-01-31', 'engine' => 'openai' ]); // Get real-time metrics $metrics = Engine::getRealTimeMetrics(); // Generate reports $report = Engine::generateReport([ 'type' => 'monthly', 'format' => 'json', 'include_charts' => true ]);
🧠Memory Storage Drivers
Multiple storage options for conversation persistence:
// Configure in config/ai-engine.php 'memory' => [ 'driver' => 'redis', // redis, database, file, mongodb 'drivers' => [ 'redis' => [ 'connection' => 'default', 'prefix' => 'ai_memory:', 'ttl' => 3600, ], 'mongodb' => [ 'connection_string' => env('AI_MEMORY_MONGODB_CONNECTION'), 'database' => env('AI_MEMORY_MONGODB_DATABASE', 'ai_engine'), 'max_messages' => 1000, ], 'database' => [ 'table' => 'ai_conversations', 'max_messages' => 100, ], ], ],
📡 Event System
Real-time events for streaming, failover, and analytics:
use LaravelAIEngine\Events\AIResponseChunk; use LaravelAIEngine\Events\AIFailoverTriggered; // Listen to streaming events Event::listen(AIResponseChunk::class, function ($event) { // Handle streaming chunk broadcast(new StreamingUpdate($event->sessionId, $event->chunk)); }); // Listen to failover events Event::listen(AIFailoverTriggered::class, function ($event) { // Send alert when failover occurs Log::warning("Provider failover: {$event->fromProvider} → {$event->toProvider}"); });
Console Commands
Analytics Reports
# Generate analytics report php artisan ai-engine:analytics-report --period=monthly --format=table # Export report to file php artisan ai-engine:analytics-report --export=/path/to/report.json # Filter by engine php artisan ai-engine:analytics-report --engine=openai
Failover Management
# Check failover status php artisan ai-engine:failover-status # Check specific provider php artisan ai-engine:failover-status --provider=openai # Reset provider health php artisan ai-engine:failover-status --reset=openai
Streaming Server
# Start WebSocket server php artisan ai-engine:streaming-server start --host=0.0.0.0 --port=8080 # Check server status php artisan ai-engine:streaming-server status # Get server statistics php artisan ai-engine:streaming-server stats # Stop server php artisan ai-engine:streaming-server stop
System Health
# Check overall system health php artisan ai-engine:system-health # Detailed health information php artisan ai-engine:system-health --detailed # JSON output php artisan ai-engine:system-health --format=json
Configuration
Enterprise Features Configuration
// config/ai-engine.php // Automatic Failover 'failover' => [ 'enabled' => env('AI_FAILOVER_ENABLED', true), 'strategy' => env('AI_FAILOVER_STRATEGY', 'priority'), 'circuit_breaker' => [ 'failure_threshold' => env('AI_FAILOVER_FAILURE_THRESHOLD', 5), 'timeout' => env('AI_FAILOVER_TIMEOUT', 60), 'retry_timeout' => env('AI_FAILOVER_RETRY_TIMEOUT', 300), ], ], // WebSocket Streaming 'streaming' => [ 'enabled' => env('AI_STREAMING_ENABLED', true), 'websocket' => [ 'host' => env('AI_WEBSOCKET_HOST', '0.0.0.0'), 'port' => env('AI_WEBSOCKET_PORT', 8080), 'max_connections' => env('AI_WEBSOCKET_MAX_CONNECTIONS', 1000), ], ], // Analytics 'analytics' => [ 'enabled' => env('AI_ANALYTICS_ENABLED', true), 'driver' => env('AI_ANALYTICS_DRIVER', 'database'), 'retention_days' => env('AI_ANALYTICS_RETENTION_DAYS', 90), 'real_time_metrics' => env('AI_ANALYTICS_REAL_TIME', true), ], // Interactive Actions 'actions' => [ 'enabled' => env('AI_ACTIONS_ENABLED', true), 'max_actions_per_response' => env('AI_ACTIONS_MAX_PER_RESPONSE', 10), 'validation' => [ 'strict_mode' => env('AI_ACTIONS_STRICT_VALIDATION', true), ], ],
Extending the Package
Adding Custom Engines
- Create a new engine driver:
use LaravelAIEngine\Drivers\BaseEngineDriver; class CustomEngineDriver extends BaseEngineDriver { public function generateText(AIRequest $request): AIResponse { // Implement your custom engine logic } // Implement other required methods... }
- Add to the EngineEnum:
case CUSTOM_ENGINE = 'custom_engine'; public function driverClass(): string { return match ($this) { // ... existing cases self::CUSTOM_ENGINE => CustomEngineDriver::class, }; }
Custom Action Handlers
use LaravelAIEngine\Services\Actions\Contracts\ActionHandlerInterface; class CustomActionHandler implements ActionHandlerInterface { public function handle(InteractiveAction $action, array $payload): ActionResponse { // Implement custom action logic return new ActionResponse( success: true, data: ['result' => 'Custom action executed'], message: 'Action completed successfully' ); } public function supports(string $actionType): bool { return $actionType === 'custom_action'; } } // Register in service provider Engine::registerActionHandler(new CustomActionHandler());
Custom Analytics Drivers
use LaravelAIEngine\Services\Analytics\Contracts\AnalyticsDriverInterface; class CustomAnalyticsDriver implements AnalyticsDriverInterface { public function track(string $type, array $data): bool { // Implement custom tracking logic } public function query(string $type, array $filters = []): array { // Implement custom querying logic } }
Testing
composer test
Contributing
Please see CONTRIBUTING.md for details.
Security
If you discover any security related issues, please email security@magicai.com instead of using the issue tracker.
License
The MIT License (MIT). Please see License File for more information.
Changelog
Please see CHANGELOG.md for more information on what has changed recently.