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

symfony/ai-typesense-store

Typesense Store integrates the Typesense vector database with Symfony AI Store, enabling vector indexing and similarity search via Typesense’s vector search API. Part of the Symfony AI ecosystem, with issues and PRs handled in the main Symfony AI repo.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies:
    composer require symfony/ai symfony/ai-typesense-store typesense/typesense
    
  2. Configure Typesense Client (in config/typesense.php):
    return [
        'client' => [
            'nodes' => ['http://localhost:8108'],
            'api_key' => 'your-api-key',
            'connection_timeout_seconds' => 2,
        ],
        'collection' => 'your_collection_name',
        'vector_dimension' => 384, // Match your embedding size
    ];
    
  3. Register the Store (in a service provider):
    $this->app->bind(\Symfony\Contracts\Ai\StoreInterface::class, function ($app) {
        $client = new \Typesense\Typesense(
            $app['config']['typesense.client']
        );
        return new \Symfony\AI\TypesenseStore\TypesenseStore(
            $client,
            $app['config']['typesense.collection'],
            $app['config']['typesense.vector_dimension']
        );
    });
    
  4. First Use Case (Embedding Storage):
    use Symfony\Contracts\Ai\StoreInterface;
    
    class ChatService {
        public function __construct(private StoreInterface $store) {}
    
        public function storeEmbedding(array $embedding, array $metadata) {
            $this->store->add($embedding, $metadata);
        }
    
        public function findSimilar(array $embedding, int $limit = 5) {
            return $this->store->find($embedding, $limit);
        }
    }
    

Where to Look First

  • Symfony AI Store Interface: symfony/ai for method signatures (add(), find(), remove()).
  • Typesense API Docs: Vector Search Guide for collection schema and query tuning.
  • Package Source: TypesenseStore class for advanced usage (e.g., filters, custom metrics).

Implementation Patterns

Core Workflows

1. Embedding Storage and Retrieval (RAG Pipeline)

// Store embeddings with metadata
$store->add($embeddingArray, [
    'document_id' => 'doc_123',
    'source' => 'user_guide',
    'category' => 'laravel'
]);

// Retrieve top-3 similar embeddings with filters
$results = $store->find($queryEmbedding, 3, [
    'filter_by' => 'category:"laravel" AND source:"user_guide"',
    'include_metadata' => true
]);

2. Bulk Operations

// Batch insert (Typesense supports bulk API)
$store->addMany([
    [$embedding1, $metadata1],
    [$embedding2, $metadata2],
]);

// Batch delete by metadata
$store->removeMany([
    ['document_id' => 'doc_123'],
    ['document_id' => 'doc_456']
]);

3. Hybrid Search (Vector + Metadata)

// Combine semantic and keyword search
$results = $store->find($embedding, 10, [
    'filter_by' => 'category:"php" AND rating>4',
    'query_by' => 'vector', // Default; can also use 'keyword'
]);

Integration Tips

Laravel-Specific Patterns

  1. Service Container Binding:

    // Bind with config overrides
    $this->app->bind(StoreInterface::class, function ($app) {
        return new TypesenseStore(
            new TypesenseClient($app['config']['typesense.client']),
            $app['config']['typesense.collection'],
            $app['config']['typesense.vector_dimension'],
            $app['config']['typesense.timeout'] ?? 5.0
        );
    });
    
  2. Queue Jobs for Async Operations:

    use Illuminate\Bus\Queueable;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class StoreEmbeddingJob implements ShouldQueue
    {
        use Queueable;
    
        public function __construct(
            private array $embedding,
            private array $metadata
        ) {}
    
        public function handle(StoreInterface $store) {
            $store->add($this->embedding, $this->metadata);
        }
    }
    
  3. Caching Layer:

    // Cache frequent queries (e.g., top-5 recommendations)
    $cacheKey = 'recommendations:' . $userId;
    $results = Cache::remember($cacheKey, now()->addMinutes(10), function () use ($store, $embedding) {
        return $store->find($embedding, 5);
    });
    

Advanced Patterns

  1. Dynamic Collection Management:

    // Create collection if it doesn’t exist
    $client = new TypesenseClient($config);
    $collection = $client->collections()->retrieve('your_collection');
    if (!$collection) {
        $client->collections()->create([
            'name' => 'your_collection',
            'fields' => [
                ['name' => 'vector', 'type' => 'float[]', 'facet' => false],
                ['name' => 'document_id', 'type' => 'string'],
                ['name' => 'category', 'type' => 'string'],
            ],
            'default_sorting_field' => 'vector',
        ]);
    }
    
  2. Custom Metrics for Observability:

    // Extend TypesenseStore to track query metrics
    class InstrumentedTypesenseStore extends TypesenseStore
    {
        public function find(array $vector, int $limit = 10, array $options = []): array
        {
            $start = microtime(true);
            $results = parent::find($vector, $limit, $options);
            $duration = microtime(true) - $start;
    
            // Log or send to APM
            \Log::info('Typesense query', [
                'duration_ms' => $duration * 1000,
                'limit' => $limit,
                'vector_dim' => count($vector),
            ]);
    
            return $results;
        }
    }
    
  3. Schema Migrations:

    // Add a new field to the collection
    $client->collections()->update('your_collection', [
        'fields' => [
            ['name' => 'vector', 'type' => 'float[]'],
            ['name' => 'document_id', 'type' => 'string'],
            ['name' => 'updated_at', 'type' => 'int64'], // New field
        ],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Vector Dimension Mismatch:

    • Issue: Storing a 384-dim vector in a collection configured for 1536-dim vectors will fail silently or corrupt data.
    • Fix: Validate dimensions in a TypesenseStore constructor:
      public function __construct(..., private int $expectedDimension) {
          if (count($embedding) !== $expectedDimension) {
              throw new \InvalidArgumentException("Vector dimension mismatch");
          }
      }
      
  2. Filter Syntax Errors:

    • Issue: Typesense uses a strict filter syntax. Malformed filters (e.g., category:"laravel" vs. category:laravel) cause silent failures.
    • Fix: Use a validator or library like typesense-filter-parser to sanitize filters.
  3. Rate Limiting:

    • Issue: Typesense’s default rate limits (e.g., 1000 requests/minute) may be hit during bulk operations.
    • Fix: Implement exponential backoff in custom clients:
      use Symfony\Component\Process\Exception\ProcessFailedException;
      
      try {
          $client->collections()->retrieve($collectionName);
      } catch (ProcessFailedException $e) {
          if (str_contains($e->getMessage(), 'rate limit')) {
              sleep(2); // Backoff
              retry();
          }
          throw $e;
      }
      
  4. Metadata Field Types:

    • Issue: Typesense infers field types on first insert. Changing metadata types later (e.g., stringint) requires collection recreation.
    • Fix: Define all fields upfront in the collection schema.
  5. Embedding Normalization:

    • Issue: Unnormalized embeddings (e.g., L2 norm ≠ 1) can skew similarity scores.
    • Fix: Normalize embeddings before storage:
      $normalized = array_map(function ($val) {
          return $val / array_sum(array_map('pow', $embedding, $embedding));
      }, $embedding);
      

Debugging Tips

  1. Enable Typesense Logging:
    $client = new TypesenseClient([
        'nodes' => ['http://localhost:8108
    
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.
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php
trappistes/laravel-custom-fields
splash/sonata-admin
splash/metadata