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 the Store in config/packages/ai.yaml:
framework:
ai:
stores:
milvus:
type: MilvusStore
uri: "http://your-milvus-server:19530" # Milvus REST API endpoint
collection: "your_collection_name" # Pre-created Milvus collection
options:
consistency_level: "Strong" # Strong/Eventual
timeout: 5.0 # API timeout (seconds)
First Use Case: Insert and Search Vectors
use Symfony\AI\Store\StoreInterface;
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
class VectorService {
public function __construct(
#[TaggedLocator('ai.store')]
iterable $stores
) {}
public function storeAndRetrieveVectors(): void {
$milvusStore = $stores['milvus']; // Get the Milvus store instance
// Insert a vector with metadata
$milvusStore->insert([
'id' => 'doc_123',
'vector' => [0.1, 0.2, 0.3, ...], // Your embedding
'metadata' => [
'category' => 'tech',
'source' => 'blog',
'timestamp' => '2023-01-01',
],
]);
// Search for similar vectors with metadata filter
$results = $milvusStore->search(
[0.15, 0.25, 0.35, ...], // Query vector
5, // Top-k results
[
'filter' => 'category = "tech" AND source = "blog"',
]
);
foreach ($results as $result) {
echo $result['id'] . ': ' . $result['distance'] . "\n";
}
}
}
Verify Milvus Collection Exists:
{
"collection_name": "your_collection_name",
"description": "App vectors",
"auto_id": false,
"fields": [
{
"name": "id",
"description": "Document ID",
"is_primary": true,
"data_type": "varchar",
"auto_id": false,
"max_length": 50
},
{
"name": "vector",
"description": "Embedding vector",
"is_primary": false,
"data_type": "float_vector",
"dim": 768 // Match your embedding dimension
},
{
"name": "category",
"description": "Document category",
"is_primary": false,
"data_type": "varchar",
"max_length": 50
},
{
"name": "source",
"description": "Document source",
"is_primary": false,
"data_type": "varchar",
"max_length": 50
}
]
}
$milvusStore->insert([
'id' => 'doc_456',
'vector' => $embeddingGenerator->generate('Your text here'),
'metadata' => [
'user_id' => 123,
'language' => 'en',
'is_public' => true,
],
]);
// Batch insert
$milvusStore->insertMany([
[
'id' => 'doc_789',
'vector' => [...],
'metadata' => [...],
],
// ... more documents
]);
$results = $milvusStore->search(
$queryVector,
10, // Top-k
[
'filter' => 'user_id = 123 AND language = "en" AND is_public = true',
'params' => [
'metric_type' => 'L2', // L2, IP, or Cosine
'params' => ['nprobe' => 10], // Index search parameter
],
]
);
// Note: Collection must exist in Milvus beforehand.
// This is a placeholder for future extensibility.
if (!$milvusStore->collectionExists('dynamic_collection')) {
// Trigger Milvus API call to create collection (not natively supported in this package).
// Consider wrapping Milvus CLI or API calls in a service.
}
// Delete by ID
$milvusStore->remove('doc_123');
// "Update" (replace entire entity)
$milvusStore->insert([
'id' => 'doc_123',
'vector' => $updatedEmbedding,
'metadata' => [...],
]);
Retriever for RAG pipelines:
use Symfony\AI\Retriever\RetrieverInterface;
class MilvusRetriever implements RetrieverInterface {
public function __construct(
private StoreInterface $milvusStore,
private EmbeddingGeneratorInterface $embeddingGenerator
) {}
public function retrieve(string $query, int $limit = 5): array {
$vector = $this->embeddingGenerator->generate($query);
return $this->milvusStore->search($vector, $limit)->toArray();
}
}
use Symfony\Component\Messenger\Attribute\AsMessage;
#[AsMessage]
class IndexVectorsMessage {
public function __construct(
public array $vectors,
public string $collection,
) {}
}
// Handler
class IndexVectorsHandler {
public function __construct(private MilvusStore $milvusStore) {}
public function __invoke(IndexVectorsMessage $message) {
$this->milvusStore->insertMany($message->vectors);
}
}
HttpClient middleware.# config/packages/http_client.yaml
framework:
http_client:
plugins:
- Symfony\Component\HttpClient\RetryMiddleware
- Symfony\Component\HttpClient\Middleware\TimeoutMiddleware
use Symfony\Contracts\Cache\CacheInterface;
class CachedMilvusStore {
public function __construct(
private MilvusStore $milvusStore,
private CacheInterface $cache
) {}
public function search(array $vector, int $limit, array $options = []): array {
$cacheKey = md5(serialize([$vector, $limit, $options]));
return $this->cache->get($cacheKey, fn() => $this->milvusStore->search($vector, $limit, $options));
}
}
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ValidatingMilvusStore {
public function __construct(
private MilvusStore $milvusStore,
private ValidatorInterface $validator
) {}
public function insert(array $entity): void {
$errors = $this->validator->validate($entity);
if (count($errors) > 0) {
throw new \InvalidArgumentException((string) $errors);
}
$this->milvusStore->insert($entity);
}
}
How can I help you explore Laravel packages today?