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 Qdrant Store Laravel Package

symfony/ai-qdrant-store

Symfony AI Store integration for Qdrant vector database. Manage collections and points, run unified similarity search with filters, and connect Symfony AI apps to Qdrant for storing and querying embeddings.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package:

    composer require symfony/ai-qdrant-store
    
  2. Configure Qdrant Store in config/packages/ai.yaml:

    framework:
        ai:
            stores:
                qdrant:
                    type: qdrant
                    url: '%env(QDRANT_URL)%'  # e.g., http://localhost:6333
                    api_key: '%env(QDRANT_API_KEY)%'  # Optional if using auth
                    collection: 'my_embeddings'  # Default collection name
                    options:
                        # Optional Qdrant client options (e.g., timeout, retries)
                        timeout: 30
    
  3. First Use Case: Upsert a Vector Inject the store into a service and use it to add a vector:

    use Symfony\AI\Store\StoreInterface;
    
    class MyService {
        public function __construct(private StoreInterface $qdrantStore) {}
    
        public function addEmbedding(array $embedding, array $payload): void {
            $this->qdrantStore->upsert(
                $embedding['vector'],
                $payload,
                $embedding['id'] ?? null
            );
        }
    }
    
  4. Query Vectors with Filtering:

    $results = $this->qdrantStore->query(
        $queryVector,
        limit: 5,
        filter: ['must': [['key' => 'status', 'match' => ['value' => 'published']]]]
    );
    

Implementation Patterns

Core Workflows

  1. Collection Management:

    • Create/update collections dynamically:
      $this->qdrantStore->createCollection('new_collection', [
          'vectors' => ['size' => 768, 'distance' => 'Cosine'],
          'payload_schema' => ['text' => 'string', 'timestamp' => 'integer'],
      ]);
      
  2. Batch Operations:

    • Use upsertMany() for bulk inserts:
      $this->qdrantStore->upsertMany([
          ['vector' => $vector1, 'payload' => $payload1, 'id' => 'id1'],
          ['vector' => $vector2, 'payload' => $payload2, 'id' => 'id2'],
      ]);
      
  3. Hybrid Search:

    • Combine vector similarity with metadata filtering:
      $results = $this->qdrantStore->query(
          $queryVector,
          filter: ['must': [
              ['key' => 'category', 'match' => ['value' => 'tech']],
              ['key' => 'rating', 'range' => ['gt' => 3]],
          ]]
      );
      

Integration Tips

  • Dependency Injection:

    • Tag services for vector operations to decouple business logic:
      services:
          App\Service\VectorSearchService:
              tags: ['ai.store.qdrant']
      
  • Custom HTTP Clients:

    • Extend ScopingHttpClient for observability or retries:
      use Symfony\Contracts\HttpClient\ScopedHttpClientInterface;
      
      $client = new ScopingHttpClient(
          $baseClient,
          ['debug' => true, 'timeout' => 10]
      );
      $store = new QdrantStore($client, 'http://qdrant:6333', 'api_key');
      
  • Schema Validation:

    • Validate payloads before upserting using Symfony’s Validator:
      use Symfony\Component\Validator\Validator\ValidatorInterface;
      
      $errors = $validator->validate($payload);
      if (count($errors) > 0) {
          throw new \RuntimeException('Invalid payload');
      }
      
  • Async Processing:

    • Offload heavy operations to a message queue (e.g., Symfony Messenger):
      $message = new VectorUpsertMessage($vector, $payload);
      $this->messageBus->dispatch($message);
      

Gotchas and Tips

Pitfalls

  1. Collection Schema Mismatches:

    • Issue: Upserting vectors with mismatched dimensions or payload schemas will fail silently or corrupt data.
    • Fix: Validate schemas upfront or use Qdrant’s createCollection() with explicit settings.
  2. Filter Syntax Errors:

    • Issue: Invalid Qdrant filter syntax (e.g., typos in must/should clauses) throws cryptic errors.
    • Fix: Test filters in Qdrant’s playground first.
  3. Rate Limiting:

    • Issue: Cloud Qdrant may throttle requests during bulk operations.
    • Fix: Implement exponential backoff with Symfony’s RetryStrategy:
      $client->withOptions([
          'retry_on_status' => [429, 500, 502, 503, 504],
          'timeout' => 30,
      ]);
      
  4. ID Collisions:

    • Issue: Reusing IDs in upsert() may overwrite data unexpectedly.
    • Fix: Use UUIDs or generate IDs server-side:
      $id = Uuid::v7();
      $this->qdrantStore->upsert($vector, $payload, $id);
      

Debugging Tips

  • Enable HTTP Debugging:

    # config/packages/dev/http_client.yaml
    framework:
        http_client:
            scoped_clients:
                qdrant:
                    options:
                        debug: true
    

    Check logs for raw Qdrant API requests/responses.

  • Query Logging:

    $this->logger->debug('Qdrant Query', [
        'vector' => $queryVector,
        'filter' => $filter,
        'limit' => $limit,
    ]);
    
  • Collection Inspection: Use Qdrant’s API to verify collections:

    curl -X GET "http://localhost:6333/collections/my_collection"
    

Extension Points

  1. Custom Query Builders:

    • Extend QdrantStore to add domain-specific query methods:
      class CustomQdrantStore extends QdrantStore {
          public function searchByCategory(string $category, int $limit): array {
              return $this->query(
                  $this->getQueryVector(),
                  filter: ['must' => [['key' => 'category', 'match' => ['value' => $category]]]],
                  limit: $limit
              );
          }
      }
      
  2. Event Listeners:

    • Hook into upsert()/remove() to trigger side effects (e.g., analytics):
      $store->addListener('upsert', function ($vector, $payload, $id) {
          $this->analytics->track('vector_upsert', ['id' => $id]);
      });
      
  3. Fallback Strategies:

    • Implement a fallback store (e.g., Redis) for high availability:
      try {
          return $this->qdrantStore->query(...);
      } catch (StoreException $e) {
          return $this->fallbackStore->query(...);
      }
      

Configuration Quirks

  • API Key Handling:

    • Avoid hardcoding keys; use Symfony’s %env(QDRANT_API_KEY)% or a secrets manager.
  • Collection Defaults:

    • If collection is omitted, the store uses a default named default. Override in config:
      framework:
          ai:
              stores:
                  qdrant:
                      collection: 'custom_collection'
      
  • Vector Distance Metrics:

    • Ensure distance (e.g., Cosine, Dot) matches your use case. Defaults to Cosine:
      framework:
          ai:
              stores:
                  qdrant:
                      options:
                          vectors:
                              distance: Dot
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope