Skip to content

Commit c0d955f

Browse files
Guikingonechr-hertel
authored andcommitted
[Store] Add Milvus
1 parent 3a160d5 commit c0d955f

File tree

11 files changed

+596
-7
lines changed

11 files changed

+596
-7
lines changed

examples/.env

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,36 @@ ALBERT_API_URL=
8383
# For MariaDB store. Server defined in compose.yaml
8484
MARIADB_URI=pdo-mysql://[email protected]:3309/my_database
8585

86-
# Meilisearch
86+
# Meilisearch (store)
8787
MEILISEARCH_HOST=http://127.0.0.1:7700
8888
MEILISEARCH_API_KEY=changeMe
8989

9090
# For using LMStudio
9191
LMSTUDIO_HOST_URL=http://127.0.0.1:1234
9292

93-
# Qdrant
93+
# Qdrant (store)
9494
QDRANT_HOST=http://127.0.0.1:6333
9595
QDRANT_SERVICE_API_KEY=changeMe
9696

97-
# SurrealDB
97+
# SurrealDB (store)
9898
SURREALDB_HOST=http://127.0.0.1:8000
9999
SURREALDB_USER=symfony
100100
SURREALDB_PASS=symfony
101101

102-
# Neo4J
102+
# Neo4J (store)
103103
NEO4J_HOST=http://127.0.0.1:7474
104104
NEO4J_DATABASE=neo4j
105105
NEO4J_USERNAME=neo4j
106106
NEO4J_PASSWORD=symfonyai
107107

108-
# Typesense
108+
# Typesense (store)
109109
TYPESENSE_HOST=http://127.0.0.1:8108
110110
TYPESENSE_API_KEY=changeMe
111111

112+
# Milvus (store)
113+
MILVUS_HOST=http://127.0.0.1:19530
114+
MILVUS_API_KEY=root:Milvus
115+
MILVUS_DATABASE=symfony
116+
112117
# Cerebras
113118
CEREBRAS_API_KEY=

examples/compose.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,69 @@ services:
5656
ports:
5757
- '8108:8108'
5858

59+
# Milvus services
60+
etcd:
61+
container_name: milvus-etcd
62+
image: quay.io/coreos/etcd:v3.5.18
63+
environment:
64+
- ETCD_AUTO_COMPACTION_MODE=revision
65+
- ETCD_AUTO_COMPACTION_RETENTION=1000
66+
- ETCD_QUOTA_BACKEND_BYTES=4294967296
67+
- ETCD_SNAPSHOT_COUNT=50000
68+
volumes:
69+
- etcd_vlm:/etcd
70+
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
71+
healthcheck:
72+
test: [ "CMD", "etcdctl", "endpoint", "health" ]
73+
interval: 30s
74+
timeout: 20s
75+
retries: 3
76+
77+
minio:
78+
container_name: milvus-minio
79+
image: minio/minio:RELEASE.2024-12-18T13-15-44Z
80+
environment:
81+
MINIO_ACCESS_KEY: minioadmin
82+
MINIO_SECRET_KEY: minioadmin
83+
ports:
84+
- '9001:9001'
85+
- '9000:9000'
86+
volumes:
87+
- minio_vlm:/minio_data
88+
command: minio server /minio_data --console-address ":9001"
89+
healthcheck:
90+
test: [ "CMD", "curl", "-f", "http://localhost:9000/minio/health/live" ]
91+
interval: 30s
92+
timeout: 20s
93+
retries: 3
94+
95+
milvus:
96+
container_name: milvus-standalone
97+
image: milvusdb/milvus:v2.6.0
98+
command: ["milvus", "run", "standalone"]
99+
security_opt:
100+
- seccomp:unconfined
101+
environment:
102+
ETCD_ENDPOINTS: etcd:2379
103+
MINIO_ADDRESS: minio:9000
104+
MQ_TYPE: woodpecker
105+
volumes:
106+
- milvus_vlm:/var/lib/milvus
107+
healthcheck:
108+
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
109+
interval: 30s
110+
start_period: 90s
111+
timeout: 20s
112+
retries: 3
113+
ports:
114+
- '19530:19530'
115+
- '9091:9091'
116+
depends_on:
117+
- 'etcd'
118+
- 'minio'
119+
59120
volumes:
60121
typesense_data:
122+
etcd_vlm:
123+
minio_vlm:
124+
milvus_vlm:

examples/rag/milvus.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\Toolbox\AgentProcessor;
14+
use Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch;
15+
use Symfony\AI\Agent\Toolbox\Toolbox;
16+
use Symfony\AI\Fixtures\Movies;
17+
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
18+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
19+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
20+
use Symfony\AI\Platform\Message\Message;
21+
use Symfony\AI\Platform\Message\MessageBag;
22+
use Symfony\AI\Store\Bridge\Milvus\Store;
23+
use Symfony\AI\Store\Document\Metadata;
24+
use Symfony\AI\Store\Document\TextDocument;
25+
use Symfony\AI\Store\Document\Vectorizer;
26+
use Symfony\AI\Store\Indexer;
27+
use Symfony\Component\Uid\Uuid;
28+
29+
require_once dirname(__DIR__).'/bootstrap.php';
30+
31+
// initialize the store
32+
$store = new Store(
33+
httpClient: http_client(),
34+
endpointUrl: env('MILVUS_HOST'),
35+
apiKey: env('MILVUS_API_KEY'),
36+
database: env('MILVUS_DATABASE'),
37+
collection: 'movies',
38+
);
39+
40+
// initialize the index
41+
$store->initialize();
42+
43+
// create embeddings and documents
44+
$documents = [];
45+
foreach (Movies::all() as $i => $movie) {
46+
$documents[] = new TextDocument(
47+
id: Uuid::v4(),
48+
content: 'Title: '.$movie['title'].\PHP_EOL.'Director: '.$movie['director'].\PHP_EOL.'Description: '.$movie['description'],
49+
metadata: new Metadata($movie),
50+
);
51+
}
52+
53+
// create embeddings for documents
54+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
55+
$vectorizer = new Vectorizer($platform, $embeddings = new Embeddings());
56+
$indexer = new Indexer($vectorizer, $store, logger());
57+
$indexer->index($documents);
58+
59+
$model = new Gpt(Gpt::GPT_4O_MINI);
60+
61+
$similaritySearch = new SimilaritySearch($platform, $embeddings, $store);
62+
$toolbox = new Toolbox([$similaritySearch], logger: logger());
63+
$processor = new AgentProcessor($toolbox);
64+
$agent = new Agent($platform, $model, [$processor], [$processor], logger());
65+
66+
$messages = new MessageBag(
67+
Message::forSystem('Please answer all user questions only using SimilaritySearch function.'),
68+
Message::ofUser('Which movie fits the theme of technology?')
69+
);
70+
$result = $agent->call($messages);
71+
72+
echo $result->getContent().\PHP_EOL;

src/ai-bundle/config/options.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,21 @@
227227
->end()
228228
->end()
229229
->end()
230+
->arrayNode('milvus')
231+
->normalizeKeys(false)
232+
->useAttributeAsKey('name')
233+
->arrayPrototype()
234+
->children()
235+
->scalarNode('endpoint')->cannotBeEmpty()->end()
236+
->scalarNode('api_key')->isRequired()->end()
237+
->scalarNode('database')->isRequired()->end()
238+
->scalarNode('collection')->isRequired()->end()
239+
->scalarNode('vector_field')->end()
240+
->scalarNode('dimensions')->end()
241+
->scalarNode('metric_type')->end()
242+
->end()
243+
->end()
244+
->end()
230245
->arrayNode('mongodb')
231246
->normalizeKeys(false)
232247
->useAttributeAsKey('name')

src/ai-bundle/src/AiBundle.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
use Symfony\AI\Store\Bridge\Local\DistanceStrategy;
4949
use Symfony\AI\Store\Bridge\Local\InMemoryStore;
5050
use Symfony\AI\Store\Bridge\Meilisearch\Store as MeilisearchStore;
51+
use Symfony\AI\Store\Bridge\Milvus\Store as MilvusStore;
5152
use Symfony\AI\Store\Bridge\MongoDb\Store as MongoDbStore;
5253
use Symfony\AI\Store\Bridge\Neo4j\Store as Neo4jStore;
5354
use Symfony\AI\Store\Bridge\Pinecone\Store as PineconeStore;
@@ -634,6 +635,37 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde
634635
}
635636
}
636637

638+
if ('milvus' === $type) {
639+
foreach ($stores as $name => $store) {
640+
$arguments = [
641+
new Reference('http_client'),
642+
$store['endpoint'],
643+
$store['api_key'],
644+
$store['database'],
645+
$store['collection'],
646+
];
647+
648+
if (\array_key_exists('vector_field', $store)) {
649+
$arguments[5] = $store['vector_field'];
650+
}
651+
652+
if (\array_key_exists('dimensions', $store)) {
653+
$arguments[6] = $store['dimensions'];
654+
}
655+
656+
if (\array_key_exists('metric_type', $store)) {
657+
$arguments[7] = $store['metric_type'];
658+
}
659+
660+
$definition = new Definition(MilvusStore::class);
661+
$definition
662+
->addTag('ai.store')
663+
->setArguments($arguments);
664+
665+
$container->setDefinition('ai.store.'.$type.'.'.$name, $definition);
666+
}
667+
}
668+
637669
if ('mongodb' === $type) {
638670
foreach ($stores as $name => $store) {
639671
$arguments = [

src/ai-bundle/tests/DependencyInjection/AiBundleTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,17 @@ private function getFullConfig(): array
393393
'strategy' => 'cosine',
394394
],
395395
],
396+
'milvus' => [
397+
'my_milvus_store' => [
398+
'endpoint' => 'http://127.0.0.1:19530',
399+
'api_key' => 'foo',
400+
'database' => 'test',
401+
'collection' => 'default',
402+
'vector_field' => '_vectors',
403+
'dimensions' => 768,
404+
'metric_type' => 'COSINE',
405+
],
406+
],
396407
'mongodb' => [
397408
'my_mongo_store' => [
398409
'database' => 'my_db',

src/store/doc/index.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ You can find more advanced usage in combination with an Agent using the store fo
4040
* `Similarity Search with MariaDB (RAG)`_
4141
* `Similarity Search with Meilisearch (RAG)`_
4242
* `Similarity Search with memory storage (RAG)`_
43+
* `Similarity Search with Milvus (RAG)`_
4344
* `Similarity Search with MongoDB (RAG)`_
4445
* `Similarity Search with Neo4j (RAG)`_
4546
* `Similarity Search with Pinecone (RAG)`_
@@ -62,6 +63,7 @@ Supported Stores
6263
* `InMemory`_
6364
* `MariaDB`_ (requires `ext-pdo`)
6465
* `Meilisearch`_
66+
* `Milvus`_
6567
* `MongoDB Atlas`_ (requires `mongodb/mongodb` as additional dependency)
6668
* `Neo4j`_
6769
* `Pinecone`_ (requires `probots-io/pinecone-php` as additional dependency)
@@ -101,9 +103,10 @@ This leads to a store implementing two methods::
101103

102104
.. _`Retrieval Augmented Generation`: https://de.wikipedia.org/wiki/Retrieval-Augmented_Generation
103105
.. _`Similarity Search with MariaDB (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/mariadb-gemini.php
104-
.. _`Similarity Search with MongoDB (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/mongodb.php
105106
.. _`Similarity Search with Meilisearch (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/meilisearch.php
106107
.. _`Similarity Search with memory storage (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/in-memory.php
108+
.. _`Similarity Search with Milvus (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/meilisearch.php
109+
.. _`Similarity Search with MongoDB (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/milvus.php
107110
.. _`Similarity Search with Neo4j (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/neo4j.php
108111
.. _`Similarity Search with Pinecone (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/pinecone.php
109112
.. _`Similarity Search with Symfony Cache (RAG)`: https://github.com/symfony/ai/blob/main/examples/rag/cache.php
@@ -113,10 +116,11 @@ This leads to a store implementing two methods::
113116
.. _`Azure AI Search`: https://azure.microsoft.com/products/ai-services/ai-search
114117
.. _`Chroma`: https://www.trychroma.com/
115118
.. _`MariaDB`: https://mariadb.org/projects/mariadb-vector/
116-
.. _`MongoDB Atlas`: https://www.mongodb.com/atlas
117119
.. _`Pinecone`: https://www.pinecone.io/
118120
.. _`Postgres`: https://www.postgresql.org/about/news/pgvector-070-released-2852/
119121
.. _`Meilisearch`: https://www.meilisearch.com/
122+
.. _`Milvus`: https://milvus.io/
123+
.. _`MongoDB Atlas`: https://www.mongodb.com/atlas
120124
.. _`SurrealDB`: https://surrealdb.com/
121125
.. _`InMemory`: https://www.php.net/manual/en/language.types.array.php
122126
.. _`Qdrant`: https://qdrant.tech/

0 commit comments

Comments
 (0)