Laravel Daily's

Build a Smarter Store: AI-Powered Product Recommendations with Laravel AI SDK

hero image

Standard keyword search is reaching its limit. When a customer searches for "warm winter coat," they expect to see parkas and down jackets, even if the word "warm" isn't in the product title. Traditional SQL LIKE queries can't bridge this gap.

Semantic search changes that. By representing products as mathematical vectors (embeddings), your application can understand the context and meaning of your catalog. Laravel 13 makes this accessible through the Laravel AI SDK. This tutorial shows you how to build a recommendation engine using embeddings and PostgreSQL.

The Foundation: AI SDK and pgvector

To build a semantic recommendation engine, you need a way to store and compare these vectors. PostgreSQL with the pgvector extension is the industry standard for this. It allows you to store arrays of numbers and perform high-speed similarity calculations directly in your database.

Start by installing the Laravel AI SDK:

composer require laravel/ai

Next, configure your provider in the .env file. You can use OpenAI or Anthropic. For embeddings, OpenAI’s text-embedding-3-small is a cost-effective and high-performance choice.

AI_PROVIDER=openai
OPENAI_API_KEY=your-api-key

Preparing the Database

Ensure your PostgreSQL instance has the pgvector extension enabled. Most managed providers support this out of the box. You can enable it via a migration or by running a raw SQL command:

CREATE EXTENSION IF NOT EXISTS vector;

Now, create a migration to add an embedding column to your products table. The dimension of the vector must match your model. OpenAI’s standard embedding model uses 1536 dimensions.

A PostgreSQL database table layout with a Vector Embedding column

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

Schema::table('products', function (Blueprint $table) {
    // 1536 is the dimension for OpenAI text-embedding-3-small
    $table->vector('embedding', 1536)->nullable();
});

In your Product model, cast the embedding column to an array. This ensures this php web framework handles the data conversion seamlessly.

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

Generating Embeddings in the Background

Generating embeddings involves making external API calls. Never do this during a standard HTTP request. If you have thousands of products, use Laravel’s built-in queue system to process them in the background.

This is where php developer tools like Laravel Horizon become invaluable for monitoring your progress.

An illustration of a Laravel background worker queue processing product boxes

Create a job to generate the embedding for a product:

namespace App\Jobs;

use App\Models\Product;
use Laravel\AI\Facades\Embeddings;
use Illuminate\Contracts\Queue\ShouldQueue;

class GenerateProductEmbedding implements ShouldQueue
{
    public function __construct(public Product $product) {}

    public function handle()
    {
        $text = "{$this->product->name}: {$this->product->description}";
        
        $this->product->update([
            'embedding' => Embeddings::generate($text)
        ]);
    }
}

You can trigger this job whenever a product is created or updated using Eloquent observers or model events.

Finding Similar Products

With your products vectorized, you can now perform similarity searches. The Laravel AI SDK adds a whereVectorSimilarTo method to the query builder. It calculates the cosine similarity between the input and your stored vectors.

A visual representation of semantic similarity search

To find recommendations for a specific product, generate an embedding for that product (or use its existing one) and search for others nearby.

use App\Models\Product;

$product = Product::find(1);

$recommendations = Product::where('id', '!=', $product->id)
    ->whereVectorSimilarTo('embedding', $product->embedding, 'cosine')
    ->limit(5)
    ->get();

The third argument, 'cosine', specifies the distance metric. Cosine similarity is the most common choice for text embeddings.

Combining AI with Business Logic

A smart store doesn't just show similar items; it shows similar items that are actually available. You can combine vector similarity with standard Eloquent constraints. This allows you to filter by stock status, category, or price range.

$recommendations = Product::where('in_stock', true)
    ->where('category_id', $currentCategory)
    ->whereVectorSimilarTo('embedding', $queryEmbedding, 'cosine', 0.75) // 0.75 is the similarity threshold
    ->orderByDesc('created_at')
    ->take(4)
    ->get();

This hybrid approach ensures your AI-driven results still respect your business rules.

Production Performance: HNSW Indexing

As your catalog grows, calculating similarity across every row becomes slow. PostgreSQL’s pgvector supports HNSW (Hierarchical Navigable Small Worlds) indexes. These create a graph-based structure for extremely fast approximate nearest neighbor searches.

Add the index in a migration:

public function up()
{
    DB::statement('CREATE INDEX ON products USING hnsw (embedding vector_cosine_ops);');
}

This index allows your store to handle hundreds of thousands of products while maintaining sub-millisecond query times.

Building the Recommendation API

Finally, you can build rest api with php to expose these recommendations to your frontend. A simple controller can handle the logic and return a clean JSON response.

namespace App\Http\Controllers\Api;

use App\Models\Product;
use Illuminate\Http\Request;

class RecommendationController
{
    public function show(Product $product)
    {
        $recommendations = Product::query()
            ->where('id', '!=', $product->id)
            ->where('is_active', true)
            ->whereVectorSimilarTo('embedding', $product->embedding, 'cosine')
            ->limit(4)
            ->get();

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

This endpoint can be called by your Vue or React frontend to populate "You may also like" sections dynamically.

Moving Forward

AI-powered search is no longer a luxury reserved for giant marketplaces. With the Laravel AI SDK and pgvector, you can implement sophisticated recommendation engines in hours.

The ecosystem continues to expand. You can further enhance this setup by using Laravel Cloud for managed infrastructure or Nightwatch for monitoring your AI usage and logs.

Start by vectorizing your most popular category. We’d love to hear how semantic search changes your conversion rates.

Previous
Laravel Trends 2026: The Framework's Evolution into a Full-Stack AI-Powered Platform
Next
Building Real-Time Dashboards with Laravel, Vue 3, and Inertia 3.x