Integrating AI into Laravel: Practical OpenAI and Gemini Features for Startups
Adding artificial intelligence to your product shouldn't just be a marketing gimmick. Here is how to build practical, production-ready AI features in Laravel using OpenAI and Gemini with streaming, queue management, and cost control.
Artificial intelligence has rapidly shifted from experimental technology to an expected feature in modern SaaS applications. Founders and product managers are embedding smart search, automatic content summarization, document extraction, and conversational agents directly into their products.
Laravel's mature ecosystem — with built-in queuing, HTTP client, and event streaming — provides an exceptional backend foundation for orchestrating AI workflows.
In this guide, I walk through practical architectural patterns for integrating OpenAI and Google Gemini APIs into Laravel applications without hanging server processes or exceeding budget limits.
Architecture: Synchronous vs. Queued AI Jobs
AI models are slow compared to typical database queries. Generating a response from GPT-4 or Gemini 1.5 Pro can take between 2 to 15 seconds. If you execute this call synchronously inside a standard HTTP controller, you will exhaust PHP-FPM worker pools and cause timeouts for users.
The Two Production Approaches:
- Asynchronous Queues: For long-running batch jobs (e.g. summarizing a 50-page PDF or transcribing audio), dispatch a queued job and notify the frontend via WebSockets (Pusher or Laravel Reverb) when complete.
- Server-Sent Events (SSE) Streaming: For interactive chat and assistant responses, stream tokens chunk by chunk directly to the user's browser in real time.
Setting Up the Official Laravel OpenAI Client
Install the community standard OpenAI client:
composer require openai-php/laravel php artisan vendor:publish --provider="OpenAI\Laravel\ServiceProvider"
Add your API credentials to .env:
OPENAI_API_KEY=sk-... OPENAI_ORGANIZATION=org-...
Implementing Real-Time Streaming with Server-Sent Events
Streaming provides an immediate visual feedback loop. The user sees words generating within 200ms rather than staring at a blank screen for 6 seconds.
Here is a clean controller implementation using Laravel's response()->stream():
namespace App\Http\Controllers; use OpenAI\Laravel\Facades\OpenAI; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\StreamedResponse; class AiAssistantController extends Controller { public function streamPrompt(Request $request): StreamedResponse { $validated = $request->validate([ 'message' => 'required|string|max:1000', ]); return response()->stream(function () use ($validated) { $stream = OpenAI::chat()->createStreamed([ 'model' => 'gpt-4o-mini', 'messages' => [ ['role' => 'system', 'content' => 'You are an expert technical assistant.'], ['role' => 'user', 'content' => $validated['message']], ], 'temperature' => 0.7, ]); foreach ($stream as $response) { $text = $response->choices[0]->delta->content ?? ''; if ($text !== '') { echo "data: " . json_encode(['text' => $text]) . "\n\n"; ob_flush(); flush(); } } echo "data: [DONE]\n\n"; ob_flush(); flush(); }, 200, [ 'Cache-Control' => 'no-cache', 'Content-Type' => 'text/event-stream', 'X-Accel-Buffering' => 'no', // Disable Nginx proxy buffering ]); } }
Using Google Gemini for Multimodal Extraction
Google's Gemini API offers generous free tiers, fast processing speeds, and exceptional multimodal capabilities (processing images, documents, and videos alongside text).
Using Laravel's native Http client, you can integrate Gemini with zero extra dependencies:
namespace App\Services; use Illuminate\Support\Facades\Http; class GeminiService { protected string $apiKey; protected string $endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent'; public function __construct() { $this->apiKey = config('services.gemini.key'); } public function extractReceiptData(string $base64Image, string $mimeType): array { $response = Http::post("{$this->endpoint}?key={$this->apiKey}", [ 'contents' => [ [ 'parts' => [ ['text' => 'Extract total_amount, merchant_name, and date in JSON format.'], [ 'inline_data' => [ 'mime_type' => $mimeType, 'data' => $base64Image, ], ], ], ], ], 'generationConfig' => [ 'response_mime_type' => 'application/json', ], ]); if ($response->failed()) { throw new \Exception('Gemini API request failed: ' . $response->body()); } $rawJson = $response->json('candidates.0.content.parts.0.text'); return json_decode($rawJson, true) ?? []; } }
Managing Costs and Preventing Token Abuse
AI features can become expensive rapidly if left unprotected:
- Strict Rate Limiting: Apply Laravel's
RateLimitermiddleware to all AI routes (e.g. max 10 requests per minute per user). - Prompt Token Caps: Always set
max_tokenson requests to prevent unbounded responses from consuming unnecessary credits. - Cache Identical Queries: If users frequently ask similar questions, cache the generated responses in Redis for 24 hours.
For broader technical strategy, explore The Best Tech Stack for an MVP in 2026 and Laravel vs Django vs .NET.
Interested in building an AI-powered MVP or integrating intelligent automation into your Laravel platform? Discover my full-stack development services or MVP development services, or contact me to discuss your ideas.