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 Open Search Store Laravel Package

symfony/ai-open-search-store

OpenSearch vector store integration for Symfony AI Store. Index and query embeddings using OpenSearch knn_vector fields and k‑NN/approximate k‑NN search. Links to OpenSearch docs and contribution resources in the main Symfony AI repo.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies:
    composer require symfony/ai-open-search-store symfony/ai symfony/http-client opensearch/opensearch
    
  2. Configure OpenSearch Client: Create a client instance in config/opensearch.php:
    return [
        'client' => OpenSearch\ClientBuilder::create()
            ->setHosts(['http://localhost:9200'])
            ->build(),
    ];
    
  3. Set Up Index: Define an index with knn_vector field (e.g., via opensearch-php client or API):
    curl -X PUT "localhost:9200/vector_index" -H 'Content-Type: application/json' -d'
    {
      "mappings": {
        "properties": {
          "embedding": { "type": "knn_vector", "dimension": 768 }
        }
      }
    }'
    
  4. First Query: Use Symfony’s OpenSearchStore to fetch nearest vectors:
    use Symfony\Component\AI\Store\OpenSearchStore;
    use OpenSearch\Client;
    
    $client = config('opensearch.client');
    $store = new OpenSearchStore($client, 'vector_index');
    
    $results = $store->nearest([0.1, 0.2, ...], limit: 5); // Replace with actual embedding
    

Where to Look First

First Use Case

Semantic Search:

  1. Generate embeddings for documents (e.g., using symfony/ai or Hugging Face).
  2. Store embeddings in OpenSearch:
    $store->add('doc_id', ['embedding' => $embeddingArray]);
    
  3. Query for similar documents:
    $similarDocs = $store->nearest($queryEmbedding, limit: 3);
    

Implementation Patterns

Usage Patterns

1. CRUD Operations

  • Add/Update:
    $store->add('id_123', ['embedding' => $vector, 'metadata' => ['title' => 'Doc']]);
    
  • Remove:
    $store->remove('id_123'); // Requires OpenSearch 2.4+
    
  • Batch Operations: Use OpenSearch’s bulk API via the client (not directly supported by the bridge).

2. Query Patterns

  • Basic k-NN Search:
    $results = $store->nearest($vector, limit: 5);
    
  • Filtered Search (Symfony AI v6.4+):
    $results = $store->nearest($vector, limit: 5, filter: [
        'term' => ['category' => 'tech']
    ]);
    
  • Approximate Search: Configure engine in the index (e.g., hnsw):
    "embedding": {
      "type": "knn_vector",
      "dimension": 768,
      "method": { "name": "hnsw", "space_type": "l2", "engine": "lucene" }
    }
    

3. Hybrid Search

Combine keyword and vector queries:

$client->search([
    'index' => 'vector_index',
    'body' => [
        'query' => [
            'bool' => [
                'must' => [
                    'knn' => ['embedding' => ['vector' => $vector, 'k' => 5]],
                    'match' => ['title' => 'AI']
                ]
            ]
        ]
    ]
]);

Workflows

Embedding Pipeline

  1. Generate Embeddings: Use symfony/ai or a custom model (e.g., SentenceTransformer):
    $embedding = $model->embed('Your text here');
    
  2. Store in OpenSearch:
    $store->add('doc_id', ['embedding' => $embedding->toArray()]);
    
  3. Retrieve for RAG:
    $context = $store->nearest($queryEmbedding, limit: 3);
    

Periodic Indexing

Use Laravel’s scheduling to refresh embeddings:

// app/Console/Commands/RefreshEmbeddings.php
public function handle() {
    $docs = Document::all();
    foreach ($docs as $doc) {
        $embedding = $model->embed($doc->content);
        $store->add($doc->id, ['embedding' => $embedding->toArray()]);
    }
}

Schedule:

// app/Console/Kernel.php
protected function schedule(Schedule $schedule) {
    $schedule->command('refresh:embeddings')->daily();
}

Integration Tips

Laravel Service Container

Bind the store as a singleton:

// app/Providers/AppServiceProvider.php
public function register() {
    $this->app->singleton(\Symfony\Component\AI\Store\OpenSearchStore::class, function ($app) {
        return new \Symfony\Component\AI\Store\OpenSearchStore(
            $app['opensearch.client'],
            'vector_index'
        );
    });
}

Query Builder Abstraction

Create a fluent query builder:

// app/Services/OpenSearchQueryBuilder.php
class OpenSearchQueryBuilder {
    public function nearest(array $vector, int $limit = 5): array {
        return $this->store->nearest($vector, $limit);
    }

    public function withFilter(array $filter): self {
        $this->filter = $filter;
        return $this;
    }
}

Error Handling

Wrap operations in try-catch:

try {
    $results = $store->nearest($vector);
} catch (\OpenSearch\Common\Exceptions\ClientException $e) {
    Log::error('OpenSearch query failed', ['error' => $e->getMessage()]);
    return [];
}

Gotchas and Tips

Pitfalls

1. OpenSearch Cluster Requirements

  • Vector Search Plugin: Ensure OpenSearch has the vector-search plugin installed:
    bin/opensearch-plugin install analysis-icu
    bin/opensearch-plugin install vector-search
    
  • Index Configuration: knn_vector fields require dimension and optionally method (e.g., hnsw). Mismatched dimensions cause errors.

2. Symfony Dependency Conflicts

  • Namespace Collisions: Symfony’s StoreInterface may conflict with Laravel’s Store facade. Use aliases:
    'aliases' => [
        'SymfonyStore' => \Symfony\Component\AI\Store\StoreInterface::class,
    ],
    
  • Autoloading: Ensure vendor/symfony/ai is not excluded from composer.json autoload.

3. Approximate NN Trade-offs

  • Precision vs. Speed: hnsw is faster but less precise than brute-force. Test with your data:
    "method": { "name": "hnsw", "space_type": "l2", "engine": "lucene", "parameters": { "ef_construction": 128, "m": 24 } }
    
  • Dimensionality Limits: OpenSearch’s hnsw struggles with >1000D vectors. Use PCA or dimensionality reduction if needed.

4. Rate Limiting

  • OpenSearch may throttle high-frequency queries. Use exponential backoff:
    use Symfony\Component\Process\Exception\ProcessFailedException;
    
    try {
        $results = $store->nearest($vector);
    } catch (ProcessFailedException $e) {
        sleep(2 ** $attempt++); // Exponential backoff
        retry();
    }
    

Debugging

Common Errors

Error Cause Solution
Invalid dimension Vector size mismatch in index definition. Recreate index with correct dimension.
No mapping for [field] Field not defined in index mappings. Add field to index mappings.
knn query not supported Missing vector search plugin. Install vector-search plugin.
Symfony\Component\AI\Exception\StoreException Invalid query syntax. Check OpenSearch query DSL docs
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky