Elasticsearch

本節將引導您設定 Elasticsearch VectorStore 以儲存文件嵌入並執行相似度搜索。

Elasticsearch 是一個基於 Apache Lucene 庫的開源搜尋和分析引擎。

先決條件

一個正在執行的 Elasticsearch 例項。以下選項可用

自動配置

Spring AI 自動配置、starter 模組的 artifact 名稱發生了重大變化。請參閱升級說明獲取更多資訊。

Spring AI 為 Elasticsearch Vector Store 提供了 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'
}

對於早於 3.3.0 的 spring-boot 版本,需要明確新增版本 > 8.13.3 的 elasticsearch-java 依賴項,否則使用的舊版本將與執行的查詢不相容

  • 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 新增到您的構建檔案中。
請參閱倉庫部分,將 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 名稱。

-

spring.elasticsearch.socket-keep-alive

是否在客戶端和 Elasticsearch 之間啟用 socket keep alive。

false

spring.elasticsearch.socket-timeout

與 Elasticsearch 通訊時使用的 socket 超時。

30s

spring.ai.vectorstore.elasticsearch.* 開頭的屬性用於配置 ElasticsearchVectorStore

屬性 描述 預設值

spring.ai.vectorstore.elasticsearch.initialize-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。閱讀 Elasticsearch 文件,瞭解有關配置自定義 RestClient 的更多深入資訊。

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

然後使用構建器模式建立 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 的功能和操作。