Skip to content

Instantly share code, notes, and snippets.

@garyblankenship
Created March 16, 2025 15:38
Show Gist options
  • Save garyblankenship/a73a503e5034afecb227790f6f866181 to your computer and use it in GitHub Desktop.
Save garyblankenship/a73a503e5034afecb227790f6f866181 to your computer and use it in GitHub Desktop.
Usage with Laravel and Prism

Laravel Typesafe AI

Transform your Laravel application with typesafe AI integration

Build reliable AI-powered features that deliver consistent, predictable results. Our Laravel Typesafe AI pattern combines the power of modern Large Language Models with the safety and predictability of strongly-typed responses.

Elegant Implementation, Powerful Results

// Simple, fluent interface
$result = app(TextAnalysisService::class)
    ->analyzeSentiment($userComment);

// Type-safe response with IDE autocompletion
echo "Sentiment: {$result->sentiment}, Score: {$result->score}";

// Strongly-typed data with helper methods
if ($result->isPositive() && $result->score > 80) {
    // Handle extremely positive feedback
}

Seamless Integration

Add AI capabilities to your Laravel application with minimal effort:

// In your controller
public function analyzeComment(Request $request, CommentAnalysisService $service)
{
    $validated = $request->validate([
        'comment' => 'required|string|min:10',
    ]);
    
    $analysis = $service->analyze($validated['comment']);
    
    return response()->json([
        'sentiment' => $analysis->sentiment,
        'topics' => $analysis->topics,
        'keywords' => $analysis->keywords,
        'toxicity' => $analysis->toxicityLevel,
    ]);
}

Complete Type Safety

Define exactly what you expect from the AI response:

// Define a schema for your AI response
public static function productDescriptionSchema(): ObjectSchema
{
    return new ObjectSchema(
        name: 'productDescription',
        description: 'A product description generator',
        properties: [
            new StringSchema('headline', 'Attention-grabbing headline'),
            new StringSchema('shortDescription', 'Short product description'),
            new ArraySchema('features', 'Product features', 
                new StringSchema('feature', 'A product feature')),
            new StringSchema('callToAction', 'Call to action text'),
        ],
        requiredFields: ['headline', 'shortDescription', 'features', 'callToAction']
    );
}

// Create a matching DTO
final readonly class ProductDescriptionData extends BaseData
{
    public function __construct(
        public string $headline,
        public string $shortDescription,
        public array $features,
        public string $callToAction,
    ) {}
    
    // Helper methods for common operations
    public function toHtml(): string
    {
        $featuresList = implode('', array_map(
            fn($feature) => "<li>{$feature}</li>", 
            $this->features
        ));
        
        return <<<HTML
            <div class="product-description">
                <h2>{$this->headline}</h2>
                <p>{$this->shortDescription}</p>
                <ul>{$featuresList}</ul>
                <div class="cta">{$this->callToAction}</div>
            </div>
        HTML;
    }
}

Real-World Applications

Content Moderation

$comments = Comment::pending()->get();
$moderationService = app(ContentModerationService::class);

foreach ($comments as $comment) {
    $analysis = $moderationService->analyze($comment->content);
    
    if ($analysis->isToxic()) {
        $comment->status = 'rejected';
        $comment->rejection_reason = "Toxicity level: {$analysis->toxicityLevel}";
    } else {
        $comment->status = 'approved';
    }
    
    $comment->save();
}

Smart Email Classification

$email = Email::find($id);
$analysis = app(EmailAnalysisService::class)->analyze($email->body);

$email->update([
    'category' => $analysis->category,
    'priority' => $analysis->priority,
    'sentiment' => $analysis->sentiment,
    'auto_tags' => $analysis->suggestedTags,
]);

if ($analysis->requiresImmediate) {
    NotificationJob::dispatch($email);
}

Product Description Generator

$product = Product::find($id);

$description = app(ProductCopyService::class)->generateDescription(
    product: $product,
    audience: 'tech-savvy professionals',
    tone: 'professional'
);

return view('products.description', [
    'product' => $product,
    'headline' => $description->headline,
    'description' => $description->shortDescription,
    'features' => $description->features,
    'callToAction' => $description->callToAction,
]);

Multi-language Support

$translationService = app(TranslationService::class);

$languages = ['es', 'fr', 'de', 'it', 'nl'];

foreach ($languages as $lang) {
    $translation = $translationService->translate(
        text: $article->content,
        sourceLanguage: 'en',
        targetLanguage: $lang
    );
    
    ArticleTranslation::create([
        'article_id' => $article->id,
        'language' => $lang,
        'title' => $translation->title,
        'content' => $translation->content,
        'meta_description' => $translation->metaDescription,
    ]);
}

Batch Processing with Artisan Commands

// Process comments in bulk
php artisan comments:analyze --file=storage/comments.json --output=analysis.json

// Generate product descriptions
php artisan products:generate-descriptions --category=electronics

// Translate content
php artisan content:translate --source=en --targets=es,fr,de

Compatible with FilamentPHP

// Analyze a blog post right from your Filament admin panel
public function analyzeContent(): Action
{
    return Action::make('analyzeContent')
        ->label('AI Analysis')
        ->action(function (Model $record) {
            $analysis = app(ContentAnalysisService::class)->analyze($record->content);
            
            // Update the record with AI-generated metadata
            $record->update([
                'reading_time' => $analysis->readingTime,
                'complexity_level' => $analysis->complexityLevel,
                'suggested_tags' => $analysis->suggestedTags,
                'seo_score' => $analysis->seoScore,
            ]);
            
            Notification::make()
                ->title('Content analyzed')
                ->success()
                ->send();
        });
}

Elegant Error Handling

try {
    $result = $aiService->generateStructured($prompt, $schema);
    return SentimentData::fromResponse($result->structured);
} catch (ProviderException $e) {
    Log::error('AI provider error', [
        'message' => $e->getMessage(),
        'provider' => $e->getProvider(),
    ]);
    
    return new SentimentData(
        sentiment: 'neutral',
        score: 50,
        keywords: []
    );
} catch (SchemaValidationException $e) {
    Log::warning('Schema validation error', [
        'message' => $e->getMessage(),
        'errors' => $e->getErrors(),
    ]);
    
    throw new AIResponseException(
        'Unable to process the response. Try rephrasing your input.'
    );
}

Benefits

  • Type Safety: IDE autocompletion and static analysis
  • Predictable Responses: Structured data that conforms to your expectations
  • Reusable Components: Build once, use everywhere
  • Elegant API: Fluent interface with method chaining
  • Flexible Integration: Works with any AI provider

Get Started Today

Transform your Laravel application with reliable, typesafe AI integration. The future of AI-powered applications is structured, predictable, and elegant.

// It's as simple as this
composer require echolabsdev/prism

Build smarter applications without sacrificing reliability or type safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment