Laravel Daily's

Building an AI-Powered Document Search API with Laravel's AI SDK

hero image

Modern applications no longer just store data. They understand it. Semantic search has moved from a luxury to a requirement for document-heavy platforms. Using the Laravel AI SDK, you can build sophisticated Retrieval-Augmented Generation (RAG) systems without the cognitive overhead of managing external vector infrastructure manually.

Laravel remains the premier php web framework by turning complex technologies into expressive, developer-friendly APIs. The AI SDK extends this philosophy to machine learning. It provides first-party tools for vector storage, embedding generation, and autonomous agents.

This guide explores how to build a production-ready document search API. You will learn to ingest documents, perform vector similarity searches, and return structured JSON responses.

The Foundation: Vector Storage and pgvector

Traditional keyword search fails when users ask questions instead of typing phrases. Vector search solves this by representing text as numerical coordinates (embeddings). Records with similar meanings sit closer together in this mathematical space.

To start, you need a database that speaks this language. PostgreSQL with the pgvector extension is the standard choice for the Laravel ecosystem. It allows you to store embeddings directly alongside your relational data.

Initializing the SDK

Begin by installing the AI SDK and publishing the necessary assets. This setup prepares your environment for conversational memory and vector handling.

composer require laravel/ai
php artisan ai:install
php artisan migrate

Configure your preferred provider in config/ai.php. The SDK supports OpenAI, Anthropic, Gemini, and more. This flexibility is a hallmark of modern php developer tools.

Creating the Vector Schema

Your database needs a dedicated column for high-dimensional vectors. In Laravel 13, the schema builder includes native support for vector types.

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\\Facades\Schema;

Schema::ensureVectorExtensionExists();

Schema::create('documents', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->vector('embedding', dimensions: 1536)->index();
    $table->timestamps();
});

The dimensions count depends on your embedding model. OpenAI’s text-embedding-3-small, for instance, defaults to 1536. Adding an index here is critical for performance as your dataset grows.

Vibrant illustration showing text transforming into numerical vectors flowing into a Laravel database

Document Ingestion and Embedding Generation

Data must be transformed before it can be searched. When a user uploads a document, your application should extract the text and generate its vector representation.

Processing via Background Jobs

Generating embeddings involves network requests to AI providers. Never perform these tasks within the main request-response cycle. Use Laravel's queue system to handle this asynchronously.

namespace App\Jobs;

use App\Models\Document;
use Laravel\Ai\Embeddings;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessDocument implements ShouldQueue
{
    public function __construct(public Document $document) {}

    public function handle(): void
    {
        $vector = Embeddings::for('openai')
            ->embed($this->document->content);

        $this->document->update(['embedding' => $vector]);
    }
}

On your Document model, ensure the embedding attribute is cast correctly. This tells Eloquent to handle the numeric array as a specialized database type.

protected $casts = [
    'embedding' => 'embedding',
];

Building the Intelligent Agent

An agent is a specialized class that coordinates between the user, the AI model, and your data. It doesn't just "talk"; it uses tools to find facts. For document search, the agent needs a tool to query your documents table.

Defining the Search Tool

The AI SDK includes a SimilaritySearch tool. This tool automatically handles the math of converting a user's question into a vector and finding the closest matches in your database.

namespace App\Ai\Agents;

use Laravel\Ai\Agents\Agent;
use Laravel\Ai\Tools\SimilaritySearch;
use App\Models\Document;
use Laravel\Ai\Agents\Concerns\RemembersConversations;

class SearchAssistant extends Agent
{
    use RemembersConversations;

    public function instructions(): string
    {
        return <<<'PROMPT'
        You are a technical document assistant.
        Use the SimilaritySearch tool to find relevant context.
        Base your answers only on the provided documents.
        Cite the document titles in your response.
        PROMPT;
    }

    public function tools(): iterable
    {
        return [
            SimilaritySearch::usingModel(Document::class, 'embedding'),
        ];
    }
}

The RemembersConversations trait allows the agent to maintain context. If a user asks a follow-up question like "Can you elaborate on that?", the agent knows what "that" refers to.

Cartoony agent character wearing a detective outfit holding a Laravel badge and organizing documents

Enforcing Structured Output

When you build rest api with php, reliability is paramount. You cannot rely on raw strings from an AI model if your frontend expects a specific JSON structure. The AI SDK solves this through the HasStructuredOutput interface.

Defining the Response Schema

By implementing this interface, you force the AI provider to return a strictly validated JSON object. This eliminates the need for fragile regex parsing or "clean-up" logic.

use Laravel\Ai\Agents\Contracts\HasStructuredOutput;

class SearchAssistant extends Agent implements HasStructuredOutput
{
    // ... logic from before ...

    public function outputSchema(): array
    {
        return [
            'type' => 'object',
            'properties' => [
                'answer' => ['type' => 'string'],
                'confidence_score' => ['type' => 'number'],
                'citations' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                        'properties' => [
                            'title' => ['type' => 'string'],
                            'page' => ['type' => 'integer'],
                        ],
                    ],
                ],
            ],
            'required' => ['answer', 'citations'],
        ];
    }
}

This schema ensures your API responses are consistent, making them easy to consume in a Vue.js or React frontend.

Exposing the API Endpoints

With the agent configured, you only need a controller to bridge the HTTP request to the AI logic. Laravel's routing and controllers provide a clean entry point for your search service.

The Chat Controller

The controller receives the user's prompt, passes it to the agent, and returns the result.

namespace App\Http\Controllers\Api;

use App\Ai\Agents\SearchAssistant;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class SearchController
{
    public function __invoke(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'prompt' => 'required|string|max:1000',
        ]);

        $response = SearchAssistant::make()
            ->handle($validated['prompt']);

        return response()->json($response);
    }
}

Register the route in routes/api.php:

use App\Http\Controllers\Api\SearchController;
use Illuminate\Support\Facades\Route;

Route::post('/v1/search', SearchController::class);

A Laravel logo box outputting a 3D glass JSON code block with REST API icons

Scaling and Refinement

This implementation is a robust starting point. As your document library grows, consider implementing document chunking. Large files should be split into smaller, overlapping segments to ensure the vector search finds the most relevant specific passages rather than a generic overview.

You might also explore FileSearch if you prefer to offload vector management to providers like OpenAI. The AI SDK allows you to switch between local SimilaritySearch and provider-managed search with minimal code changes.

The Laravel ecosystem continues to lower the barrier for advanced AI integration. By combining Eloquent, pgvector, and the AI SDK, you can ship feature-rich search experiences in hours instead of weeks.

We’d love to hear how you are using the AI SDK to transform your internal documentation or customer support flows. The next wave of PHP development is here, and it is deeply intelligent.

Previous
Laravel Trends 2026: What's Shaping the PHP Framework Landscape
Next
Real-Time Notifications with Laravel Reverb, Vue 3, and Inertia 3.x: A 2026 Production Guide