...

How to Build an AI Chatbot in Laravel Using ChatGPT and Gemini APIs

Artificial Intelligence is reshaping the way websites interact with users. If you’re building with Laravel, you can easily integrate ChatGPT (OpenAI) and Gemini (Google AI) into your application to provide a smart chatbot. In this guide, we’ll build a Laravel AI Chatbot step by step.

You’ll learn how to:
✅ Setup API integration with OpenAI and Gemini
✅ Create a chatbot service & controller in Laravel
✅ Build a Tailwind CSS chat UI
✅ Add the chatbot as a floating widget on your homepage

Step 1: Install Laravel & Dependencies

Make sure you have a Laravel project ready. Then install GuzzleHTTP to handle API requests:

composer require guzzlehttp/guzzle

Step 2: Add API Keys

In your .env file, add:

OPENAI_API_KEY=your_openai_api_key_here
GEMINI_API_KEY=your_gemini_api_key_here

Step 3: Create a Service for Chat APIs

Create app/Services/ChatAIService.php

<?php

namespace App\Services;

use GuzzleHttp\Client;

class ChatAIService
{
    protected $client;

    public function __construct()
    {
        $this->client = new Client();
    }

    // ChatGPT
    public function chatWithOpenAI($message)
    {
        $response = $this->client->post('https://api.openai.com/v1/chat/completions', [
            'headers' => [
                'Authorization' => 'Bearer ' . env('OPENAI_API_KEY'),
                'Content-Type'  => 'application/json',
            ],
            'json' => [
                'model' => 'gpt-4o-mini',
                'messages' => [
                    ['role' => 'system', 'content' => 'You are a helpful assistant.'],
                    ['role' => 'user', 'content' => $message],
                ],
                'max_tokens' => 300,
            ],
        ]);

        $data = json_decode($response->getBody(), true);
        return $data['choices'][0]['message']['content'] ?? 'No response';
    }

    // Gemini
    public function chatWithGemini($message)
    {
        $response = $this->client->post("https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=" . env('GEMINI_API_KEY'), [
            'headers' => [
                'Content-Type' => 'application/json',
            ],
            'json' => [
                'contents' => [
                    ['parts' => [['text' => $message]]],
                ],
            ],
        ]);

        $data = json_decode($response->getBody(), true);
        return $data['candidates'][0]['content']['parts'][0]['text'] ?? 'No response';
    }
}


Step 4: Create Controller


Make app/Http/Controllers/ChatController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\ChatAIService;

class ChatController extends Controller
{
    protected $chatService;

    public function __construct(ChatAIService $chatService)
    {
        $this->chatService = $chatService;
    }

    public function askOpenAI(Request $request)
    {
        $message = $request->input('message');
        $reply = $this->chatService->chatWithOpenAI($message);

        return response()->json(['reply' => $reply]);
    }

    public function askGemini(Request $request)
    {
        $message = $request->input('message');
        $reply = $this->chatService->chatWithGemini($message);

        return response()->json(['reply' => $reply]);
    }
}

Step 5: Define Routes

Add in routes/web.php:

use App\Http\Controllers\ChatController;

Route::post('/chat/openai', [ChatController::class, 'askOpenAI']);
Route::post('/chat/gemini', [ChatController::class, 'askGemini']);

Step 6: Create Tailwind Chat Widget

Create a widget view:
resources/views/components/chat-widget.blade.php

<div id="chat-widget" class="fixed bottom-5 right-5 w-80 bg-white shadow-lg rounded-2xl overflow-hidden flex flex-col hidden">
    
    <!-- Header -->
    <div class="bg-indigo-600 text-white px-4 py-2 flex justify-between items-center">
        <span class="font-semibold">🤖 AI Chatbot</span>
        <button onclick="toggleChat()" class="text-white"></button>
    </div>

    <!-- Chat Messages -->
    <div id="chat-box" class="flex-1 overflow-y-auto p-3 space-y-3 h-64">
        <!-- Messages will appear here -->
    </div>

    <!-- Input Area -->
    <div class="border-t p-2 flex items-center space-x-2">
        <input id="message" type="text" placeholder="Type..." 
               class="flex-1 px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-400">

        <button onclick="sendMessage()" 
                class="bg-indigo-600 text-white px-3 py-2 rounded-lg hover:bg-indigo-700 transition text-sm">
            GPT
        </button>
        <button onclick="sendMessageGemini()" 
                class="bg-green-600 text-white px-3 py-2 rounded-lg hover:bg-green-700 transition text-sm">
            Gem
        </button>
    </div>
</div>

<!-- Floating Button -->
<button id="chat-toggle-btn" onclick="toggleChat()" 
        class="fixed bottom-5 right-5 bg-indigo-600 text-white p-4 rounded-full shadow-lg hover:bg-indigo-700">
    💬
</button>

<script>
    function toggleChat() {
        let widget = document.getElementById("chat-widget");
        let btn = document.getElementById("chat-toggle-btn");
        widget.classList.toggle("hidden");
        btn.classList.toggle("hidden");
    }

    function addMessage(sender, text, type = "user") {
        const chatBox = document.getElementById("chat-box");
        const msgDiv = document.createElement("div");

        if (type === "user") {
            msgDiv.className = "flex justify-end";
            msgDiv.innerHTML = `<div class="bg-indigo-100 text-gray-800 px-3 py-2 rounded-lg max-w-xs">${text}</div>`;
        } else {
            msgDiv.className = "flex justify-start";
            msgDiv.innerHTML = `<div class="bg-gray-200 text-gray-800 px-3 py-2 rounded-lg max-w-xs"><b>${sender}:</b> ${text}</div>`;
        }

        chatBox.appendChild(msgDiv);
        chatBox.scrollTop = chatBox.scrollHeight;
    }

    async function sendMessage() {
        let message = document.getElementById('message').value;
        if (!message.trim()) return;

        addMessage("You", message, "user");
        document.getElementById('message').value = "";

        let res = await fetch('/chat/openai', {
            method: 'POST',
            headers: {
                "Content-Type": "application/json",
                "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute('content')
            },
            body: JSON.stringify({ message })
        });

        let data = await res.json();
        addMessage("OpenAI", data.reply, "bot");
    }

    async function sendMessageGemini() {
        let message = document.getElementById('message').value;
        if (!message.trim()) return;

        addMessage("You", message, "user");
        document.getElementById('message').value = "";

        let res = await fetch('/chat/gemini', {
            method: 'POST',
            headers: {
                "Content-Type": "application/json",
                "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute('content')
            },
            body: JSON.stringify({ message })
        });

        let data = await res.json();
        addMessage("Gemini", data.reply, "bot");
    }
</script>

Step 7: Include Widget on Homepage

In resources/views/home.blade.php (or welcome.blade.php):

@extends('layouts.app')

@section('content')
    <div class="container mx-auto p-6">
        <h1 class="text-3xl font-bold mb-6">Welcome to My Site</h1>
        <p class="mb-4">This is the homepage content...</p>
    </div>

    {{-- Chatbot Widget --}}
    @include('components.chat-widget')
@endsection
Here’s a full Tailwind-styled chatbot interface (with scrolling chat bubbles,
input box, and buttons):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AI Chatbot</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen">

    <div class="w-full max-w-lg bg-white rounded-2xl shadow-lg flex flex-col h-[600px]">
        
        <!-- Header -->
        <div class="bg-indigo-600 text-white text-center py-3 rounded-t-2xl font-semibold">
            🤖 Laravel AI Chatbot
        </div>

        <!-- Chat Messages -->
        <div id="chat-box" class="flex-1 overflow-y-auto p-4 space-y-4">
            <!-- Messages will appear here -->
        </div>

        <!-- Input Area -->
        <div class="border-t p-3 flex items-center space-x-2">
            <input id="message" type="text" placeholder="Type a message..." 
                   class="flex-1 px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-400">
            
            <button onclick="sendMessage()" 
                    class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition">
                ChatGPT
            </button>

            <button onclick="sendMessageGemini()" 
                    class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition">
                Gemini
            </button>
        </div>
    </div>

    <script>
        function addMessage(sender, text, type = "user") {
            const chatBox = document.getElementById("chat-box");
            const msgDiv = document.createElement("div");
            
            if (type === "user") {
                msgDiv.className = "flex justify-end";
                msgDiv.innerHTML = `<div class="bg-indigo-100 text-gray-800 px-4 py-2 rounded-lg max-w-xs">${text}</div>`;
            } else {
                msgDiv.className = "flex justify-start";
                msgDiv.innerHTML = `<div class="bg-gray-200 text-gray-800 px-4 py-2 rounded-lg max-w-xs"><b>${sender}:</b> ${text}</div>`;
            }
            
            chatBox.appendChild(msgDiv);
            chatBox.scrollTop = chatBox.scrollHeight;
        }

        async function sendMessage() {
            let message = document.getElementById('message').value;
            if (!message.trim()) return;
            
            addMessage("You", message, "user");
            document.getElementById('message').value = "";

            let res = await fetch('/chat/openai', {
                method: 'POST',
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                },
                body: JSON.stringify({ message })
            });

            let data = await res.json();
            addMessage("OpenAI", data.reply, "bot");
        }

        async function sendMessageGemini() {
            let message = document.getElementById('message').value;
            if (!message.trim()) return;
            
            addMessage("You", message, "user");
            document.getElementById('message').value = "";

            let res = await fetch('/chat/gemini', {
                method: 'POST',
                headers: {
                    "Content-Type": "application/json",
                    "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                },
                body: JSON.stringify({ message })
            });

            let data = await res.json();
            addMessage("Gemini", data.reply, "bot");
        }
    </script>
</body>
</html>
Final Result 🎉

You now have a Laravel AI Chatbot powered by ChatGPT and Gemini.

It appears as a floating widget on your homepage.

Users can chat in real-time with AI responses styled using Tailwind CSS.

William Anderson

I am a versatile Full-Stack Web Developer with a strong focus on Laravel, Livewire, Vue.js, and Tailwind CSS. With extensive experience in backend development, I specialize in building scalable, efficient, and high-performance web applications.