Spring AI Vector Databases Milvus

Milvus

Milvus是一个开源的向量数据库,在数据科学和机器学习领域受到了广泛关注。其突出特性之一在于对向量索引和查询的强大支持。Milvus采用最前沿的先进算法来加速搜索过程,使其在检索相似向量时效率极高,即使处理大规模数据集也是如此。

先决条件

一个正在运行的Milvus实例。以下选项可用:

  • Milvus Standalone:Docker、Operator、Helm、DEB/RPM、Docker Compose。
  • Milvus Cluster:Operator、Helm。

如果需要,为EmbeddingModel准备一个API密钥,用于生成MilvusVectorStore存储的嵌入向量。

依赖

Spring AI自动配置和启动模块的工件名称发生了重大变化。请参阅升级说明以获取更多信息。

然后将Milvus VectorStore启动器依赖项添加到您的项目中:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-milvus</artifactId>
</dependency>

或者添加到您的Gradle build.gradle 构建文件中。

gradle 复制代码
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-vector-store-milvus'
}

请参阅依赖管理部分将Spring AI BOM添加到您的构建文件中。请参阅工件仓库部分将Maven中央仓库和/或快照仓库添加到您的构建文件中。

向量存储实现可以为您初始化所需的模式,但您必须通过在适当的构造函数中指定 initializeSchema 布尔值,或在 application.properties 文件中设置 ...​initialize-schema=true 来选择启用。

这是一个重大变更! 在早期版本的Spring AI中,此模式初始化是默认发生的。

向量存储还需要一个 EmbeddingModel 实例来计算文档的嵌入向量。您可以选择一个可用的 EmbeddingModel 实现。

要连接和配置 MilvusVectorStore,您需要提供Milvus实例的访问详细信息。一个简单的配置可以通过Spring Boot的 application.yml 提供:

yaml 复制代码
spring:
    ai:
        vectorstore:
            milvus:
                client:
                    host: "localhost"
                    port: 19530
                    username: "root"
                    password: "milvus"
                databaseName: "default"
                collectionName: "vector_store"
                embeddingDimension: 1536
                indexType: IVF_FLAT
                metricType: COSINE

请查看配置参数列表以了解默认值和配置选项。

现在您可以在应用程序中自动装配Milvus向量存储并使用它:

java 复制代码
@Autowired VectorStore vectorStore;

// ...

List <Document> documents = List.of(
    new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")),
    new Document("The World is Big and Salvation Lurks Around the Corner"),
    new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2")));

// 将文档添加到 Milvus 向量存储
vectorStore.add(documents);

// 检索与查询相似的文档
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());

手动配置

您可以不使用Spring Boot自动配置,而是手动配置 MilvusVectorStore。将以下依赖项添加到您的项目中:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-milvus-store</artifactId>
</dependency>

请参阅依赖管理部分将Spring AI BOM添加到您的构建文件中。

要在您的应用程序中配置 MilvusVectorStore,您可以使用以下设置:

java 复制代码
    @Bean
    public VectorStore vectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) {
        return MilvusVectorStore.builder(milvusClient, embeddingModel)
                .collectionName("test_vector_store")
                .databaseName("default")
                .indexType(IndexType.IVF_FLAT)
                .metricType(MetricType.COSINE)
                .batchingStrategy(new TokenCountBatchingStrategy())
                .initializeSchema(true)
                .build();
    }

    @Bean
    public MilvusServiceClient milvusClient() {
        return new MilvusServiceClient(ConnectParam.newBuilder()
            .withAuthorization("minioadmin", "minioadmin")
            .withUri(milvusContainer.getEndpoint())
            .build());
    }

元数据过滤

您可以将通用的、可移植的元数据过滤器与Milvus存储一起使用。

例如,您可以使用文本表达式语言:

java 复制代码
vectorStore.similaritySearch(
    SearchRequest.builder()
    .query("The World")
    .topK(TOP_K)
    .similarityThreshold(SIMILARITY_THRESHOLD)
    .filterExpression("author in ['john', 'jill'] && article_type == 'blog'").build());

或者使用 Filter.Expression DSL 以编程方式构建:

java 复制代码
FilterExpressionBuilder b = new FilterExpressionBuilder();

vectorStore.similaritySearch(SearchRequest.builder()
    .query("The World")
    .topK(TOP_K)
    .similarityThreshold(SIMILARITY_THRESHOLD)
    .filterExpression(b.and(
        b.in("author","john", "jill"),
        b.eq("article_type", "blog")).build()).build());

这些过滤表达式会被转换为等效的Milvus过滤器。

使用 MilvusSearchRequest

MilvusSearchRequest 扩展了 SearchRequest,允许您使用Milvus特有的搜索参数,如原生表达式(native expressions)和搜索参数JSON(search parameter JSON)。

java 复制代码
MilvusSearchRequest request = MilvusSearchRequest.milvusBuilder()
    .query("sample query")
    .topK(5)
    .similarityThreshold(0.7)
    .nativeExpression("metadata[\"age\"] > 30") // 如果同时设置了 nativeExpression,则会覆盖 filterExpression
    .filterExpression("age <= 30") // 如果设置了 nativeExpression,此设置将被忽略
    .searchParamsJson("{\"nprobe\":128}")
    .build();
List results = vectorStore.similaritySearch(request);

这在使用Milvus特有的搜索功能时提供了更大的灵活性。

nativeExpression 和 searchParamsJson 在 MilvusSearchRequest 中的重要性

这两个参数增强了Milvus搜索的精度并确保了最佳的查询性能:

  • nativeExpression:允许使用Milvus的原生过滤表达式进行额外的过滤。Milvus 过滤

    示例:

    java 复制代码
    MilvusSearchRequest request = MilvusSearchRequest.milvusBuilder()
        .query("sample query")
        .topK(5)
        .nativeExpression("metadata['category'] == 'science'")
        .build();
  • searchParamsJson:在使用Milvus的默认索引 IVF_FLAT 时,对于调整搜索行为至关重要。Milvus 向量索引

    默认情况下,IVF_FLAT 需要设置 nprobe 才能获得准确结果。如果未指定,nprobe 默认为1,这可能导致较低的召回率甚至零搜索结果。

    示例:

    java 复制代码
    MilvusSearchRequest request = MilvusSearchRequest.milvusBuilder()
        .query("sample query")
        .topK(5)
        .searchParamsJson("{\"nprobe\":128}")
        .build();

使用 nativeExpression 确保了高级过滤,而 searchParamsJson 则防止了因低默认 nprobe 值导致的无效搜索。

Milvus VectorStore 属性

您可以在Spring Boot配置中使用以下属性来定制Milvus向量存储。

属性 描述 默认值
spring.ai.vectorstore.milvus.database-name 要使用的Milvus数据库名称。 default
spring.ai.vectorstore.milvus.collection-name 用于存储向量的Milvus集合名称。 vector_store
spring.ai.vectorstore.milvus.initialize-schema 是否初始化Milvus后端模式。 false
spring.ai.vectorstore.milvus.embedding-dimension 存储在Milvus集合中的向量的维度。 1536
spring.ai.vectorstore.milvus.index-type 为Milvus集合创建的索引类型。 IVF_FLAT
spring.ai.vectorstore.milvus.metric-type 用于Milvus集合的度量类型。 COSINE
spring.ai.vectorstore.milvus.index-parameters 用于Milvus集合的索引参数。 {"nlist":1024}
spring.ai.vectorstore.milvus.id-field-name 集合的ID字段名称。 doc_id
spring.ai.vectorstore.milvus.auto-id 布尔标志,指示ID字段是否使用自动ID。 false
spring.ai.vectorstore.milvus.content-field-name 集合的内容字段名称。 content
spring.ai.vectorstore.milvus.metadata-field-name 集合的元数据字段名称。 metadata
spring.ai.vectorstore.milvus.embedding-field-name 集合的嵌入向量字段名称。 embedding
spring.ai.vectorstore.milvus.client.host 主机名或地址。 localhost
spring.ai.vectorstore.milvus.client.port 连接端口。 19530
spring.ai.vectorstore.milvus.client.uri Milvus实例的URI。 -
spring.ai.vectorstore.milvus.client.token 用作标识和身份验证密钥的令牌。 -
spring.ai.vectorstore.milvus.client.connect-timeout-ms 客户端通道的连接超时值。该值必须大于零。 10000
spring.ai.vectorstore.milvus.client.keep-alive-time-ms 客户端通道的保持活动时间值。该值必须大于零。 55000
spring.ai.vectorstore.milvus.client.keep-alive-timeout-ms 客户端通道的保持活动超时值。该值必须大于零。 20000
spring.ai.vectorstore.milvus.client.rpc-deadline-ms 等待服务器回复的截止时间。设置截止时间后,当遇到网络波动导致的快速RPC失败时,客户端将等待。该值必须大于或等于零。 0
spring.ai.vectorstore.milvus.client.client-key-path 用于TLS双向认证的 client.key 路径,仅在 securetrue 时生效。 -
spring.ai.vectorstore.milvus.client.client-pem-path 用于TLS双向认证的 client.pem 路径,仅在 securetrue 时生效。 -
spring.ai.vectorstore.milvus.client.ca-pem-path 用于TLS双向认证的 ca.pem 路径,仅在 securetrue 时生效。 -
spring.ai.vectorstore.milvus.client.server-pem-path 用于TLS单向认证的 server.pem 路径,仅在 securetrue 时生效。 -
spring.ai.vectorstore.milvus.client.server-name 设置用于SSL主机名检查的目标名称覆盖,仅在 secureTrue 时生效。注意:此值传递给 grpc.ssl_target_name_override -
spring.ai.vectorstore.milvus.client.secure 为此连接启用安全授权,设置为 true 以启用TLS。 false
spring.ai.vectorstore.milvus.client.idle-timeout-ms 客户端通道的空闲超时值。该值必须大于零。 24h
spring.ai.vectorstore.milvus.client.username 此连接的用户名。 root
spring.ai.vectorstore.milvus.client.password 此连接的密码。 milvus

启动 Milvus Store

src/test/resources/ 文件夹内运行:

bash 复制代码
docker-compose up

清理环境:

bash 复制代码
docker-compose down; rm -Rf ./volumes

然后通过 http://localhost:19530 连接到向量存储,或通过 http://localhost:9001(用户:minioadmin,密码:minioadmin)进行管理。

故障排除

如果Docker报告资源不足,请执行:

bash 复制代码
docker system prune --all --force --volumes

访问原生客户端

Milvus向量存储实现通过 getNativeClient() 方法提供对底层原生Milvus客户端(MilvusServiceClient)的访问:

java 复制代码
MilvusVectorStore vectorStore = context.getBean(MilvusVectorStore.class);
Optional<MilvusServiceClient> nativeClient = vectorStore.getNativeClient();

if (nativeClient.isPresent()) {
    MilvusServiceClient client = nativeClient.get();
    // 使用原生客户端执行Milvus特有的操作
}

原生客户端让您可以访问可能未通过 VectorStore 接口公开的Milvus特有功能和操作。