symfony/ai-maria-db-store
MariaDB vector store integration for Symfony AI Store. Requires MariaDB 11.7+ for VECTOR columns, vector indexing, and distance search. Useful for building RAG and similarity search apps backed by MariaDB.
Install the Package:
composer require symfony/ai-maria-db-store
Ensure your composer.json includes Symfony’s AI components if not already present:
"require": {
"symfony/ai": "^0.8",
"symfony/dependency-injection": "^7.0"
}
Configure MariaDB:
mariadb --version).VECTOR column:
CREATE TABLE ai_embeddings (
id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT,
metadata JSON,
embedding VECTOR(1536), -- Adjust dimensions to your embedding size
INDEX vec_idx USING HNSW(embedding) WITH (distance_type = 'COSINE')
) ENGINE=InnoDB;
.env:
DB_MARIADB_CONNECTION=mariadb
DB_MARIADB_URL="mysql://user:pass@host/db?serverVersion=11.7"
Register the Store:
Add a service provider (e.g., App\Providers\MariaDbStoreServiceProvider):
use Symfony\Component\AI\Store\AiStoreInterface;
use Symfony\AI\MariaDbStore\MariaDbStore;
public function register()
{
$this->app->singleton(AiStoreInterface::class, function ($app) {
return new MariaDbStore(
$app['db']->connection('mariadb')->getPdo(),
[
'table' => 'ai_embeddings',
'vector_column' => 'embedding',
'distance' => 'cosine',
'dimensions' => 1536,
]
);
});
}
First Use Case: Insert and query embeddings in a Laravel controller:
use Symfony\Component\AI\Store\AiStoreInterface;
public function storeEmbedding(AiStoreInterface $store)
{
$embedding = [0.1, 0.2, ..., 0.1]; // Your 1536-dim vector
$store->insert([
'content' => 'Sample text',
'metadata' => ['category' => 'tech'],
'embedding' => $embedding,
]);
// Query with similarity
$results = $store->query($embedding, [
'limit' => 5,
'filter' => ['category' => 'tech'],
]);
}
CRUD Operations:
insert() for single records or insertMany() for batches:
$store->insertMany([
['content' => 'Doc 1', 'embedding' => $vec1, 'metadata' => [...]],
['content' => 'Doc 2', 'embedding' => $vec2, 'metadata' => [...]],
]);
insert() (no native update; use remove() + insert()).$store->remove(['id' => 1]); // By ID
$store->remove(['category' => 'deprecated']); // By metadata filter
Hybrid Queries: Combine vector similarity with SQL filters:
$results = $store->query($queryVector, [
'limit' => 10,
'filter' => [
'category' => 'tech',
'created_at' => ['>', '2023-01-01'],
],
]);
WHERE syntax (e.g., JSON_EXTRACT(metadata, '$.priority') > 5).Batch Processing:
insertMany() for efficiency (test with 1K+ records).dispatch(new ProcessEmbeddings($store, $batch));
Schema Management:
dimensions change (no ALTER TABLE support for VECTOR).ALTER TABLE ai_embeddings ADD INDEX vec_idx USING HNSW(embedding);
Laravel-Specific:
class EmbeddingRepository {
public function __construct(private AiStoreInterface $store) {}
public function findSimilar($vector, array $filters = []) {
return $this->store->query($vector, ['filter' => $filters]);
}
}
EmbeddingStored):
event(new EmbeddingStored($record));
Symfony Abstraction:
AiStoreInterface for custom methods:
interface CustomStoreInterface extends AiStoreInterface {
public function getByMetadata(array $filters);
}
Testing:
$store = $this->createMock(AiStoreInterface::class);
$store->method('query')->willReturn([...]);
MariaDB Version:
Unknown column type 'VECTOR' → You’re on MariaDB <11.7.pgvector).Distance Functions:
Unknown system variable 'distance_type' → HNSW index misconfiguration.COSINE or L2 (Euclidean) explicitly:
INDEX vec_idx USING HNSW(embedding) WITH (distance_type = 'COSINE')
Vector Dimensions:
Data too long for column 'embedding' → Mismatched dimensions.dimensions in config match the VECTOR(N) column.Hybrid Query Limits:
SQLSTATE[HY000]: General error: 1118 → Complex filters may fail.$store->query($vector, ['filter' => ['raw' => 'category = ? AND priority > ?', ['tech', 5]]]);
Laravel-Symfony Conflicts:
Class 'Symfony\Component\AI\Store\AiStoreInterface' not found.symfony/ai is installed and autoloaded.[mysqld]
general_log = 1
general_log_file = /var/log/mysql/mariadb-query.log
DB::enableQueryLog() to capture raw SQL:
DB::enableQueryLog();
$store->query($vector);
dd(DB::getQueryLog());
Indexing Overhead:
-- Disable index temporarily for bulk inserts
ALTER TABLE ai_embeddings DROP INDEX vec_idx;
-- Insert data
ALTER TABLE ai_embeddings ADD INDEX vec_idx;
Batch Size:
insertMany() batch size: 500–2000 records (benchmark with EXPLAIN).Distance Metrics:
Custom Distance Functions:
Override the store’s getDistanceSql() method:
class CustomMariaDbStore extends MariaDbStore {
protected function getDistanceSql(string $column, string $distance): string
{
return match ($distance) {
'custom' => "1 - (($column) * $this->getVectorPlaceholder())",
default => parent::getDistanceSql($column, $distance),
};
}
}
Metadata Serialization: Extend to handle custom metadata formats (e.g., arrays):
protected function serializeMetadata(array $metadata): string
{
return json_encode($metadata, JSON_THROW_ON_ERROR);
}
Async Operations: Use Laravel Queues for long-running queries:
class ProcessVectorQuery implements ShouldQueue {
public function handle(AiStoreInterface $store) {
$store->query
How can I help you explore Laravel packages today?