symfony/ai-milvus-store
Milvus Store adds Milvus vector database support to Symfony AI Store. Connect to a Milvus instance, create collections, insert vectors, run similarity searches, and apply boolean filter expressions using Milvus REST APIs.
Install the Package:
composer require symfony/ai-milvus-store
Configure Symfony AI:
Add Milvus store configuration to config/packages/ai.yaml:
framework:
ai:
stores:
milvus:
type: MilvusStore
uri: "http://your-milvus-server:19530" # Replace with your Milvus endpoint
collection: "your_collection_name" # Pre-created collection
options:
consistency_level: "Strong"
First Use Case - Inserting Vectors:
use Symfony\AI\Store\StoreInterface;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('ai.store')]
class MyService {
public function __construct(
private StoreInterface $milvusStore
) {}
public function addVector(array $vector, array $metadata): void {
$this->milvusStore->add($vector, $metadata);
}
}
First Use Case - Searching Vectors:
public function searchVectors(array $queryVector, int $limit = 5): array {
return $this->milvusStore->nearest(
$queryVector,
$limit,
filter: ['category' => 'tech'] // Example filter
);
}
Insertion:
$this->milvusStore->add($vector, ['metadata' => 'value']);
symfony/ai's EmbeddingGenerator).$this->milvusStore->addMany([[$vector1, $metadata1], [$vector2, $metadata2]]);
Deletion:
$this->milvusStore->remove($vectorId); // By primary key
$this->milvusStore->removeMany([$id1, $id2]); // Bulk delete
Basic Nearest Neighbors:
$results = $this->milvusStore->nearest($queryVector, 10);
Filtered Search:
$results = $this->milvusStore->nearest(
$queryVector,
5,
filter: ['AND' => [
['category' => 'books'],
['rating' => ['$gt' => 4]]
]]
);
Hybrid Search: Combine vector similarity with metadata:
$results = $this->milvusStore->nearest(
$queryVector,
5,
filter: ['OR' => [
['author' => 'J.K. Rowling'],
['genre' => 'fantasy']
]]
);
// Check if collection exists (manual step; not in package)
if (!$this->milvusStore->collectionExists('dynamic_collection')) {
$this->createCollection('dynamic_collection', 768); // 768-dim vectors
}
Embedding Pipeline:
use Symfony\AI\EmbeddingGeneratorInterface;
public function generateAndStoreEmbedding(string $text): void {
$embedding = $this->embeddingGenerator->generate($text);
$this->milvusStore->add($embedding, ['text' => $text, 'source' => 'user']);
}
Retriever Integration:
use Symfony\AI\RetrieverInterface;
class MilvusRetriever implements RetrieverInterface {
public function __construct(private StoreInterface $milvusStore) {}
public function retrieve(string $query, int $limit = 3): array {
$vector = $this->embeddingGenerator->generate($query);
return $this->milvusStore->nearest($vector, $limit);
}
}
use Symfony\Component\Messenger\MessageBusInterface;
public function __construct(
private StoreInterface $milvusStore,
private MessageBusInterface $bus
) {}
public function asyncBatchInsert(array $vectors): void {
$this->bus->dispatch(new BatchInsertMessage($vectors));
}
#[AsMessageHandler]
public function handle(BatchInsertMessage $message): void {
$this->milvusStore->addMany($message->getVectors());
}
use Symfony\Contracts\Cache\CacheInterface;
public function __construct(
private StoreInterface $milvusStore,
private CacheInterface $cache
) {}
public function cachedSearch(array $queryVector, string $cacheKey): array {
return $this->cache->get($cacheKey, fn() =>
$this->milvusStore->nearest($queryVector, 10)
);
}
public function migrateCollection(string $collection, array $newSchema): void {
// Drop and recreate collection (Milvus REST API)
$this->milvusStore->dropCollection($collection);
$this->milvusStore->createCollection($collection, $newSchema);
// Reinsert data
}
use Symfony\Component\Retry\Retry;
public function safeNearest(array $vector, int $limit): array {
return Retry::create()
->withMaxRetries(3)
->withDelay(100)
->execute(fn() => $this->milvusStore->nearest($vector, $limit));
}
Gotcha: The package does not handle collection creation. You must:
"code": 400, "message": "Schema mismatch: expected 384 dim, got 768"
Tip: Use a migration script to ensure collections exist:
if (!$this->milvusStore->collectionExists('my_collection')) {
$this->milvusStore->createCollection('my_collection', [
'dimension' => 768,
'fields' => [
['name' => 'id', 'type' => 'INT64', 'is_primary' => true],
['name' => 'vector', 'type' => 'FLOAT_VECTOR', 'dim' => 768],
['name' => 'metadata', 'type' => 'JSON'],
],
]);
}
['AND' => [['field' => 'value'], ['field' => ['$gt' => 10]]]]
['field > 10 AND field2 = "value"'] // Will fail
Strong, Eventual, and Bounded consistency. Default is Strong, which may impact performance.
Eventual for read-heavy workloads:
options:
consistency_level: "
How can I help you explore Laravel packages today?