Skip to content

Commit 2237ed7

Browse files
committed
[Feature][Integration][Java] Add Milvus vector store integration
Signed-off-by: YangYanbin <warlock.yyb@alibaba-inc.com>
1 parent e617645 commit 2237ed7

17 files changed

Lines changed: 2287 additions & 43 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,18 @@ jobs:
265265
run: bash tools/build.sh
266266
- name: Install ollama
267267
run: bash tools/start_ollama_server.sh
268+
- name: Start Milvus
269+
run: |
270+
docker compose -f tools/docker/milvus/docker-compose.yml down -v
271+
docker compose -f tools/docker/milvus/docker-compose.yml up -d
272+
timeout 180 bash -c 'until curl -fsS http://localhost:9091/healthz; do sleep 5; done'
268273
- name: Run e2e tests
269274
env:
270275
LOG_LEVEL: INFO
271276
run: |
272277
export ES_HOST="http://localhost:9200"
273-
tools/e2e.sh
278+
export MILVUS_URI="http://localhost:19530"
279+
tools/e2e.sh
280+
- name: Stop Milvus
281+
if: always()
282+
run: docker compose -f tools/docker/milvus/docker-compose.yml down -v

api/src/main/java/org/apache/flink/agents/api/resource/ResourceName.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ public static final class VectorStore {
171171
public static final String ELASTICSEARCH_VECTOR_STORE =
172172
"org.apache.flink.agents.integrations.vectorstores.elasticsearch.ElasticsearchVectorStore";
173173

174+
// Milvus
175+
public static final String MILVUS_VECTOR_STORE =
176+
"org.apache.flink.agents.integrations.vectorstores.milvus.MilvusVectorStore";
177+
174178
// Python Wrapper
175179
public static final String PYTHON_WRAPPER_VECTOR_STORE =
176180
"org.apache.flink.agents.api.vectorstores.python.PythonVectorStore";

dist/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ under the License.
100100
<artifactId>flink-agents-integrations-vector-stores-elasticsearch</artifactId>
101101
<version>${project.version}</version>
102102
</dependency>
103+
<dependency>
104+
<groupId>org.apache.flink</groupId>
105+
<artifactId>flink-agents-integrations-vector-stores-milvus</artifactId>
106+
<version>${project.version}</version>
107+
</dependency>
103108
<dependency>
104109
<groupId>org.apache.flink</groupId>
105110
<artifactId>flink-agents-integrations-vector-stores-opensearch</artifactId>
@@ -156,4 +161,4 @@ under the License.
156161
</plugin>
157162
</plugins>
158163
</build>
159-
</project>
164+
</project>

docs/content/docs/development/vector_stores.md

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ In Flink Agents, vector stores are essential for:
4141

4242
### Concepts
4343
* **Document**: Document is the abstraction that represents a piece of text and associated metadata. A document may also carry a pre-computed `embedding` vector and a `score` populated by query results.
44+
* **Collection**: Collection is the abstraction that represents a set of documents. It corresponds to different concept for different vector store specification, like index in Elasticsearch/OpenSearch and collection in Chroma/Milvus.
4445
* **Filter DSL**: A unified, equality-only metadata filter dialect shared by `query`, `get`, and `delete`. The DSL covers only the subset every supported backend can honour (equality matching), so callers don't need to know each store's native operators. See the [Filter DSL](#filter-dsl) section below for details.
4546

4647
## How to use
@@ -172,7 +173,7 @@ For vector stores that implement `CollectionManageableVectorStore`, you can crea
172173
* `delete_collection` / `deleteCollection`: Delete a collection by name.
173174

174175
{{< hint info >}}
175-
Collection-level operations are only supported for vector stores that implement `CollectionManageableVectorStore`. Among the built-in providers, Chroma (Python), Elasticsearch (Java) and OpenSearch (Java) implement this interface.
176+
Collection-level operations are only supported for vector stores that implement `CollectionManageableVectorStore`. Among the built-in providers, Chroma (Python), Elasticsearch (Java), OpenSearch (Java), and Milvus (Java) implement this interface.
176177
{{< /hint >}}
177178

178179
{{< tabs "Collection level operations" >}}
@@ -642,9 +643,86 @@ public static ResourceDescriptor vectorStore() {
642643

643644
{{< /tabs >}}
644645

646+
### Milvus
647+
648+
[Milvus](https://milvus.io/) is an open-source vector database designed for high-dimensional vector search at scale.
649+
650+
{{< hint info >}}
651+
Milvus is currently supported in the Java API only. To use Milvus from Python agents, see [Using Cross-Language Providers](#using-cross-language-providers).
652+
{{< /hint >}}
653+
654+
#### Prerequisites
655+
656+
1. A Milvus server.
657+
658+
#### MilvusVectorStore Parameters
659+
660+
| Parameter | Type | Default | Description |
661+
|-----------------------------|------|--------------------------------------|-----------------------------------------------------------------------------|
662+
| `embedding_model` | str | Required | Reference to embedding model resource name |
663+
| `collection` | str | `"flink_agents_milvus_collection"` | Default target Milvus collection name |
664+
| `collection_name` | str | None | Alias for `collection` |
665+
| `index` | str | None | Alias for `collection`, mainly for cross-provider compatibility |
666+
| `id_field` | str | `"id"` | Name of the primary key field |
667+
| `content_field` | str | `"content"` | Name of the field storing document content |
668+
| `metadata_field` | str | `"metadata"` | Name of the JSON field storing document metadata |
669+
| `vector_field` | str | `"embedding"` | Name of the FloatVector field used for vector search |
670+
| `dims` | int | `768` | Vector dimensionality |
671+
| `id_max_length` | int | `65535` | Maximum length for the VarChar primary key field |
672+
| `content_max_length` | int | `65535` | Maximum length for the VarChar content field |
673+
| `metric_type` | str | `"COSINE"` | Milvus metric type used by vector search |
674+
| `index_type` | str | `"AUTOINDEX"` | Milvus vector index type |
675+
| `index_params` | map | `{}` | Extra vector index parameters passed to Milvus |
676+
| `metadata_index_keys` | list | `user_id`, `agent_id`, `run_id`, `actor_id`, `category` | Additional metadata JSON keys indexed with path indexes |
677+
| `metadata_index_cast_types` | map | Default keys use `"VARCHAR"` | Per-metadata-key JSON path index cast type overrides |
678+
| `num_shards` | int | `1` | Number of Milvus shards for newly created collections |
679+
| `consistency_level` | str | `"BOUNDED"` | Milvus consistency level for collection creation, query, and search |
680+
| `max_get_limit` | int | `10000` | Maximum number of documents returned by `get` when no limit is specified |
681+
| `load_timeout_ms` | long | `120000` | Timeout for loading collections |
682+
| `uri` | str | `"http://localhost:19530"` | Milvus endpoint |
683+
| `host` | str | `"localhost"` | Milvus host used when `uri` is not set |
684+
| `port` | int | `19530` | Milvus port used when `uri` is not set |
685+
| `db_name` | str | None | Milvus database name |
686+
| `token` | str | None | Token for Milvus authentication |
687+
| `username` | str | None | Username for basic authentication |
688+
| `password` | str | None | Password for basic authentication |
689+
| `enable_precheck` | bool | `false` | Whether to enable Milvus client precheck |
690+
691+
{{< hint info >}}
692+
When creating a collection, MilvusVectorStore creates a primary-key field, content field, JSON metadata field, vector field, vector index, and JSON metadata indexes. The default metadata JSON path indexes cover common filter keys such as `user_id`, `agent_id`, `run_id`, `actor_id`, and `category`; add `metadata_index_keys` for application-specific filter keys.
693+
694+
The default shard count is `1`. As a rough capacity-planning rule, use about one shard per 100 million vectors, and increase it for heavier write throughput.
695+
{{< /hint >}}
696+
697+
#### Usage Example
698+
699+
{{< tabs "Milvus Usage Example" >}}
700+
701+
{{< tab "Java" >}}
702+
703+
```java
704+
@VectorStore
705+
public static ResourceDescriptor vectorStore() {
706+
return ResourceDescriptor.Builder.newBuilder(ResourceName.VectorStore.MILVUS_VECTOR_STORE)
707+
.addInitialArgument("embedding_model", "embeddingModel")
708+
.addInitialArgument("uri", "http://localhost:19530")
709+
.addInitialArgument("collection", "my_documents")
710+
.addInitialArgument("dims", 1536)
711+
.addInitialArgument("metric_type", "COSINE")
712+
.addInitialArgument("index_type", "AUTOINDEX")
713+
// Optional metadata JSON path indexes
714+
// .addInitialArgument("metadata_index_keys", List.of("user_id", "agent_id", "run_id"))
715+
.build();
716+
}
717+
```
718+
719+
{{< /tab >}}
720+
721+
{{< /tabs >}}
722+
645723
## Using Cross-Language Providers
646724

647-
Flink Agents supports cross-language vector store integration, allowing you to use vector stores implemented in one language (Java or Python) from agents written in the other language. This is particularly useful when a vector store provider is only available in one language (e.g., Elasticsearch is currently Java-only, Chroma is currently Python-only).
725+
Flink Agents supports cross-language vector store integration, allowing you to use vector stores implemented in one language (Java or Python) from agents written in the other language. This is particularly useful when a vector store provider is only available in one language (e.g., Elasticsearch and Milvus are currently Java-only, Chroma is currently Python-only).
648726

649727
{{< hint warning >}}
650728
**Limitations:**
@@ -1101,4 +1179,4 @@ public class MyVectorStore extends BaseVectorStore
11011179

11021180
{{< /tab >}}
11031181

1104-
{{< /tabs >}}
1182+
{{< /tabs >}}

docs/content/docs/faq/faq.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ Flink Agents provides built-in integrations for many ecosystem providers. Some i
117117
|---|---|---|
118118
| [Chroma]({{< ref "docs/development/vector_stores#chroma" >}}) | ✅ | ❌ |
119119
| [Elasticsearch]({{< ref "docs/development/vector_stores#elasticsearch" >}}) | ❌ | ✅ |
120+
| [Milvus]({{< ref "docs/development/vector_stores#milvus" >}}) | ❌ | ✅ |
120121
121122
**MCP Server**
122123
@@ -131,4 +132,4 @@ Flink Agents provides built-in integrations for many ecosystem providers. Some i
131132
To avoid potential conflict with Flink cluster, the scope of the dependencies related to Flink and Flink Agents for agent job are provided. See [Maven Dependencies]({{< ref "docs/get-started/installation#maven-dependencies-for-java" >}}) for details.
132133
133134
To run the examples in IDE, users must enable the IDE feature: `add dependencies with provided scope to classpath`.
134-
* For **IDEA**, edit the **`Run/Debug Configuration`** and enable **`add dependencies with provided scope to classpath`**. See [Run/Debug Configuration](https://www.jetbrains.com/help/idea/run-debug-configuration-scala.html) for details.
135+
* For **IDEA**, edit the **`Run/Debug Configuration`** and enable **`add dependencies with provided scope to classpath`**. See [Run/Debug Configuration](https://www.jetbrains.com/help/idea/run-debug-configuration-scala.html) for details.

e2e-test/flink-agents-end-to-end-tests-resource-cross-language/src/test/java/org/apache/flink/agents/resource/test/VectorStoreCrossLanguageAgent.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
public class VectorStoreCrossLanguageAgent extends Agent {
6060
public static final String OLLAMA_MODEL = "nomic-embed-text";
6161
public static final String TEST_COLLECTION = "test_collection";
62+
private static final String VECTOR_STORE_BACKEND = "CHROMA";
6263

6364
@EmbeddingModelConnection
6465
public static ResourceDescriptor embeddingConnection() {
@@ -121,7 +122,8 @@ public static void inputEvent(Event event, RunnerContext ctx) throws Exception {
121122
TEST_COLLECTION,
122123
Map.of("metadata", Map.of("key1", "value1", "key2", "value2")));
123124

124-
System.out.println("[TEST] Vector store Collection Management PASSED");
125+
System.out.printf(
126+
"[TEST][%s] Vector store Collection Management PASSED%n", VECTOR_STORE_BACKEND);
125127

126128
vectorStore.deleteCollection(TEST_COLLECTION);
127129
Assertions.assertThrows(
@@ -168,7 +170,8 @@ public static void inputEvent(Event event, RunnerContext ctx) throws Exception {
168170
Assertions.assertEquals(
169171
Map.of("category", "database", "source", "test"), doc.getMetadata());
170172

171-
System.out.println("[TEST] Vector store Document Management PASSED");
173+
System.out.printf(
174+
"[TEST][%s] Vector store Document Management PASSED%n", VECTOR_STORE_BACKEND);
172175

173176
// Verify VectorStoreQuery.filters survives the Java->Python bridge.
174177
// ChromaDB applies the unified-DSL filter to its `where` clause, so the
@@ -191,7 +194,8 @@ public static void inputEvent(Event event, RunnerContext ctx) throws Exception {
191194
filteredDocs.get(0).getId(),
192195
"Filter {category=database} should match doc2");
193196

194-
System.out.println("[TEST] Vector store filter query PASSED");
197+
System.out.printf(
198+
"[TEST][%s] Vector store filter query PASSED%n", VECTOR_STORE_BACKEND);
195199

196200
ctx.getShortTermMemory().set("is_initialized", true);
197201
}
@@ -244,12 +248,16 @@ public static void contextRetrievalResponseEvent(Event event, RunnerContext ctx)
244248
first.getContent().substring(0, Math.min(50, first.getContent().length())));
245249

246250
ctx.sendEvent(new OutputEvent(result));
247-
System.out.printf("[TEST] Vector store retrieval PASSED, count=%d%n", documents.size());
251+
System.out.printf(
252+
"[TEST][%s] Vector store retrieval PASSED, count=%d%n",
253+
VECTOR_STORE_BACKEND, documents.size());
248254
} catch (Exception e) {
249255
result.put("test_status", "FAILED");
250256
result.put("error", e.getMessage());
251257
ctx.sendEvent(new OutputEvent(result));
252-
System.err.printf("[TEST] Vector store retrieval FAILED: %s%n", e.getMessage());
258+
System.err.printf(
259+
"[TEST][%s] Vector store retrieval FAILED: %s%n",
260+
VECTOR_STORE_BACKEND, e.getMessage());
253261
throw e;
254262
}
255263
}

integrations/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ under the License.
3333
<properties>
3434
<ollama4j.version>1.1.5</ollama4j.version>
3535
<elasticsearch.version>8.19.0</elasticsearch.version>
36+
<milvus.version>2.6.18</milvus.version>
3637
<openai.version>4.8.0</openai.version>
3738
<anthropic.version>2.11.1</anthropic.version>
3839
<aws.sdk.version>2.32.16</aws.sdk.version>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
Unless required by applicable law or agreed to in writing,
12+
software distributed under the License is distributed on an
13+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
KIND, either express or implied. See the License for the
15+
specific language governing permissions and limitations
16+
under the License.
17+
-->
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<parent>
24+
<groupId>org.apache.flink</groupId>
25+
<artifactId>flink-agents-integrations-vector-stores</artifactId>
26+
<version>0.3-SNAPSHOT</version>
27+
<relativePath>../pom.xml</relativePath>
28+
</parent>
29+
30+
<artifactId>flink-agents-integrations-vector-stores-milvus</artifactId>
31+
<name>Flink Agents : Integrations: Vector Stores: Milvus</name>
32+
<packaging>jar</packaging>
33+
34+
<dependencies>
35+
<dependency>
36+
<groupId>org.apache.flink</groupId>
37+
<artifactId>flink-agents-api</artifactId>
38+
<version>${project.version}</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>io.milvus</groupId>
42+
<artifactId>milvus-sdk-java</artifactId>
43+
<version>${milvus.version}</version>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.slf4j</groupId>
47+
<artifactId>slf4j-api</artifactId>
48+
<version>${slf4j.version}</version>
49+
</dependency>
50+
</dependencies>
51+
52+
</project>

0 commit comments

Comments
 (0)