主题
Milvus
Milvus 是一个开源向量数据库。LangChain4j 可将它用作 EmbeddingStore,以持久化嵌入并在其上运行相似度搜索。
两个 Milvus 模块
目前有 两个 Milvus 集成模块。它们相互独立,可以并列使用。
| 模块 | Milvus Java SDK | 能力 | 状态 |
|---|---|---|---|
langchain4j-milvus | v1(MilvusServiceClient) | 稠密向量搜索 | 遗留。基于已弃用的 v1 SDK。 |
langchain4j-milvus-v2 | v2(MilvusClientV2) | 稠密 + 稀疏 + 混合 搜索(含内置 BM25) | 当前。新项目推荐使用。 |
过渡性命名——这将在 LangChain4j 2.0 中变化
-v2 后缀指的是 Milvus SDK 的版本,而非本模块的版本。它是临时性的。
在 LangChain4j 2.0 中,遗留的 langchain4j-milvus 模块将被移除,而 langchain4j-milvus-v2 将被更名为 langchain4j-milvus(Maven artifact、...milvus.v2 包,以及 MilvusV2* 类名都会去掉 v2)。
如果你现在就采用 langchain4j-milvus-v2,请注意升级到 2.0 时需要更新你的 Maven 坐标、import 与类名。迁移指南将随 2.0 发布提供。
新项目应使用 langchain4j-milvus-v2。
langchain4j-milvus-v2(推荐)
基于当前的 Milvus Java SDK v2。支持稠密向量搜索、稀疏向量搜索,以及混合 (稠密 + 稀疏)搜索——包括 Milvus 内置的 BM25 全文稀疏向量。
Maven 依赖
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-milvus-v2</artifactId>
<version>1.22.0-beta32</version>
</dependency>1
2
3
4
5
2
3
4
5
API
MilvusV2EmbeddingStore
基本用法——稠密向量搜索
这是标准的 EmbeddingStore 用法。搜索模式默认为 VECTOR(仅稠密)。
java
MilvusV2EmbeddingStore store = MilvusV2EmbeddingStore.builder()
.uri("http://localhost:19530") // or .host("localhost").port(19530)
.collectionName("my_collection")
.dimension(384) // required when a new collection is created
.build();
store.add(embedding, textSegment);
EmbeddingSearchResult<TextSegment> result = store.search(
EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(5)
.build());1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
混合搜索(稠密 + 稀疏)
混合搜索将稠密向量搜索与稀疏向量搜索结合,并用一个重排序器合并结果(默认为倒数排名融合,RRF)。用 searchMode(HYBRID) 启用它。
产生稀疏向量有两种方式,通过 sparseMode 选择:
BM25(默认) —— Milvus 从你的文本自动计算稀疏向量。你提供文本。CUSTOM—— 你自行提供稀疏向量(例如来自 BGE-M3 模型)。
方式 A——内置 BM25(文本 → 稀疏,由 Milvus 计算)
java
MilvusV2EmbeddingStore store = MilvusV2EmbeddingStore.builder()
.uri("http://localhost:19530")
.collectionName("bm25_collection")
.dimension(384)
.searchMode(MilvusV2EmbeddingStore.SearchMode.HYBRID)
.sparseMode(MilvusV2EmbeddingStore.MilvusSparseMode.BM25) // default
.build();
// Insert: only dense embeddings are needed; Milvus builds the BM25 sparse index from the text.
store.addAll(ids, denseEmbeddings, textSegments);
// Search: provide the dense query embedding and the query text (used for BM25).
MilvusV2EmbeddingSearchRequest request = MilvusV2EmbeddingSearchRequest.milvusBuilder()
.queryEmbedding(queryDenseEmbedding)
.query("full-text keywords here")
.maxResults(10)
.build();
EmbeddingSearchResult<TextSegment> result = store.search(request);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
方式 B——自定义稀疏向量(例如 BGE-M3)
java
MilvusV2EmbeddingStore store = MilvusV2EmbeddingStore.builder()
.uri("http://localhost:19530")
.collectionName("hybrid_collection")
.dimension(384)
.searchMode(MilvusV2EmbeddingStore.SearchMode.HYBRID)
.sparseMode(MilvusV2EmbeddingStore.MilvusSparseMode.CUSTOM) // you provide sparse vectors
.build();
// Insert both dense and sparse embeddings.
List<SparseEmbedding> sparseEmbeddings = List.of(
new SparseEmbedding(new long[]{1L, 42L, 300L}, new float[]{0.8f, 0.5f, 0.3f}),
new SparseEmbedding(new long[]{7L, 99L}, new float[]{0.6f, 0.4f}));
store.addAllHybrid(ids, denseEmbeddings, sparseEmbeddings, textSegments);
// Search with a dense query embedding and a sparse query embedding.
MilvusV2EmbeddingSearchRequest request = MilvusV2EmbeddingSearchRequest.milvusBuilder()
.queryEmbedding(queryDenseEmbedding)
.sparseEmbedding(querySparseEmbedding)
.maxResults(10)
.build();
EmbeddingSearchResult<TextSegment> result = store.search(request);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
NOTE
搜索模式是集合 schema 的一个属性,在存储(及集合)创建时设定一次。HYBRID 集合同时具有稠密与稀疏向量字段;VECTOR 集合只有稠密字段。二者不可互换——切换模式需要新建集合。
连接到 Zilliz Cloud
java
MilvusV2EmbeddingStore store = MilvusV2EmbeddingStore.builder()
.uri("https://xxx.api.gcp-us-west1.zillizcloud.com")
.token("your-api-key")
.collectionName("my_collection")
.dimension(384)
.build();1
2
3
4
5
6
2
3
4
5
6
你也可以通过 .milvusClient(client) 传入你自己的 MilvusClientV2 实例。
兼容性
- 推荐 Milvus Server 2.5.x 或更新版本(BM25 全文搜索需要 2.5+;混合搜索需要 2.4+)。
- Java 17+
langchain4j-milvus(遗留)
基于 Milvus Java SDK v1。仅支持稠密向量搜索。它将在 LangChain4j 2.0 中被移除 (见上文说明);新项目应优先选择 langchain4j-milvus-v2。
Maven 依赖
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-milvus</artifactId>
<version>1.22.0-beta32</version>
</dependency>1
2
3
4
5
2
3
4
5
API
MilvusEmbeddingStore
创建
创建 MilvusEmbeddingStore 有两种方式:
- 让存储内部根据主机、端口与认证信息创建一个
MilvusServiceClient:
java
MilvusEmbeddingStore store = MilvusEmbeddingStore.builder()
.host("localhost") // Host for Milvus instance
.port(19530) // Port for Milvus instance
.collectionName("example_collection") // Name of the collection
.dimension(128) // Dimension of vectors
.indexType(IndexType.FLAT) // Index type
.metricType(MetricType.COSINE) // Metric type
.username("username") // Username for Milvus
.password("password") // Password for Milvus
.consistencyLevel(ConsistencyLevelEnum.EVENTUALLY) // Consistency level
.autoFlushOnInsert(true) // Auto flush after insert
.idFieldName("id") // ID field name
.textFieldName("text") // Text field name
.metadataFieldName("metadata") // Metadata field name
.vectorFieldName("vector") // Vector field name
.build();1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 传入一个已有的
MilvusServiceClient:
java
// Set up a custom MilvusServiceClient
MilvusServiceClient customMilvusClient = new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost("localhost")
.withPort(19530)
.build()
);
// Use the custom client in the builder
MilvusEmbeddingStore store = MilvusEmbeddingStore.builder()
.milvusClient(customMilvusClient) // Use an existing Milvus client
.collectionName("example_collection") // Name of the collection
.dimension(128) // Dimension of vectors
.indexType(IndexType.FLAT) // Index type
.metricType(MetricType.COSINE) // Metric type
.consistencyLevel(ConsistencyLevelEnum.EVENTUALLY) // Consistency level
.autoFlushOnInsert(true) // Auto flush after insert
.idFieldName("id") // ID field name
.textFieldName("text") // Text field name
.metadataFieldName("metadata") // Metadata field name
.vectorFieldName("vector") // Vector field name
.build();1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22