Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ai Cloudflare Store Laravel Package

symfony/ai-cloudflare-store

Integrates Cloudflare Vectorize as a vector store for Symfony AI Store. Supports indexing and querying embeddings plus upserts and deletions via the Vectorize APIs, making it easy to connect Symfony AI apps to Cloudflare’s managed vector database.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies:
    composer require symfony/ai symfony/ai-cloudflare-store
    
  2. Configure Cloudflare API Token and Index: Add to .env:
    CLOUDFLARE_API_TOKEN=your_cloudflare_api_token
    CLOUDFLARE_VECTORIZE_INDEX=your_vectorize_index_name
    
  3. Bind the Store in Laravel: Create a service provider (e.g., CloudflareVectorizeServiceProvider) and register the store:
    use Symfony\Component\AI\Store\StoreInterface;
    use Symfony\AI\CloudflareStore\CloudflareVectorizeStore;
    
    public function register()
    {
        $this->app->singleton(StoreInterface::class, function ($app) {
            return new CloudflareVectorizeStore(
                $app->make(\Symfony\Component\AI\Client::class),
                config('services.cloudflare.vectorize_index')
            );
        });
    }
    

First Use Case: Upserting Vectors

use Symfony\Component\AI\Store\StoreInterface;

public function __construct(private StoreInterface $store) {}

public function indexDocument(array $embedding, string $id)
{
    $this->store->upsert([$embedding], [$id]);
}

First Use Case: Querying Vectors

public function searchSimilarDocuments(array $queryEmbedding, int $limit = 5)
{
    $results = $this->store->query($queryEmbedding, $limit);
    return $results->getVectors();
}

Implementation Patterns

Workflow: AI-Powered Semantic Search

  1. Embedding Generation: Use a model (e.g., symfony/ai with HuggingFace) to generate embeddings for documents:
    $embedding = $aiClient->getEmbedding('Your document text');
    
  2. Store Embeddings:
    $this->store->upsert([$embedding], ['doc_id_123']);
    
  3. Query Embeddings:
    $queryEmbedding = $aiClient->getEmbedding('User search query');
    $similarDocs = $this->store->query($queryEmbedding, 3);
    
  4. Retrieve Metadata: Use the returned IDs to fetch full documents from your database.

Workflow: RAG Pipeline

  1. Chunk and Embed: Split documents into chunks and generate embeddings for each.
  2. Batch Upsert:
    $this->store->upsert($embeddings, $chunkIds);
    
  3. Retrieve Context:
    $contextEmbedding = $aiClient->getEmbedding('User question');
    $contextChunks = $this->store->query($contextEmbedding, 5);
    
  4. Prompt Construction: Combine retrieved chunks into a prompt for your LLM.

Integration with Laravel Queues

Offload vector operations to avoid blocking requests:

use Illuminate\Support\Facades\Queue;

Queue::push(function () {
    $this->store->upsert($embeddings, $ids);
});

Integration with Scout (Hybrid Search)

Use Cloudflare Vectorize for semantic search and Scout for keyword search:

// Semantic search via Cloudflare
$semanticResults = $this->store->query($queryEmbedding, 10);

// Keyword search via Scout
$keywordResults = YourModel::search($query)->get();

Gotchas and Tips

Pitfalls

  1. Symfony AI Dependency:

    • The package requires symfony/ai, which may not be natively compatible with Laravel. Ensure you’re using a recent Laravel version (10+) and handle potential namespace conflicts.
    • Fix: Use symfony/ai as a standalone dependency and explicitly bind services to avoid conflicts.
  2. Cloudflare API Rate Limits:

    • Cloudflare Vectorize may throttle requests. Monitor your usage and implement retries with exponential backoff.
    • Tip: Use Laravel’s Illuminate\Support\Facades\Retry for resilient API calls:
      Retry::retry(3, function () {
          $this->store->query($embedding);
      }, function ($e) {
          return $e instanceof \Symfony\Component\AI\Exception\RateLimitExceededException;
      });
      
  3. Vector ID Collisions:

    • Ensure IDs passed to upsert() are unique. Cloudflare Vectorize may silently overwrite duplicates.
    • Tip: Use UUIDs or database-generated IDs to avoid collisions.
  4. Metadata Filtering:

    • The package supports filtering via the query() method, but complex filters may require custom NDJSON payloads.
    • Tip: Refer to Cloudflare’s query API docs for advanced filtering.
  5. Cost Monitoring:

    • Cloudflare Vectorize pricing is based on operations. Monitor usage to avoid unexpected costs.
    • Tip: Log the number of operations and set up alerts for spikes.

Debugging

  1. Enable Debug Logging: Configure the Symfony AI client to log API requests:

    $aiClient = new \Symfony\Component\AI\Client(
        config('services.openai.key'),
        new \Symfony\Component\AI\HttpClient\Psr18Client(
            new \GuzzleHttp\Client(['debug' => true])
        )
    );
    

    Use Laravel’s logging to inspect Cloudflare API responses:

    Log::debug('Cloudflare API Response', ['response' => $response]);
    
  2. Validate NDJSON Payloads: Cloudflare Vectorize expects NDJSON for upsert and query. Validate payloads before sending:

    $payload = json_encode([$embedding], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    Log::debug('NDJSON Payload', ['payload' => $payload]);
    
  3. Handle API Errors: Catch specific exceptions from the Symfony AI client:

    try {
        $this->store->query($embedding);
    } catch (\Symfony\Component\AI\Exception\CloudflareException $e) {
        Log::error('Cloudflare Error: ' . $e->getMessage());
        // Implement fallback logic (e.g., cache, retry)
    }
    

Extension Points

  1. Custom Filtering: Extend the query() method to support custom filters by modifying the NDJSON payload:

    $this->store->query($embedding, 5, [
        'filter' => json_encode(['metadata' => ['category' => 'tech']])
    ]);
    
  2. Batch Operations: For large datasets, implement batch upserts using Cloudflare’s bulk API:

    $batchSize = 100;
    foreach (array_chunk($embeddings, $batchSize) as $batch) {
        $this->store->upsert($batch, array_chunk($ids, $batchSize));
    }
    
  3. Local Fallback: Implement a fallback to a local store (e.g., Redis) if Cloudflare is unavailable:

    public function query(array $embedding, int $limit = 5)
    {
        try {
            return $this->store->query($embedding, $limit);
        } catch (\Exception $e) {
            Log::error('Cloudflare fallback triggered', ['error' => $e]);
            return $this->localStore->query($embedding, $limit);
        }
    }
    
  4. Monitoring Metrics: Track vector store performance and costs using Laravel’s monitoring tools:

    $this->store->query($embedding, 5, [], function ($response) {
        $this->trackMetric('vectorize.query.time', $response->getElapsedTime());
    });
    

Configuration Quirks

  1. Environment Variables: Ensure CLOUDFLARE_API_TOKEN and CLOUDFLARE_VECTORIZE_INDEX are set in .env. The package may not throw clear errors if these are missing.

    • Tip: Add validation in your service provider:
      if (!config('services.cloudflare.api_token')) {
          throw new \RuntimeException('Cloudflare API token not configured.');
      }
      
  2. Index Creation: The package assumes the Vectorize index already exists. Create it manually via the Cloudflare Dashboard or API if needed.

    • Tip: Add a migration or artisan command to create the index:
      public function createVectorizeIndex()
      {
          $client = new \Cloudflare\Vectorize\Client(config('services.cloudflare.api_token'));
          $client->createIndex(config('services.cloudflare.vectorize_index'), [
            'dimension' => 768, // Adjust based on your embeddings
            'metric' => 'cosine'
          ]);
      }
      
  3. Dimension Mismatch: Ensure your embeddings match the index’s dimension. Mismatches will cause silent failures.

    • Tip: Validate dimensions before upserting:
      $expectedDimension = 768; // Configured in your index
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/graphviz
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata