creativecrafts/laravel-ai-assistant

A handy package to access and interact with OpenAi endpoint


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Laravel AI Assistant is an enterprise-grade, comprehensive package designed to seamlessly integrate OpenAI's powerful language models into your Laravel applications. It provides an easy-to-use, fluent API with advanced features including streaming responses, background job processing, lazy loading optimization, comprehensive metrics collection, robust security controls, and sophisticated error handling. Perfect for building production-ready AI-powered applications with enterprise-level reliability and performance.

🔄 Migration Guide (Version 3.x is current in beta and not ready for production)

Upgrading to Latest Version

From v2.x to v3.x

  • Breaking Change: The default model has been updated from gpt-4 to gpt-5
  • Breaking Change: Streaming configuration has been moved from root level to streaming array
  • New Feature: Responses API is now the default for new installations
  • Configuration Changes:
    // Old configuration
    'stream' => true,
    'buffer_size' => 8192,
    
    // New configuration
    'streaming' => [
        'enabled' => true,
        'buffer_size' => 8192,
        'chunk_size' => 1024,
        'timeout' => 120,
    ],

From v1.x to v2.x

  • Breaking Change: Minimum PHP version increased to 8.2
  • Breaking Change: Laravel 9 support dropped, minimum Laravel 10 required
  • New Feature: Background job processing added
  • Configuration Changes:
    // Add to your .env file
    AI_BACKGROUND_JOBS_ENABLED=false  // Set to true if you want to enable
    AI_QUEUE_NAME=ai-assistant

Migration Steps

  1. Update Dependencies:

    composer update creativecrafts/laravel-ai-assistant
  2. Update Configuration:

    php artisan vendor:publish --tag="laravel-ai-assistant-config" --force
  3. Update Environment Variables:

    • Review your .env file against the new configuration options
    • Update any deprecated environment variables
  4. Test Your Implementation:

    • Run your test suite to ensure compatibility
    • Check for any deprecated method usage
  5. Update Database (if using Eloquent persistence):

    php artisan vendor:publish --tag="laravel-ai-assistant-migrations" --force
    php artisan migrate

Deprecated Features

  • ⚠️ Assistant::sendMessage() - Use sendChatMessage() instead
  • ⚠️ Root-level streaming config - Use streaming array configuration
  • ⚠️ Legacy thread management - Migrate to Responses API for better performance

For detailed migration instructions, see the migration documentation.

Table of Contents

Overview

Laravel AI Assistant simplifies the integration of AI models into your Laravel application with enterprise-grade features. Whether you're building a conversational chatbot, automating content creation, transcribing audio files, or processing large-scale AI operations, this package provides a clean, expressive API to handle complex tasks with minimal effort.

The package now includes advanced architectural improvements:

  • Enterprise-grade streaming with memory management and performance monitoring
  • Background job processing for long-running AI operations
  • Lazy loading optimization for better resource management
  • Comprehensive metrics collection for monitoring and analytics
  • Advanced security features including rate limiting and request validation
  • Sophisticated error handling with custom exception types
  • Performance optimizations including caching and connection pooling

⚡ Quick Start (5 Minutes)

Get up and running with Laravel AI Assistant in just 5 minutes:

1. Install the Package

composer require creativecrafts/laravel-ai-assistant

2. Set Your API Key

Add your OpenAI API key to your .env file:

OPENAI_API_KEY=your-openai-api-key-here

3. Publish Configuration (Optional)

php artisan vendor:publish --tag="laravel-ai-assistant-config"

4. Start Using AI Assistant

use CreativeCrafts\LaravelAiAssistant\Facades\Ai;

// Simple chat interaction
$response = Ai::chat('Explain Laravel in one sentence')->send();
echo $response->getContent();

// Or use the fluent builder
$response = Ai::assistant()
    ->usingModel('gpt-4o')
    ->withTemperature(0.7)
    ->sendChatMessage('Write a haiku about coding');

5. Enable Advanced Features (Optional)

For production use, consider enabling these features in your .env:

# Background job processing
AI_BACKGROUND_JOBS_ENABLED=true
AI_QUEUE_NAME=ai-assistant

# Streaming responses
AI_STREAMING_ENABLED=true

# Metrics collection
AI_METRICS_ENABLED=true
AI_METRICS_DRIVER=database

# Connection pooling for better performance
AI_CONNECTION_POOL_ENABLED=true

That's it! You now have a powerful AI assistant integrated into your Laravel application. Continue reading for advanced features and configuration options.

Features

Core Features

  • Fluent API: Chain method calls for a clean and intuitive setup
  • Chat Messaging: Easily manage user, developer, and tool messages
  • Audio Transcription: Convert audio files to text with optional prompts
  • Tool Integration: Extend functionality with file search, code interpreter, and custom function calls
  • Custom Configuration: Configure model parameters, temperature, top_p, and more
  • DTOs & Factories: Use data transfer objects to structure and validate your data

Advanced Features

  • Streaming Service: Real-time response streaming with memory management and buffering
  • Background Jobs: Queue long-running AI operations with progress tracking
  • Lazy Loading: Optimize resource usage with intelligent lazy initialization
  • Metrics Collection: Comprehensive monitoring of API usage, performance, and costs
  • Security Service: Advanced security with API key validation, rate limiting, and request signing
  • Error Handling: Robust exception system with 8+ custom exception types
  • Performance Monitoring: Memory usage tracking and performance optimization
  • Caching & Optimization: Intelligent caching for improved performance

Choosing the right class

Pick the entrypoint that best matches your use case:

  • AiAssistant (Responses API)

    • Ephemeral, per-turn options. Best for one-off chat turns with modern Responses + Conversations APIs.
    • Strongly-typed DTOs are available via sendChatMessageDto() and ResponseEnvelope via sendChatMessageEnvelope().
    • Great when you want full control over tools, files, response formats, and streaming.
  • Assistant (legacy Chat Completions style)

    • Persistent-style builder with backwards compatibility. Returns arrays by default, DTO via sendChatMessageDto().
    • Useful when migrating existing code; supports streaming and many configuration options.
  • Facade Ai

    • Ai::chat() provides a discoverable, typed ChatSession over AiAssistant.
    • Ai::assistant() gives you the Assistant builder when you prefer that flow.

Quick examples

  • One-off turn (modern Responses API)
use CreativeCrafts\LaravelAiAssistant\Facades\Ai;

$response = Ai::chat('Summarize SOLID in 2 lines')
    ->setResponseFormatText()
    ->send();

echo $response->content; // normalized text content when available
  • Streaming (text chunks)
foreach (Ai::chat('Stream a limerick about Laravel')->streamText(fn($t) => print($t)) as $chunk) {
    // $chunk is a string delta
}
  • Assistant (legacy-style)
use CreativeCrafts\LaravelAiAssistant\Assistant;

$assistant = app(Assistant::class)
    ->setUserMessage('Compare Laravel and Symfony briefly');

$result = $assistant->sendChatMessageDto();

When to choose which

  • Prefer Ai::chat() / AiAssistant for new work and modern Responses + Conversations features (tool calls, file_search, json_schema).
  • Use Assistant when migrating older code or when its builder API matches your needs today.

See also: Migration Guide in docs/Migrate_from_AssistantAPI_to_ResponseAPI.md.

Installation

You can install the package via composer:

composer require creativecrafts/laravel-ai-assistant

You can publish the config file with:

php artisan vendor:publish --tag="ai-assistant-config"

Configuration

After publishing, you will find a configuration file at config/ai-assistant.php. The configuration includes:

API Credentials

Set your OpenAI API key and organization:

'api_key' => env('OPENAI_API_KEY', null),
'organization' => env('OPENAI_ORGANIZATION', null),

Note:

  • This package uses openai-php/client ^0.10. For chat completions use $client->chat()->create([...]). For legacy text completions use $client->completions()->create([...]). Do not chain $client-> chat()->completions()->create([...]).
  • AppConfig::openAiClient requires only ai-assistant.api_key. The organization id is optional. If provided, it will be used; otherwise the client is created with API key only.
  • Configuration uses the key max_completion_tokens. AppConfig maps this to the OpenAI API parameter max_tokens in request payloads.

Model Settings

Configure your default models for different operations:

'model' => env('OPENAI_CHAT_MODEL', 'gpt-3.5-turbo'),
'chat_model' => env('OPENAI_CHAT_MODEL', 'gpt-3.5-turbo'),
'edit_model' => 'gpt-4o',
'audio_model' => 'whisper-1',

Advanced Configuration

Configure advanced features like streaming, caching, and security:

// Streaming configuration
'streaming' => [
    'enabled' => true,
    'buffer_size' => 1024,
    'timeout' => 30,
    'memory_limit_mb' => 256,
],

// Background jobs configuration
'background_jobs' => [
    'enabled' => true,
    'queue' => 'ai-operations',
    'timeout' => 300,
    'max_tries' => 3,
],

// Security configuration
'security' => [
    'rate_limiting' => [
        'enabled' => true,
        'max_requests' => 100,
        'time_window' => 3600,
    ],
    'api_key_validation' => true,
    'request_signing' => false,
],

// Metrics collection
'metrics' => [
    'enabled' => true,
    'track_response_times' => true,
    'track_token_usage' => true,
    'track_error_rates' => true,
],

Core Usage

Initializing the Assistant

Create a new assistant instance using the fluent API:

use CreativeCrafts\LaravelAiAssistant\AiAssistant;

$assistant = AiAssistant::init();

Basic Chat Operations

Configure and send chat messages:

$response = AiAssistant::init()
    ->setModelName('gpt-4')
    ->adjustTemperature(0.7)
    ->setDeveloperMessage('Please maintain a friendly tone.')
    ->setUserMessage('What is the weather like today?')
    ->sendChatMessage();

Audio Transcription

Transcribe audio files with language specification:

$transcription = AiAssistant::init()
    ->setFilePath('/path/to/audio.mp3')
    ->transcribeTo('en', 'Transcribe the following audio:');

Creating AI Assistants

Create and configure AI assistants with custom tools:

$assistant = AiAssistant::init()
    ->setModelName('gpt-4')
    ->adjustTemperature(0.5)
    ->setAssistantName('My Assistant')
    ->setAssistantDescription('An assistant for handling tasks')
    ->setInstructions('Be as helpful as possible.')
    ->includeFunctionCallTool(
        'calculateSum',
        'Calculates the sum of two numbers',
        ['num1' => 'number', 'num2' => 'number'],
        isStrict: true,
        requiredParameters: ['num1', 'num2']
    )
    ->create();

Advanced Features

Streaming Service

The streaming service provides real-time response processing with advanced memory management and performance monitoring.

Basic Streaming Usage

use CreativeCrafts\LaravelAiAssistant\Services\StreamingService;

$streamingService = app(StreamingService::class);

// Process a stream with automatic buffering
foreach ($streamingService->processStream($apiStream, 'chat_completion') as $chunk) {
    echo $chunk['content'];
    // Real-time processing of each chunk
}

Advanced Streaming Configuration

// Configure streaming with custom buffer size and chunk processing
$streamingService = app(StreamingService::class);

$customProcessor = function($chunk) {
    // Custom processing logic
    return strtoupper($chunk['content']);
};

foreach ($streamingService->processStream($stream, 'text_completion', $customProcessor) as $chunk) {
    // Process transformed chunks
    broadcast(new StreamChunkEvent($chunk));
}

Streaming Metrics

$metrics = $streamingService->getStreamingMetrics();
// Returns: active_streams, total_streams_processed, average_stream_size_mb, total_data_processed_mb, streaming_errors

$capabilities = $streamingService->validateStreamingCapabilities();
// Returns system capabilities and limits

Background Jobs

Queue long-running AI operations with progress tracking and retry mechanisms.

Queuing Operations

use CreativeCrafts\LaravelAiAssistant\Services\BackgroundJobService;

$jobService = app(BackgroundJobService::class);

// Queue a long-running operation
$jobId = $jobService->queueLongRunningOperation('large_text_processing', [
    'text' => $largeText,
    'model' => 'gpt-4',
    'temperature' => 0.7
], [
    'queue' => 'high-priority',
    'timeout' => 600,
    'max_tries' => 5
]);

echo "Job queued with ID: $jobId";

Batch Operations

// Process multiple items in batches
$batchJobIds = $jobService->queueBatchOperation('translate_texts', [
    ['text' => 'Hello world', 'to' => 'es'],
    ['text' => 'How are you?', 'to' => 'fr'],
    ['text' => 'Good morning', 'to' => 'de']
], 10, ['queue' => 'translations']);

Job Monitoring

// Check job status
$status = $jobService->getJobStatus($jobId);
/*
Returns:
[
    'job_id' => 'job_123',
    'operation' => 'large_text_processing',
    'status' => 'processing', // queued, processing, completed, failed, cancelled
    'progress' => 75,
    'created_at' => '2024-01-01T10:00:00Z',
    'started_at' => '2024-01-01T10:00:05Z',
    'completed_at' => null,
    'duration_seconds' => 42.1,
    'result' => null,
    'error' => null,
    'retry_count' => 1
]
*/

// Get queue statistics
$stats = $jobService->getQueueStatistics();
/*
Returns:
[
    'total_jobs' => 150,
    'queued_jobs' => 5,
    'processing_jobs' => 3,
    'completed_jobs' => 140,
    'failed_jobs' => 2,
    'cancelled_jobs' => 1,
    'average_processing_time' => 45.2,
    'success_rate_percent' => 98.6
]
*/

Lazy Loading

Optimize resource usage with intelligent lazy initialization of AI models and HTTP clients.

Resource Registration

use CreativeCrafts\LaravelAiAssistant\Services\LazyLoadingService;

$lazyService = app(LazyLoadingService::class);

// Register a lazy-loaded resource
$lazyService->registerLazyResource('heavy_model', function() {
    return new ExpensiveAiModel();
}, [
    'ttl' => 3600,  // Cache for 1 hour
    'preload' => false,
    'category' => 'ai_models'
]);

// Get resource (loads only when first accessed)
$model = $lazyService->getResource('heavy_model');

AI Model Lazy Loading

// Register multiple AI models for lazy loading
$lazyService->registerAiModels([
    'gpt-4' => ['type' => 'chat', 'context_size' => 8192],
    'gpt-3.5-turbo' => ['type' => 'chat', 'context_size' => 4096],
    'whisper-1' => ['type' => 'audio', 'languages' => ['en', 'es', 'fr']]
]);

// Register HTTP clients with different configurations
$lazyService->registerHttpClients([
    'standard' => ['timeout' => 30, 'pool_size' => 10],
    'streaming' => ['timeout' => 300, 'stream' => true],
    'batch' => ['timeout' => 600, 'concurrent' => 5]
]);

Performance Metrics

$metrics = $lazyService->getLazyLoadingMetrics();
/*
Returns:
[
    'total_resources' => 15,
    'loaded_resources' => 8,
    'cache_hits' => 45,
    'cache_misses' => 12,
    'average_load_time' => 2.3,
    'memory_saved_mb' => 124.5,
    'cache_hit_rate' => 78.9
]
*/

Metrics Collection

Comprehensive monitoring and analytics for API usage, performance, and costs.

API Monitoring

use CreativeCrafts\LaravelAiAssistant\Services\MetricsCollectionService;

$metricsService = app(MetricsCollectionService::class);

// Automatic recording (handled internally)
// Manual recording for custom operations
$metricsService->recordApiCall('/chat/completions', 1.5, 200, [
    'model' => 'gpt-4',
    'tokens' => 150
]);

$metricsService->recordTokenUsage('chat_completion', 100, 50, 'gpt-4');

Performance Analysis

// Get API performance summary
$performance = $metricsService->getApiPerformanceSummary('/chat/completions', 24);
/*
Returns:
[
    'total_calls' => 1250,
    'average_response_time' => 1.8,
    'success_rate' => 99.2,
    'error_rate' => 0.8,
    'p95_response_time' => 3.2,
    'total_errors' => 10
]
*/

// Get token usage summary
$tokenUsage = $metricsService->getTokenUsageSummary(24);
/*
Returns:
[
    'total_tokens' => 125000,
    'prompt_tokens' => 75000,
    'completion_tokens' => 50000,
    'estimated_cost_usd' => 2.50,
    'by_model' => [
        'gpt-4' => ['tokens' => 50000, 'cost' => 1.00],
        'gpt-3.5-turbo' => ['tokens' => 75000, 'cost' => 0.15]
    ]
]
*/

System Health Monitoring

// System health is recorded automatically
$health = $metricsService->getSystemHealthSummary(1);
/*
Returns:
[
    'status' => 'healthy', // healthy, warning, critical
    'uptime_seconds' => 86400,
    'memory_usage_mb' => 512,
    'cpu_usage_percent' => 15.3,
    'disk_usage_percent' => 68.2,
    'active_connections' => 25,
    'error_rate_percent' => 0.5
]
*/

Security Features

Advanced security controls including API key validation, rate limiting, and request integrity.

API Key Validation

use CreativeCrafts\LaravelAiAssistant\Services\SecurityService;

$securityService = app(SecurityService::class);

// Validate API key format and structure
if ($securityService->validateApiKey($apiKey)) {
    echo "API key is valid";
}

// Validate organization ID
if ($securityService->validateOrganizationId($orgId)) {
    echo "Organization ID is valid";
}

Rate Limiting

// Check rate limit before making API call
$identifier = "user_" . auth()->id();
$canProceed = $securityService->checkRateLimit($identifier, 100, 3600); // 100 requests per hour

if ($canProceed) {
    // Apply rate limiting to operation
    $result = $securityService->applyRateLimit($identifier, function() {
        return AiAssistant::init()->sendChatMessage();
    }, 100, 3600);
} else {
    throw new RateLimitExceededException("Rate limit exceeded");
}

Request Integrity

// Generate request signature
$payload = ['message' => 'Hello AI', 'model' => 'gpt-4'];
$secret = config('app.key');
$timestamp = time();

$signature = $securityService->generateRequestSignature($payload, $secret, $timestamp);

// Verify request signature
$isValid = $securityService->verifyRequestSignature(
    $payload, 
    $signature, 
    $secret, 
    $timestamp, 
    300 // 5 minute tolerance
);

Data Sanitization

// Sanitize sensitive data before logging
$sensitiveData = [
    'api_key' => 'sk-secret123',
    'user_email' => 'user@example.com',
    'message' => 'Hello world',
    'organization' => 'org-secret456'
];

$sanitized = $securityService->sanitizeSensitiveData($sensitiveData, [
    'api_key', 'organization', 'password', 'secret'
]);
/*
Returns:
[
    'api_key' => '***REDACTED***',
    'user_email' => 'user@example.com',
    'message' => 'Hello world',
    'organization' => '***REDACTED***'
]
*/

Performance Optimizations

Memory Management

use CreativeCrafts\LaravelAiAssistant\Services\MemoryMonitoringService;

$memoryService = app(MemoryMonitoringService::class);

// Monitor memory usage during operations
$memoryReport = $memoryService->getMemoryReport();
/*
Returns:
[
    'current_usage_mb' => 45.2,
    'peak_usage_mb' => 67.8,
    'limit_mb' => 256,
    'usage_percent' => 17.7,
    'available_mb' => 210.8
]
*/

// Set memory alerts
$memoryService->setMemoryAlert(200, function($usage) {
    Log::warning("High memory usage detected: {$usage}MB");
});

Caching Strategies

use CreativeCrafts\LaravelAiAssistant\Services\CacheService;

$cacheService = app(CacheService::class);

// Cache API responses
$cacheKey = 'ai_response_' . md5($prompt);
$response = $cacheService->remember($cacheKey, 3600, function() use ($prompt) {
    return AiAssistant::init()->setUserMessage($prompt)->sendChatMessage();
});

// Smart caching with tags
$cacheService->tags(['ai_responses', 'user_123'])->put($cacheKey, $response, 3600);

// Clear related caches
$cacheService->tags(['user_123'])->flush();
Advanced Caching Configuration

Configure caching for optimal performance in your environment variables:

# Enable lazy loading with caching
AI_LAZY_LOADING_ENABLED=true
AI_LAZY_CACHE_DURATION=3600

# Connection pooling for better performance
AI_CONNECTION_POOL_ENABLED=true
AI_MAX_CONNECTIONS=100
AI_MAX_CONNECTIONS_PER_HOST=10

# Memory monitoring
AI_MEMORY_MONITORING_ENABLED=true
AI_MEMORY_THRESHOLD_MB=256
AI_LOG_MEMORY_USAGE=true
Cache Best Practices
// Use appropriate TTL based on content type
$cacheService->cacheResponse('static_content', $response, 86400); // 24 hours
$cacheService->cacheResponse('dynamic_content', $response, 300);  // 5 minutes

// Implement cache warming for frequently accessed data
$cacheService->cacheConfig('popular_prompts', $popularPrompts, 7200);

// Use hierarchical cache keys for better organization
$cacheKey = "ai_response:{$userId}:{$modelName}:" . md5($prompt);

Queue Configuration for Background Jobs

Configure background job processing for better scalability:

Environment Configuration
# Enable background job processing
AI_BACKGROUND_JOBS_ENABLED=true
AI_QUEUE_NAME=ai-assistant
AI_QUEUE_CONNECTION=redis

# Job configuration
AI_JOB_TIMEOUT=300
AI_JOB_RETRY_AFTER=90
AI_JOB_MAX_TRIES=3

# Tool calling execution via queue
AI_TOOL_CALLING_EXECUTOR=queue
AI_TOOL_CALLING_PARALLEL=true
Queue Setup Examples
// Process large operations in background
use CreativeCrafts\LaravelAiAssistant\Jobs\ProcessAiRequestJob;

// Dispatch AI processing to queue
ProcessAiRequestJob::dispatch($requestData)
    ->onQueue(config('ai-assistant.background_jobs.queue'))
    ->delay(now()->addSeconds(5));

// Batch processing for multiple requests
$jobs = collect($requests)->map(function ($request) {
    return new ProcessAiRequestJob($request);
});

Bus::batch($jobs)
    ->then(function (Batch $batch) {
        // All jobs completed successfully
    })
    ->catch(function (Batch $batch, Throwable $e) {
        // First batch job failure
    })
    ->finally(function (Batch $batch) {
        // Batch has finished executing
    })
    ->dispatch();
Redis Queue Configuration
// config/queue.php
'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => env('REDIS_QUEUE', 'default'),
        'retry_after' => 90,
        'block_for' => null,
        'after_commit' => false,
    ],
],

// Dedicated connection for AI Assistant
'ai-assistant-redis' => [
    'driver' => 'redis',
    'connection' => 'ai-assistant',
    'queue' => 'ai-assistant',
    'retry_after' => 300,
    'block_for' => null,
],

Load Testing and Performance Verification

Performance Benchmarking

Run the included performance tests to verify package performance:

# Run performance tests
composer test -- --group=performance

# Run specific performance test
vendor/bin/pest tests/Performance/AssistantServicePerformanceTest.php

# Generate performance report
vendor/bin/pest tests/Performance/ --coverage
Load Testing Setup

Create load testing scenarios for your application:

// tests/Performance/LoadTest.php
use CreativeCrafts\LaravelAiAssistant\AiAssistant;

public function test_concurrent_requests_performance()
{
    $concurrentRequests = 50;
    $promises = [];
    
    $startTime = microtime(true);
    
    for ($i = 0; $i < $concurrentRequests; $i++) {
        $promises[] = AiAssistant::init()
            ->setUserMessage("Test message {$i}")
            ->sendChatMessage();
    }
    
    // Wait for all requests to complete
    $results = collect($promises)->map(fn($promise) => $promise);
    
    $duration = microtime(true) - $startTime;
    $avgResponseTime = $duration / $concurrentRequests;
    
    $this->assertLessThan(5.0, $avgResponseTime, 'Average response time should be under 5 seconds');
}
Production Load Testing

Use tools like Apache Bench or Siege for production load testing:

# Test API endpoint with Apache Bench
ab -n 1000 -c 10 -H "Authorization: Bearer your-token" \
   -p post_data.json -T application/json \
   https://yourapp.com/api/ai-assistant/chat

# Test with Siege
siege -c 20 -t 60s -H "Authorization: Bearer your-token" \
      --content-type="application/json" \
      'https://yourapp.com/api/ai-assistant/chat POST < post_data.json'
Performance Monitoring

Set up comprehensive metrics collection:

# Enable metrics collection
AI_METRICS_ENABLED=true
AI_METRICS_DRIVER=database  # or redis, log
AI_TRACK_RESPONSE_TIMES=true
AI_TRACK_TOKEN_USAGE=true
AI_TRACK_ERROR_RATES=true

# Health checks
AI_HEALTH_CHECKS_ENABLED=true
AI_HEALTH_CHECK_ROUTE_PREFIX=/ai-assistant/health
// Monitor performance metrics
use CreativeCrafts\LaravelAiAssistant\Services\MetricsService;

$metrics = app(MetricsService::class);
$performanceData = $metrics->getPerformanceMetrics();

/*
Returns:
[
    'avg_response_time' => 1.2,
    'total_requests' => 1500,
    'error_rate' => 0.02,
    'token_usage' => [
        'total' => 45000,
        'avg_per_request' => 30
    ],
    'cache_hit_rate' => 0.85
]
*/

Scaling Best Practices

  1. Queue Management: Use dedicated queue workers for AI processing
  2. Connection Pooling: Enable HTTP connection pooling for better throughput
  3. Caching Strategy: Implement multi-layer caching (Redis + Application)
  4. Resource Monitoring: Set up alerts for memory and performance thresholds
  5. Load Balancing: Distribute requests across multiple application instances
  6. Rate Limiting: Implement appropriate rate limiting for API endpoints

Error Handling & Exceptions

The package includes 8+ custom exception types for precise error handling:

Exception Types

use CreativeCrafts\LaravelAiAssistant\Exceptions\{
    ApiResponseValidationException,
    ConfigurationValidationException,
    CreateNewAssistantException,
    FileOperationException,
    InvalidApiKeyException,
    MaxRetryAttemptsExceededException,
    MissingRequiredParameterException,
    ThreadExecutionTimeoutException
};

Exception Handling Examples

try {
    $assistant = AiAssistant::init()
        ->setModelName('gpt-4')
        ->sendChatMessage();
} catch (InvalidApiKeyException $e) {
    Log::error('Invalid API key provided', ['error' => $e->getMessage()]);
    return response()->json(['error' => 'Authentication failed'], 401);
    
} catch (MaxRetryAttemptsExceededException $e) {
    Log::error('Maximum retry attempts exceeded', ['error' => $e->getMessage()]);
    return response()->json(['error' => 'Service temporarily unavailable'], 503);
    
} catch (ThreadExecutionTimeoutException $e) {
    Log::error('Thread execution timeout', ['error' => $e->getMessage()]);
    return response()->json(['error' => 'Request timeout'], 408);
    
} catch (ApiResponseValidationException $e) {
    Log::error('API response validation failed', ['error' => $e->getMessage()]);
    return response()->json(['error' => 'Invalid response from AI service'], 502);
    
} catch (FileOperationException $e) {
    Log::error('File operation failed', ['error' => $e->getMessage()]);
    return response()->json(['error' => 'File processing error'], 422);
}

Configuration Validation

try {
    // Configuration is validated automatically during service provider boot
    $config = config('ai-assistant');
} catch (ConfigurationValidationException $e) {
    // Handle configuration errors
    Log::critical('AI Assistant configuration invalid', [
        'error' => $e->getMessage(),
        'config' => $e->getConfigurationErrors()
    ]);
}

Best Practices

Performance Best Practices

  1. Use Streaming for Real-time Applications

    // Enable streaming for real-time chat interfaces
    $streamingService = app(StreamingService::class);
    foreach ($streamingService->processStream($stream, 'chat_completion') as $chunk) {
        broadcast(new MessageChunkEvent($chunk));
    }
  2. Queue Long-running Operations

    // Queue operations that take more than 30 seconds
    $jobService = app(BackgroundJobService::class);
    $jobId = $jobService->queueLongRunningOperation('bulk_processing', $data);
  3. Implement Lazy Loading for Resources

    // Register expensive resources for lazy loading
    $lazyService = app(LazyLoadingService::class);
    $lazyService->registerLazyResource('expensive_model', $initializer, ['ttl' => 3600]);

Security Best Practices

  1. Always Validate API Keys

    $securityService = app(SecurityService::class);
    if (!$securityService->validateApiKey($apiKey)) {
        throw new InvalidApiKeyException('Invalid API key format');
    }
  2. Implement Rate Limiting

    // Implement per-user rate limiting
    $canProceed = $securityService->checkRateLimit("user_{$userId}", 100, 3600);
  3. Sanitize Sensitive Data in Logs

    $sanitizedData = $securityService->sanitizeSensitiveData($data, [
        'api_key', 'organization', 'password'
    ]);
    Log::info('API call made', $sanitizedData);

Monitoring Best Practices

  1. Enable Comprehensive Metrics

    // Configure in config/ai-assistant.php
    'metrics' => [
        'enabled' => true,
        'track_response_times' => true,
        'track_token_usage' => true,
        'track_error_rates' => true,
    ]
  2. Set Up Health Monitoring

    $metricsService = app(MetricsCollectionService::class);
    $health = $metricsService->getSystemHealthSummary(1);
    
    if ($health['status'] === 'critical') {
        // Alert administrators
        Mail::to('admin@example.com')->send(new SystemHealthAlert($health));
    }
  3. Monitor Token Usage and Costs

    $tokenUsage = $metricsService->getTokenUsageSummary(24);
    if ($tokenUsage['estimated_cost_usd'] > $dailyBudget) {
        // Implement cost controls
        Log::warning('Daily AI budget exceeded', $tokenUsage);
    }

Cookbook

Chat with JSON output

use CreativeCrafts\LaravelAiAssistant\Facades\Ai;

$schema = [
    '$schema' => 'https://json-schema.org/draft/2020-12/schema',
    'type' => 'object',
    'properties' => [
        'title' => ['type' => 'string'],
        'bullets' => ['type' => 'array', 'items' => ['type' => 'string']],
    ],
    'required' => ['title', 'bullets'],
    'additionalProperties' => false,
];

$response = Ai::chat('Summarize SOLID principles as JSON')
    ->setResponseFormatJsonSchema($schema, 'answer')
    ->send();

// Normalized text if the model returns textual content
$textOutput = $response->content;

// Or inspect the raw normalized envelope data as an array
$raw = $response->toArray();

Tips:

  • Prefer Ai::chat() for modern Responses + Conversations flows.
  • setToolChoice('none') if you want pure JSON without tool calls.

Function calling with a Laravel job executor (queue)

This recipe demonstrates enabling queued function (tool) execution. The executor dispatches tool calls as jobs and returns an inline result for determinism while the job runs in your queue.

  1. Configure the executor to queue
  • In .env:
AI_TOOL_CALLING_EXECUTOR=queue
AI_QUEUE_CONNECTION=redis   # or database, sqs, etc.
AI_QUEUE_NAME=ai-tools
  • Or dynamically in code (e.g., for tests or one-off scripts):
config([
    'ai-assistant.tool_calling.executor' => 'queue',  // 'sync' | 'queue'
    'ai-assistant.background_jobs.queue' => 'ai-tools',
    'queue.default' => env('AI_QUEUE_CONNECTION', 'sync'),
]);
  1. Define a callable tool and let the assistant invoke it
use CreativeCrafts\LaravelAiAssistant\AiAssistant;

$assistant = AiAssistant::init()
    ->startConversation()
    ->includeFunctionCallTool(
        'getWeather',
        'Gets current weather for a city',
        [
            'type' => 'object',
            'properties' => [ 'city' => ['type' => 'string'] ],
            'required' => ['city'],
            'additionalProperties' => false,
        ],
        isStrict: true
    )
    ->setToolChoice('auto')
    ->setUserMessage('What is the weather in Paris?');

$result = $assistant->sendChatMessage();

// If the model requested a tool call, you can continue the turn with tool results
$toolCalls = $result['toolCalls'] ?? [];
if ($toolCalls !== []) {
    $call = $toolCalls[0];

    // Execute your domain logic (this can also be in a Job handler for full control)
    $weather = [ 'temp_c' => 21, 'condition' => 'Cloudy' ];

    $followUp = AiAssistant::init()
        ->useConversation($result['conversationId'])
        ->continueWithToolResults([
            [
                'tool_call_id' => $call['id'],
                'output' => json_encode($weather),
            ],
        ]);
}

Notes:

  • With AI_TOOL_CALLING_EXECUTOR=queue, the package dispatches ExecuteToolCallJob internally (requires a working queue).
  • For local development, set executor to sync to avoid queue setup: AI_TOOL_CALLING_EXECUTOR=sync.
  • Related config: AI_TOOL_CALLING_MAX_ROUNDS, AI_TOOL_CALLING_PARALLEL.

Troubleshooting:

  • If jobs don’t run, verify your queue worker and connection settings.
  • Check logs: the executor logs dispatch events with correlation IDs.

Attach files and enable file search (vector stores)

use CreativeCrafts\LaravelAiAssistant\AiAssistant;

$result = AiAssistant::init()
    ->startConversation()
    ->includeFileSearchTool(['vector_store_789'])  // pass vector store IDs
    ->attachFilesToTurn(['file_abc123'])           // optional file IDs already uploaded
    ->setUserMessage('Answer using the attached policy file and related knowledge base.')
    ->sendChatMessage();

Variants:

  • Disable automatic file_search while still attaching files:
$result = AiAssistant::init()
    ->startConversation()
    ->useFileSearch(false)
    ->attachFilesToTurn(['file_abc123'])
    ->setUserMessage('Do not use RAG; answer generally.')
    ->sendChatMessage();

📊 Performance Benchmarks

Laravel AI Assistant is optimized for enterprise-scale applications. Below are performance metrics and optimization recommendations:

Benchmark Results

Response Times (Average)

  • Simple Chat Message: ~800ms-1.2s (depends on model and complexity)
  • Streaming Response: First token ~400ms, subsequent tokens ~50-100ms
  • File Processing: ~2-5s per MB (varies by file type)
  • Background Jobs: Queue dispatch ~50ms, processing time varies

Throughput (With Connection Pooling)

  • Concurrent Requests: Up to 100 simultaneous connections
  • Requests per Second: 50-150 RPS (depends on response complexity)
  • Memory Usage: ~10-50MB per active request
  • Connection Reuse: 80-90% efficiency with pooling enabled

Performance Optimization Tips

1. Enable Connection Pooling

AI_CONNECTION_POOL_ENABLED=true
AI_MAX_CONNECTIONS=100
AI_MAX_CONNECTIONS_PER_HOST=10

Impact: 30-50% improvement in response times for multiple requests

2. Use Background Jobs for Long Operations

AI_BACKGROUND_JOBS_ENABLED=true
AI_QUEUE_NAME=ai-assistant

Impact: Prevents blocking the main thread, improves user experience

3. Optimize Streaming Configuration

AI_STREAMING_ENABLED=true
AI_STREAMING_BUFFER_SIZE=8192
AI_STREAMING_CHUNK_SIZE=1024

Impact: 60-80% faster perceived response times for long responses

4. Configure Memory Monitoring

AI_MEMORY_MONITORING_ENABLED=true
AI_MEMORY_THRESHOLD_MB=256

Impact: Prevents memory exhaustion, maintains system stability

5. Enable Metrics Collection

AI_METRICS_ENABLED=true
AI_METRICS_DRIVER=redis  # or database

Impact: Provides insights for further optimization

Model-Specific Performance

Model Avg Response Time Tokens/Sec Best Use Case
gpt-5 1.2s 80-120 Complex reasoning, latest features
gpt-4o 0.8s 120-180 Balanced performance and capability
gpt-4o-mini 0.4s 200-300 Simple tasks, high throughput

Scaling Recommendations

Small Applications (< 1,000 requests/day)

AI_CONNECTION_POOL_ENABLED=false
AI_BACKGROUND_JOBS_ENABLED=false
AI_METRICS_ENABLED=false

Medium Applications (1,000 - 50,000 requests/day)

AI_CONNECTION_POOL_ENABLED=true
AI_MAX_CONNECTIONS=50
AI_BACKGROUND_JOBS_ENABLED=true
AI_METRICS_ENABLED=true
AI_METRICS_DRIVER=database

Large Applications (> 50,000 requests/day)

AI_CONNECTION_POOL_ENABLED=true
AI_MAX_CONNECTIONS=100
AI_BACKGROUND_JOBS_ENABLED=true
AI_QUEUE_CONNECTION=redis
AI_METRICS_ENABLED=true
AI_METRICS_DRIVER=redis
AI_LAZY_LOADING_ENABLED=true

Monitoring & Profiling

The package provides built-in performance monitoring:

use CreativeCrafts\LaravelAiAssistant\Services\Metrics;

// Get performance metrics
$metrics = app(Metrics::class);
$stats = $metrics->getStats();

echo "Average Response Time: " . $stats['avg_response_time'] . "ms\n";
echo "Total Requests: " . $stats['total_requests'] . "\n";
echo "Error Rate: " . ($stats['error_rate'] * 100) . "%\n";

Examples

Example 1: Building a Chat Interface with Streaming

use CreativeCrafts\LaravelAiAssistant\AiAssistant;
use CreativeCrafts\LaravelAiAssistant\Services\StreamingService;

class ChatController extends Controller
{
    public function streamChat(Request $request)
    {
        $streamingService = app(StreamingService::class);
        
        // Validate and rate limit
        $securityService = app(SecurityService::class);
        $userId = auth()->id();
        
        if (!$securityService->checkRateLimit("chat_user_{$userId}", 50, 3600)) {
            return response()->json(['error' => 'Rate limit exceeded'], 429);
        }
        
        // Create streaming response
        return response()->stream(function() use ($request, $streamingService) {
            $assistant = AiAssistant::init()
                ->setModelName('gpt-4')
                ->adjustTemperature(0.7)
                ->setUserMessage($request->input('message'));
            
            $stream = $assistant->getStreamingResponse();
            
            foreach ($streamingService->processStream($stream, 'chat_completion') as $chunk) {
                echo "data: " . json_encode(['content' => $chunk['content']]) . "\n\n";
                ob_flush();
                flush();
            }
        }, 200, [
            'Content-Type' => 'text/event-stream',
            'Cache-Control' => 'no-cache',
        ]);
    }
}

Example 2: Background Processing with Progress Tracking

use CreativeCrafts\LaravelAiAssistant\Services\BackgroundJobService;

class DocumentProcessor
{
    public function processBulkDocuments(array $documents)
    {
        $jobService = app(BackgroundJobService::class);
        
        // Queue batch processing
        $jobIds = $jobService->queueBatchOperation('process_document', 
            array_map(fn($doc) => ['path' => $doc['path'], 'format' => $doc['format']], $documents),
            5, // Process 5 at a time
            [
                'queue' => 'document-processing',
                'timeout' => 600,
                'max_tries' => 3
            ]
        );
        
        return [
            'message' => 'Documents queued for processing',
            'job_ids' => $jobIds,
            'total_documents' => count($documents)
        ];
    }
    
    public function getProcessingStatus(array $jobIds)
    {
        $jobService = app(BackgroundJobService::class);
        $statuses = [];
        
        foreach ($jobIds as $jobId) {
            $statuses[$jobId] = $jobService->getJobStatus($jobId);
        }
        
        $completed = collect($statuses)->where('status', 'completed')->count();
        $total = count($statuses);
        
        return [
            'overall_progress' => ($completed / $total) * 100,
            'job_statuses' => $statuses,
            'queue_stats' => $jobService->getQueueStatistics()
        ];
    }
}

Example 3: Advanced AI Assistant with Custom Tools

use CreativeCrafts\LaravelAiAssistant\AiAssistant;

class AdvancedAiService
{
    public function createSmartAssistant()
    {
        return AiAssistant::init()
            ->setModelName('gpt-4')
            ->adjustTemperature(0.3)
            ->setAssistantName('Smart Business Assistant')
            ->setAssistantDescription('An AI assistant specialized in business operations')
            ->setInstructions('You are a business expert. Provide clear, actionable advice.')
            
            // Add code interpreter for data analysis
            ->includeCodeInterpreterTool(['file_12345'])
            
            // Add file search for document retrieval
            ->includeFileSearchTool(['vector_store_789'])
            
            // Add custom business calculation functions
            ->includeFunctionCallTool(
                'calculate_roi',
                'Calculate return on investment',
                [
                    'initial_investment' => 'number',
                    'final_value' => 'number',
                    'time_period_years' => 'number'
                ],
                isStrict: true,
                requiredParameters: ['initial_investment', 'final_value', 'time_period_years']
            )
            
            // Add inventory management function
            ->includeFunctionCallTool(
                'check_inventory',
                'Check product inventory levels',
                [
                    'product_id' => 'string',
                    'location' => 'string'
                ],
                isStrict: true,
                requiredParameters: ['product_id']
            )
            
            ->create();
    }
    
    public function processBusinessQuery($assistantId, $query)
    {
        // Use lazy loading for the assistant interaction
        $lazyService = app(LazyLoadingService::class);
        
        $result = $lazyService->getResource('business_assistant_' . $assistantId, function() use ($assistantId, $query) {
            return AiAssistant::init()
                ->setAssistantId($assistantId)
                ->createTask()
                ->askQuestion($query)
                ->process()
                ->response();
        });
        
        return $result;
    }
}

Example 4: Comprehensive Monitoring Dashboard

use CreativeCrafts\LaravelAiAssistant\Services\MetricsCollectionService;

class AiDashboardController extends Controller
{
    public function getDashboardData()
    {
        $metricsService = app(MetricsCollectionService::class);
        $hours = 24; // Last 24 hours
        
        return [
            'api_performance' => [
                'chat_completions' => $metricsService->getApiPerformanceSummary('/chat/completions', $hours),
                'audio_transcriptions' => $metricsService->getApiPerformanceSummary('/audio/transcriptions', $hours),
                'assistants' => $metricsService->getApiPerformanceSummary('/assistants', $hours),
            ],
            
            'token_usage' => $metricsService->getTokenUsageSummary($hours),
            'system_health' => $metricsService->getSystemHealthSummary($hours),
            
            'streaming_metrics' => app(StreamingService::class)->getStreamingMetrics(),
            'lazy_loading_metrics' => app(LazyLoadingService::class)->getLazyLoadingMetrics(),
            'job_queue_stats' => app(BackgroundJobService::class)->getQueueStatistics(),
            
            'cost_analysis' => [
                'estimated_daily_cost' => $metricsService->calculateEstimatedCost($hours),
                'cost_by_model' => $metricsService->getTokenUsageByModel($hours),
                'cost_by_operation' => $metricsService->getTokenUsageByOperation($hours),
            ]
        ];
    }
}

Environment Variables

Add the following to your .env file:

# Required
OPENAI_API_KEY=your_openai_api_key
OPENAI_ORGANIZATION=your_organization_id
OPENAI_CHAT_MODEL=gpt-3.5-turbo

# Persistence
AI_ASSISTANT_PERSISTENCE_DRIVER=memory # or 'eloquent'

# Optional advanced configuration
AI_ASSISTANT_STREAMING_ENABLED=true
AI_ASSISTANT_JOBS_ENABLED=true
AI_ASSISTANT_METRICS_ENABLED=true
AI_ASSISTANT_SECURITY_RATE_LIMITING=true
AI_ASSISTANT_LAZY_LOADING_ENABLED=true

Notes:

  • If you set AI_ASSISTANT_PERSISTENCE_DRIVER=eloquent, publish and run the package migrations:
php artisan vendor:publish --tag="ai-assistant-migrations"
php artisan migrate
  • You can optionally publish Eloquent model stubs for customization:
php artisan vendor:publish --tag="ai-assistant-models"
  • With hasMigrations([...]), the package can also load migrations without publishing; publish only if you need to customize.

đź”§ Troubleshooting

Common issues and their solutions when working with Laravel AI Assistant:

Installation & Configuration Issues

Issue: "Class 'OpenAI\Client' not found"

Solution:

composer require openai-php/client
composer dump-autoload

Issue: "OPENAI_API_KEY environment variable is required"

Solution:

  1. Add your API key to .env:
    OPENAI_API_KEY=sk-your-actual-api-key-here
  2. Clear config cache:
    php artisan config:clear

Issue: Service provider not loading

Solution:

# Clear all caches
php artisan config:clear
php artisan cache:clear
php artisan route:clear

# Re-discover packages
composer dump-autoload

Runtime Issues

Issue: "Connection timeout" errors

Symptoms: Requests taking too long or timing out Solutions:

  1. Increase timeout values:
    AI_STREAMING_TIMEOUT=300
    AI_CONNECTION_TIMEOUT=60
  2. Enable connection pooling:
    AI_CONNECTION_POOL_ENABLED=true

Issue: High memory usage

Symptoms: Memory exhaustion during large operations Solutions:

  1. Enable memory monitoring:
    AI_MEMORY_MONITORING_ENABLED=true
    AI_MEMORY_THRESHOLD_MB=256
  2. Use background jobs for large operations:
    AI_BACKGROUND_JOBS_ENABLED=true

Issue: "Rate limit exceeded" errors

Symptoms: 429 HTTP status codes from OpenAI Solutions:

  1. Enable retry mechanism:
    AI_RESPONSES_RETRY_ENABLED=true
    AI_RESPONSES_RETRY_MAX_ATTEMPTS=3
  2. Implement request queuing:
    AI_BACKGROUND_JOBS_ENABLED=true
    AI_QUEUE_NAME=ai-assistant

Database & Persistence Issues

Issue: "Table doesn't exist" when using Eloquent persistence

Solution:

php artisan vendor:publish --tag="laravel-ai-assistant-migrations"
php artisan migrate

Issue: Eloquent models not found

Solution:

php artisan vendor:publish --tag="ai-assistant-models"

Performance Issues

Issue: Slow response times

Diagnostic Steps:

  1. Check your model selection:
    OPENAI_CHAT_MODEL=gpt-4o-mini  # Faster than gpt-5
  2. Enable streaming for better perceived performance:
    AI_STREAMING_ENABLED=true
  3. Use connection pooling:
    AI_CONNECTION_POOL_ENABLED=true
    AI_MAX_CONNECTIONS=50

Issue: Queue jobs not processing

Solution:

  1. Ensure queue worker is running:
    php artisan queue:work --queue=ai-assistant
  2. Check queue configuration:
    AI_QUEUE_CONNECTION=redis  # or database
    AI_QUEUE_NAME=ai-assistant

API & Authentication Issues

Issue: "Invalid API key" errors

Solutions:

  1. Verify your API key format (starts with sk-):
    OPENAI_API_KEY=sk-your-48-character-key-here
  2. Check API key permissions in OpenAI dashboard
  3. Ensure no extra spaces in .env file

Issue: Organization access errors

Solution:

OPENAI_ORGANIZATION=org-your-organization-id

Streaming Issues

Issue: Streaming responses not working

Solutions:

  1. Check if streaming is enabled:
    AI_STREAMING_ENABLED=true
  2. Verify buffer settings:
    AI_STREAMING_BUFFER_SIZE=8192
    AI_STREAMING_CHUNK_SIZE=1024
  3. Ensure proper headers in your frontend:
    const headers = {
      "Accept": "text/event-stream",
      "Cache-Control": "no-cache"
    };

Development & Testing Issues

Issue: Tests failing with API key errors

Solution: Use the test configuration override:

// In your test
config(['ai-assistant.api_key' => 'test_key_123']);
config(['ai-assistant.mock_responses' => true]);

Issue: Mock responses not working

Solution:

AI_ASSISTANT_MOCK=true

Debug Mode

Enable debug logging for troubleshooting:

LOG_LEVEL=debug
AI_METRICS_ENABLED=true
AI_LOG_MEMORY_USAGE=true

Then check your Laravel logs:

tail -f storage/logs/laravel.log

Getting Help

If you're still experiencing issues:

  1. Check the logs: Laravel logs often contain detailed error information
  2. Review configuration: Compare your config with the defaults
  3. Test with minimal setup: Try with basic configuration first
  4. Check GitHub issues: Search existing issues for similar problems
  5. Create an issue: Provide detailed error messages and configuration

Useful Commands for Debugging

# Check package installation
composer show creativecrafts/laravel-ai-assistant

# Verify configuration
php artisan config:show ai-assistant

# Test API connectivity
php artisan tinker
>>> app(\CreativeCrafts\LaravelAiAssistant\Services\AssistantService::class);

# Clear all caches
php artisan optimize:clear

Testing

Bootstrap: tests/Pest.php applies the shared TestCase across the test suite. The shared tests/TestCase.php configures:

  • database.default = testing
  • ai-assistant.api_key = 'test_key_123' (bypasses ServiceProvider OPENAI_API_KEY validation in tests)

If you author tests that boot the app outside the shared TestCase, set this config key manually inside the test or provide OPENAI_API_KEY in env to avoid ConfigurationValidationException during package boot.

The package has 100% code and mutation test coverage. Run tests using:

# Run all tests
composer test

# Run tests with coverage
composer test-coverage

# Run mutation tests
composer test-mutation

# Run static analysis
composer analyse

# Run code style checks
composer format

Compatibility

  • PHP: 8.1, 8.2, 8.3+
  • Laravel: 9.x, 10.x, 11.x
  • OpenAI API: Compatible with latest API versions as of December 2024

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details on how to contribute to this package.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

Responses + Conversations (New API)

This package now uses OpenAI's Responses + Conversations APIs under the hood. Below are copy‑paste examples that match the current fluent methods and payload shapes.

Quickstart: Start and use a conversation

use CreativeCrafts\LaravelAiAssistant\AiAssistant;

$assistant = AiAssistant::init()
    ->startConversation(['tenant_id' => 'acme-1'])
    ->instructions('You are a helpful assistant. Keep answers concise.')
    ->setModelName('gpt-4o')
    ->setUserMessage('What are three benefits of unit testing?');

$result = $assistant->sendChatMessage();

// Result fields
$responseId = $result['responseId'];
$conversationId = $result['conversationId'];
$text = $result['messages'];

To continue the same conversation:

$assistant = AiAssistant::init()
    ->useConversation($conversationId)
    ->setUserMessage('Give me a short code example in PHP.');

$next = $assistant->sendChatMessage();

Instructions (system/developer persona)

$assistant = AiAssistant::init()
    ->startConversation()
    ->instructions('You are a senior PHP engineer. Always explain the why.');

Tool choice and response format (json_schema)

$schema = [
    '$schema' => 'https://json-schema.org/draft/2020-12/schema',
    'type' => 'object',
    'properties' => [
        'title' => ['type' => 'string'],
        'bullets' => ['type' => 'array', 'items' => ['type' => 'string']],
    ],
    'required' => ['title','bullets'],
    'additionalProperties' => false,
];

$assistant = AiAssistant::init()
    ->startConversation()
    ->setToolChoice('auto') // 'auto' | 'required' | 'none' | ['type' => 'function', 'name' => '...']
    ->setResponseFormatJsonSchema($schema, 'answer')
    ->setUserMessage('Summarize SOLID principles as JSON.');

$result = $assistant->sendChatMessage();

File search and attachments

$assistant = AiAssistant::init()
    ->startConversation()
    ->includeFileSearchTool() // explicitly include file_search tool
    ->attachFilesToTurn(['file_abc123']) // file IDs previously uploaded
    ->setUserMessage('Answer using the attached policy file.');

$result = $assistant->sendChatMessage();

Disable auto file_search insertion if you want to pass file_ids but avoid the tool:

$assistant = AiAssistant::init()
    ->startConversation()
    ->useFileSearch(false)
    ->attachFilesToTurn(['file_abc123'])
    ->setUserMessage('Do not use RAG; answer generally.');

$result = $assistant->sendChatMessage();

Images: from file and by URL

// Local file
$assistant = AiAssistant::init()
    ->startConversation()
    ->addImageFromFile(storage_path('app/public/photo.jpg'))
    ->setUserMessage('Describe this image in one sentence.');

$res1 = $assistant->sendChatMessage();

// Remote URL
$res2 = AiAssistant::init()
    ->startConversation()
    ->addImageFromUrl('https://example.com/cat.jpg')
    ->setUserMessage('What breed is this cat?')
    ->sendChatMessage();

Streaming with onEvent and shouldStop

$assistant = AiAssistant::init()
    ->startConversation()
    ->setUserMessage('Stream a limerick about Laravel.');

$onEvent = function(array $evt) {
    // evt example: ['type' => 'response.output_text.delta', 'data' => [...], 'isFinal' => false]
    if (($evt['type'] ?? '') === 'response.output_text.delta') {
        echo $evt['data']['delta'] ?? '';
    }
};

$shouldStop = function() {
    // Return true to stop early (e.g., client disconnected)
    return false;
};

foreach ($assistant->streamChatMessage($onEvent, $shouldStop) as $event) {
    if (!empty($event['isFinal'])) {
        // completed/failed
    }
}

Cancel an in‑flight response

// If you captured a response ID to cancel later:
AiAssistant::init()->cancelResponse($responseId);

Continue a turn with tool results

$first = AiAssistant::init()
    ->startConversation()
    ->includeFunctionCallTool(
        'getWeather',
        'Gets weather by city',
        [
            'type' => 'object',
            'properties' => ['city' => ['type' => 'string']],
            'required' => ['city']
        ],
        true
    )
    ->setToolChoice('auto')
    ->setUserMessage('What is the weather in Paris?')
    ->sendChatMessage();

$toolCalls = $first['toolCalls'] ?? [];
if ($toolCalls !== []) {
    $call = $toolCalls[0];
    $resultPayload = [
        [
            'tool_call_id' => $call['id'],
            'output' => json_encode(['temp_c' => 21, 'condition' => 'Cloudy']),
        ],
    ];

    $followUp = AiAssistant::init()
        ->useConversation($first['conversationId'])
        ->continueWithToolResults($resultPayload);
}

Deprecation notes (legacy Assistants/Threads/Runs)

The following legacy methods are deprecated. Use the new replacements:

  • createThread(), writeMessage(), runMessageThread(), listMessages() → startConversation(), sendChatMessage()/streamChatMessage(), and AssistantService::listConversationItems().
  • createAssistant/getAssistantViaId → Prefer local config + per‑turn instructions via instructions().

See docs/Migrate_from_AssistantAPI_to_ResponseAPI.md for the complete migration guide.

QA checklist for examples

  • Configured OPENAI_API_KEY and default model in config/ai-assistant.php
  • Confirmed conversationId is returned and reused across turns
  • Verified streaming events print deltas and respect early stop
  • Validated tool_call flow with continueWithToolResults()
  • Confirmed cancelResponse() works with an in‑flight response ID
  • Verified addImageFromFile/addImageFromUrl block shapes in payload
  • Checked file_search toggles based on includeFileSearchTool()/useFileSearch(false)

Additional Documentation

  • Architecture Overview: docs/ARCHITECTURE.md
  • Code Map: docs/CODEMAP.md
  • Migration Guide: docs/Migrate_from_AssistantAPI_to_ResponseAPI.md
  • Tests Guide: tests/README.md
  • Contributing: CONTRIBUTING.md

Migration Guide (2.0)

This release introduces a unified, typed, Laravel-native API while preserving backwards compatibility. Here’s how to migrate gradually.

Key goals

  • Prefer Ai::chat() entrypoint and the ChatSession for discoverability and strong typing.
  • Keep existing code working, but note deprecations on array-returning methods.

Recommended new entrypoint

use CreativeCrafts\LaravelAiAssistant\Facades\Ai;

// Simple, typed chat turn
$response = Ai::chat('Help me compare X and Y')
    ->instructions('You are a product assistant')
    ->setResponseFormatJsonSchema([
        'type' => 'object',
        'properties' => [ 'verdict' => ['type' => 'string'] ],
    ])
    ->send(); // returns ChatResponseDto

$text = $response->content;           // normalized content when available
$raw  = $response->toArray();         // raw normalized envelope array if needed

// Streaming (typed events via ChatSession::stream or text chunks via streamText)
foreach (Ai::chat('stream me')->stream() as $event) {
    // $event is StreamingEventDto
}

Files and Tools helpers

// Files helper mirrors AiAssistant capabilities
Ai::chat('Explain these docs')
    ->files()->attachFileReference('file_123', useFileSearch: true)
    ->tools()->includeFileSearchTool()
    ->send();

Backwards compatibility and deprecations

  • AiAssistant::sendChatMessage(): array is deprecated. Use one of:
    • Ai::chat()->send() which returns ChatResponseDto, or
    • AiAssistant::sendChatMessageDto(): ChatResponseDto, or
    • AiAssistant::sendChatMessageEnvelope(): ResponseEnvelope
  • AiAssistant::continueWithToolResults(array): array is deprecated. Use:
    • Ai::chat()->continueWithToolResults($results) → ChatResponseDto, or
    • AiAssistant::continueWithToolResultsDto()/continueWithToolResultsEnvelope()
  • AiAssistant::reply(?string): array is deprecated. Use:
    • Ai::chat($message)->send() or Ai::chat()->setUserMessage($message)->send()
  • Assistant::sendChatMessage(): array is deprecated. Use:
    • Assistant::sendChatMessageDto(): ChatResponseDto, or
    • Ai::chat() for the new fluent chat entrypoint

Why DTOs?

  • ChatResponseDto provides a stable, typed surface while preserving access to the underlying normalized array via toArray().
  • StreamingEventDto provides a consistent event shape for streaming.
  • ResponseEnvelope represents the normalized Responses API envelope when you need full fidelity.

Minimal migration examples

// Old
$assistant = new \CreativeCrafts\LaravelAiAssistant\AiAssistant('Help me');
$result = $assistant->sendChatMessage(); // array

// New (preferred)
use CreativeCrafts\LaravelAiAssistant\Facades\Ai;
$dto = Ai::chat('Help me')->send();      // ChatResponseDto

// Or typed via AiAssistant (incremental migration)
$assistant = new \CreativeCrafts\LaravelAiAssistant\AiAssistant('Help me');
$dto = $assistant->sendChatMessageDto(); // ChatResponseDto

Notes

  • All deprecated methods remain functional in 2.x for BC but will be removed in a future major release. Update at your convenience.
  • The new API follows Laravel conventions (facades + fluent builders) and improves discoverability (tools(), files()).
  • Tests and fakes continue to work. For unit tests, prefer asserting on DTOs.