Elasticsearch

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

本节将指导你配置 Elasticsearch VectorStore 以存储文档向量并执行相似性搜索。

Elasticsearch 是基于 Apache Lucene 库的开源搜索与分析引擎。

先决条件

要运行一个 Elasticsearch 实例。可选方案包括:

自动配置

Spring AI 自动配置及 Starter 模块的 Artifact 名称已发生重大变更。更多信息请参阅 升级说明

Spring AI 为 Elasticsearch 向量存储提供 Spring Boot 自动配置。启用该功能需在项目的 Maven pom.xml 或 Gradle build.gradle 构建文件中添加以下依赖:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-elasticsearch</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-vector-store-elasticsearch'
}

Spring Boot 3.3.0 之前版本需显式添加 elasticsearch-java 依赖(版本需 > 8.13.3),否则旧版本会与查询操作不兼容:

  • Maven

  • Gradle

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.13.3</version>
</dependency>
dependencies {
    implementation 'co.elastic.clients:elasticsearch-java:8.13.3'
}
请参考 “依赖管理” 部分将 Spring AI BOM 添加至构建文件。
请参考 “Artifact 仓库” 部分将 Maven Central 和/或 Snapshot 仓库添加至构建文件。

向量存储实现可自动初始化必要表结构,但需通过在对应构造函数中指定 initializeSchema 布尔参数,或在 application.properties 文件中设置 …​initialize-schema=true 显式启用。也可选择手动初始化,通过 Elasticsearch 客户端创建索引(适用于需要高级映射或额外配置的场景)。

此为重大变更!在早期 Spring AI 版本中,表结构初始化默认为自动执行。

请查阅向量存储的 配置参数列表 以了解默认值及配置选项。这些属性也可通过配置 ElasticsearchVectorStoreOptions Bean 设置。

此外,需配置 EmbeddingModel Bean。详细信息请参阅 EmbeddingModel 部分。

现在你可以在应用中自动注入 ElasticsearchVectorStore 作为向量存储使用。

@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")));

// Add the documents to Elasticsearch
vectorStore.add(documents);

// Retrieve documents similar to a query
List<Document> results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());

配置属性

连接 Elasticsearch 并使用 ElasticsearchVectorStore 需提供实例访问配置。简易配置可通过 Spring Boot 的 application.yml 文件实现:

spring:
  elasticsearch:
    uris: <elasticsearch instance URIs>
    username: <elasticsearch username>
    password: <elasticsearch password>
  ai:
    vectorstore:
      elasticsearch:
        initialize-schema: true
        index-name: custom-index
        dimensions: 1536
        similarity: cosine

spring.elasticsearch.* 开头的 Spring Boot 属性用于配置 Elasticsearch 客户端:

属性 说明 默认值

spring.elasticsearch.connection-timeout

与 Elasticsearch 通信的连接超时设置。

1s

spring.elasticsearch.password

用于通过 Elasticsearch 验证的密码。

-

spring.elasticsearch.username

用于通过 Elasticsearch 验证的用户名。

-

spring.elasticsearch.uris

用逗号分隔的要使用的 Elasticsearch 实例列表。

localhost:9200

spring.elasticsearch.path-prefix

添加到发送到 Elasticsearch 的每个请求的路径中的前缀。

-

spring.elasticsearch.restclient.sniffer.delay-after-failure

故障后调度嗅探操作的延迟时间。

1m

spring.elasticsearch.restclient.sniffer.interval

连续两次普通嗅探执行之间的间隔。

5m

spring.elasticsearch.restclient.ssl.bundle

SSL bundle name.

-

spring.elasticsearch.socket-keep-alive

是否在客户端与 Elasticsearch 之间启用 socket 保持活动状态。

false

spring.elasticsearch.socket-timeout

与 Elasticsearch 通信时使用的 socket 超时时间。

30s

spring.ai.vectorstore.elasticsearch.* 开头的属性用于配置 ElasticsearchVectorStore

属性 说明 默认值

spring.ai.vectorstore.elasticsearch.initialize-schema

是否初始化所需的 Schema

false

spring.ai.vectorstore.elasticsearch.index-name

用于存储向量的索引名称

spring-ai-document-index

spring.ai.vectorstore.elasticsearch.dimensions

向量中的维度数量

1536

spring.ai.vectorstore.elasticsearch.similarity

要使用的相似性函数

cosine

以下相似性函数可用:

  • cosine - 默认选项,适用于大多数使用场景。用于衡量向量之间的余弦相似性。

  • l2_norm - 向量之间的欧几里得距离。值越小表示相似性越高。

  • dot_product - 适用于已归一化的向量(例如 OpenAI 嵌入),具有最佳性能。

更多详细信息,请参阅 Elasticsearch 文档 中关于密集向量的部分。

元数据过滤

你同样可以将通用的、可移植的 元数据过滤器 与 Elasticsearch 一起使用。

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

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 以编程方式实现:

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());
这些(可移植的)过滤器表达式会自动转换为专有的 Elasticsearch 查询字符串查询

例如,这个可移植的过滤器表达式:

author in ['john', 'jill'] && 'article_type' == 'blog'

转换为 Elasticsearch 专有的过滤器格式

(metadata.author:john OR jill) AND metadata.article_type:blog

手动配置

除了使用 Spring Boot 的自动配置外,你也可以手动配置 Elasticsearch 向量存储。为此,你需要将 spring-ai-elasticsearch-store 添加到你的项目中:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-elasticsearch-store</artifactId>
</dependency>

或者添加到你的 Gradle build.gradle 构建文件中:

dependencies {
    implementation 'org.springframework.ai:spring-ai-elasticsearch-store'
}

创建一个 Elasticsearch RestClient Bean。有关自定义 RestClient 配置的更详细信息,请参阅 Elasticsearch 文档

@Bean
public RestClient restClient() {
    return RestClient.builder(new HttpHost("<host>", 9200, "http"))
        .setDefaultHeaders(new Header[]{
            new BasicHeader("Authorization", "Basic <encoded username and password>")
        })
        .build();
}

然后使用 Builder 模式创建 ElasticsearchVectorStore Bean:

@Bean
public VectorStore vectorStore(RestClient restClient, EmbeddingModel embeddingModel) {
    ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions();
    options.setIndexName("custom-index");    // Optional: defaults to "spring-ai-document-index"
    options.setSimilarity(COSINE);           // Optional: defaults to COSINE
    options.setDimensions(1536);             // Optional: defaults to model dimensions or 1536

    return ElasticsearchVectorStore.builder(restClient, embeddingModel)
        .options(options)                     // Optional: use custom options
        .initializeSchema(true)               // Optional: defaults to false
        .batchingStrategy(new TokenCountBatchingStrategy()) // Optional: defaults to TokenCountBatchingStrategy
        .build();
}

// This can be any EmbeddingModel implementation
@Bean
public EmbeddingModel embeddingModel() {
    return new OpenAiEmbeddingModel(new OpenAiApi(System.getenv("OPENAI_API_KEY")));
}

访问原生客户端

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

ElasticsearchVectorStore vectorStore = context.getBean(ElasticsearchVectorStore.class);
Optional<ElasticsearchClient> nativeClient = vectorStore.getNativeClient();

if (nativeClient.isPresent()) {
    ElasticsearchClient client = nativeClient.get();
    // Use the native client for Elasticsearch-specific operations
}

原生客户端使你可以访问 VectorStore 接口可能未暴露的、Elasticsearch 特有的功能和操作。