Skip to main content

The Goal of the Embedding Process

The goal is to convert each meaningful chunk of text from your document (provided by docling) into a vector. A vector is simply an array of numbers (e.g., [0.012, -0.45, 0.89, ..., -0.11]). The magic of modern embedding models is that semantically similar texts will have vectors that are numerically close to each other in multi-dimensional space. This is what enables powerful “semantic search” or “similarity search,” where you can find document chunks related to a user’s query even if they don’t use the exact same keywords.

Why Use the Gemini API?

  • State-of-the-Art: Google’s models are highly advanced and produce high-quality embeddings.
  • Managed Service: You don’t need to host, manage, or scale any complex AI models yourself.
  • Cost-Effective: It’s a pay-as-you-go service, which is very efficient for variable workloads.
  • Good Integration: There are solid PHP libraries for interacting with the API.
The specific model we’ll be using is text-embedding-004 (or the latest equivalent), which is optimized for this task. It takes text as input and outputs a 768-dimension vector.

Step-by-Step Integration into Your Laravel Job

Here’s how to modify your ProcessDocumentJob to include this step.

Step 1: Install the Gemini PHP Client

First, you need a way to communicate with the Gemini API. The community-driven google-gemini-php/client is a great choice.

Step 2: Configure Your API Key

Never hardcode your API key. Store it in your .env file.
It’s also good practice to create a config file to make it accessible throughout your app cleanly.
Now, edit config/gemini.php:

Step 3: Modify the ProcessDocumentJob

We will create a dedicated private method within the job to handle the embedding logic. This keeps the main handle() method clean. The key to efficiency here is batching. Instead of making one API call for every single text chunk (which would be very slow and inefficient), we will send multiple chunks to the Gemini API in a single request. Here’s the refined ProcessDocumentJob.php:

Important Considerations

  1. Chunk Size: docling should be configured to produce text chunks of a reasonable size. Very long chunks can lose semantic detail, while very short chunks might lack context. A good starting point is around 200-500 words per chunk. This also ensures you don’t exceed the token limit for the Gemini embedding model.
  2. Cost Management: Every call to the Gemini API will incur a cost. Batching significantly reduces the number of requests but the cost is based on the total number of tokens processed. Monitor your usage in the Google AI Platform dashboard.
  3. Rate Limiting & Error Handling: The Gemini API has rate limits (e.g., requests per minute). The client library may throw exceptions when these limits are hit. Because this code runs in a Laravel Job, Laravel’s queue system will automatically retry the job based on your queue configuration (e.g., retry 3 times with an exponential backoff), which is perfect for handling temporary rate limiting or network issues.
  4. Database Connection: Ensure your config/database.php has a separate connection configured for Supabase. This allows you to use Laravel’s standard DB facade while keeping your main app’s database separate.
This detailed approach provides a robust, efficient, and maintainable way to integrate a powerful external AI service directly into your Laravel application’s asynchronous workflow.