diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfiguration.java index 47628a30ceb..28a4e4529ad 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfiguration.java @@ -40,7 +40,7 @@ import org.springframework.ai.embedding.BatchingStrategy; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.embedding.TokenCountBatchingStrategy; -import org.springframework.ai.vectorstore.OpenSearchVectorStore; +import org.springframework.ai.vectorstore.opensearch.OpenSearchVectorStore; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -78,9 +78,17 @@ OpenSearchVectorStore vectorStore(OpenSearchVectorStoreProperties properties, Op var indexName = Optional.ofNullable(properties.getIndexName()).orElse(OpenSearchVectorStore.DEFAULT_INDEX_NAME); var mappingJson = Optional.ofNullable(properties.getMappingJson()) .orElse(OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION); - return new OpenSearchVectorStore(indexName, openSearchClient, embeddingModel, mappingJson, - properties.isInitializeSchema(), observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP), - customObservationConvention.getIfAvailable(() -> null), batchingStrategy); + + return OpenSearchVectorStore.builder() + .index(indexName) + .openSearchClient(openSearchClient) + .embeddingModel(embeddingModel) + .mappingJson(mappingJson) + .initializeSchema(properties.isInitializeSchema()) + .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) + .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) + .batchingStrategy(batchingStrategy) + .build(); } @Configuration(proxyBeanMethods = false) diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/AwsOpenSearchVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/AwsOpenSearchVectorStoreAutoConfigurationIT.java index d3449dc9f50..0810c6cab7c 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/AwsOpenSearchVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/AwsOpenSearchVectorStoreAutoConfigurationIT.java @@ -36,7 +36,7 @@ import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.transformers.TransformersEmbeddingModel; -import org.springframework.ai.vectorstore.OpenSearchVectorStore; +import org.springframework.ai.vectorstore.opensearch.OpenSearchVectorStore; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfigurationIT.java index 55022d938b4..87c774ced92 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/opensearch/OpenSearchVectorStoreAutoConfigurationIT.java @@ -36,7 +36,7 @@ import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.observation.conventions.VectorStoreProvider; import org.springframework.ai.transformers.TransformersEmbeddingModel; -import org.springframework.ai.vectorstore.OpenSearchVectorStore; +import org.springframework.ai.vectorstore.opensearch.OpenSearchVectorStore; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext; import org.springframework.boot.autoconfigure.AutoConfigurations; diff --git a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverter.java b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverter.java similarity index 98% rename from vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverter.java rename to vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverter.java index 71022a98616..9b5be81e759 100644 --- a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverter.java +++ b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.text.ParseException; import java.text.SimpleDateFormat; diff --git a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchVectorStore.java b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java similarity index 59% rename from vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchVectorStore.java rename to vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java index 0492ec80f1d..ec91f7ba2c1 100644 --- a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/OpenSearchVectorStore.java +++ b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.io.IOException; import java.io.StringReader; @@ -48,6 +48,8 @@ import org.springframework.ai.embedding.TokenCountBatchingStrategy; import org.springframework.ai.observation.conventions.VectorStoreProvider; import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric; +import org.springframework.ai.vectorstore.AbstractVectorStoreBuilder; +import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.filter.Filter; import org.springframework.ai.vectorstore.filter.FilterExpressionConverter; import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore; @@ -83,10 +85,6 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem } """; - private static final Logger logger = LoggerFactory.getLogger(OpenSearchVectorStore.class); - - private final EmbeddingModel embeddingModel; - private final OpenSearchClient openSearchClient; private final String index; @@ -101,40 +99,106 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem private String similarityFunction; + /** + * Creates a new OpenSearchVectorStore with default mapping and collection name. + * @deprecated Use {@link #builder()} instead + * @param openSearchClient The OpenSearch client + * @param embeddingModel The embedding model to use + * @param initializeSchema Whether to initialize the schema + * @since 1.0.0 + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public OpenSearchVectorStore(OpenSearchClient openSearchClient, EmbeddingModel embeddingModel, boolean initializeSchema) { this(openSearchClient, embeddingModel, DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION, initializeSchema); } + /** + * Creates a new OpenSearchVectorStore with custom mapping. + * @deprecated Use {@link #builder()} instead + * @param openSearchClient The OpenSearch client + * @param embeddingModel The embedding model to use + * @param mappingJson The JSON mapping for the index + * @param initializeSchema Whether to initialize the schema + * @since 1.0.0 + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public OpenSearchVectorStore(OpenSearchClient openSearchClient, EmbeddingModel embeddingModel, String mappingJson, boolean initializeSchema) { this(DEFAULT_INDEX_NAME, openSearchClient, embeddingModel, mappingJson, initializeSchema); } + /** + * Creates a new OpenSearchVectorStore with custom index name and mapping. + * @deprecated Use {@link #builder()} instead + * @param index The name of the index + * @param openSearchClient The OpenSearch client + * @param embeddingModel The embedding model to use + * @param mappingJson The JSON mapping for the index + * @param initializeSchema Whether to initialize the schema + * @since 1.0.0 + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public OpenSearchVectorStore(String index, OpenSearchClient openSearchClient, EmbeddingModel embeddingModel, String mappingJson, boolean initializeSchema) { this(index, openSearchClient, embeddingModel, mappingJson, initializeSchema, ObservationRegistry.NOOP, null, new TokenCountBatchingStrategy()); } + /** + * Creates a new OpenSearchVectorStore with all configuration options. + * @deprecated Use {@link #builder()} instead + * @param index The name of the index + * @param openSearchClient The OpenSearch client + * @param embeddingModel The embedding model to use + * @param mappingJson The JSON mapping for the index + * @param initializeSchema Whether to initialize the schema + * @param observationRegistry The observation registry for metrics + * @param customObservationConvention Custom observation convention + * @param batchingStrategy The strategy for batching operations + * @since 1.0.0 + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public OpenSearchVectorStore(String index, OpenSearchClient openSearchClient, EmbeddingModel embeddingModel, String mappingJson, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - super(observationRegistry, customObservationConvention); + this(builder().openSearchClient(openSearchClient) + .embeddingModel(embeddingModel) + .index(index) + .mappingJson(mappingJson) + .initializeSchema(initializeSchema) + .observationRegistry(observationRegistry) + .customObservationConvention(customObservationConvention) + .batchingStrategy(batchingStrategy)); + } - Objects.requireNonNull(embeddingModel, "RestClient must not be null"); - Objects.requireNonNull(embeddingModel, "EmbeddingModel must not be null"); - this.openSearchClient = openSearchClient; - this.embeddingModel = embeddingModel; - this.index = index; - this.mappingJson = mappingJson; - this.filterExpressionConverter = new OpenSearchAiSearchFilterExpressionConverter(); + /** + * Creates a new OpenSearchVectorStore using the builder pattern. + * @param builder The configured builder instance + */ + protected OpenSearchVectorStore(OpenSearchBuilder builder) { + super(builder); + + Assert.notNull(builder.openSearchClient, "OpenSearchClient must not be null"); + + this.openSearchClient = builder.openSearchClient; + this.index = builder.index; + this.mappingJson = builder.mappingJson; + this.filterExpressionConverter = builder.filterExpressionConverter; // the potential functions for vector fields at // https://opensearch.org/docs/latest/search-plugins/knn/approximate-knn/#spaces - this.similarityFunction = COSINE_SIMILARITY_FUNCTION; - this.initializeSchema = initializeSchema; - this.batchingStrategy = batchingStrategy; + this.similarityFunction = builder.similarityFunction; + this.initializeSchema = builder.initializeSchema; + this.batchingStrategy = builder.batchingStrategy; + } + + /** + * Creates a new builder instance for configuring an OpenSearchVectorStore. + * @return A new OpenSearchBuilder instance + */ + public static OpenSearchBuilder builder() { + return new OpenSearchBuilder(); } public OpenSearchVectorStore withSimilarityFunction(String similarityFunction) { @@ -306,4 +370,132 @@ else if ("l2".equalsIgnoreCase(this.similarityFunction)) { public record OpenSearchDocument(String id, String content, Map metadata, float[] embedding) { } + /** + * Builder class for creating OpenSearchVectorStore instances. + */ + public static class OpenSearchBuilder extends AbstractVectorStoreBuilder { + + private OpenSearchClient openSearchClient; + + private String index = DEFAULT_INDEX_NAME; + + private String mappingJson = DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION; + + private boolean initializeSchema = false; + + private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); + + private FilterExpressionConverter filterExpressionConverter = new OpenSearchAiSearchFilterExpressionConverter(); + + private String similarityFunction = COSINE_SIMILARITY_FUNCTION; + + /** + * Sets the OpenSearch client. + * @param openSearchClient The OpenSearch client to use + * @return The builder instance + * @throws IllegalArgumentException if openSearchClient is null + */ + public OpenSearchBuilder openSearchClient(OpenSearchClient openSearchClient) { + Assert.notNull(openSearchClient, "OpenSearchClient must not be null"); + this.openSearchClient = openSearchClient; + return this; + } + + /** + * Sets the embedding model. + * @param embeddingModel The embedding model to use + * @return The builder instance + * @throws IllegalArgumentException if embeddingModel is null + */ + public OpenSearchBuilder embeddingModel(EmbeddingModel embeddingModel) { + Assert.notNull(embeddingModel, "EmbeddingModel must not be null"); + this.embeddingModel = embeddingModel; + return this; + } + + /** + * Sets the index name. + * @param index The name of the index to use + * @return The builder instance + * @throws IllegalArgumentException if index is null or empty + */ + public OpenSearchBuilder index(String index) { + Assert.hasText(index, "index must not be null or empty"); + this.index = index; + return this; + } + + /** + * Sets the JSON mapping for the index. + * @param mappingJson The JSON mapping to use + * @return The builder instance + * @throws IllegalArgumentException if mappingJson is null or empty + */ + public OpenSearchBuilder mappingJson(String mappingJson) { + Assert.hasText(mappingJson, "mappingJson must not be null or empty"); + this.mappingJson = mappingJson; + return this; + } + + /** + * Sets whether to initialize the schema. + * @param initializeSchema true to initialize schema, false otherwise + * @return The builder instance + */ + public OpenSearchBuilder initializeSchema(boolean initializeSchema) { + this.initializeSchema = initializeSchema; + return this; + } + + /** + * Sets the batching strategy. + * @param batchingStrategy The batching strategy to use + * @return The builder instance + * @throws IllegalArgumentException if batchingStrategy is null + */ + public OpenSearchBuilder batchingStrategy(BatchingStrategy batchingStrategy) { + Assert.notNull(batchingStrategy, "batchingStrategy must not be null"); + this.batchingStrategy = batchingStrategy; + return this; + } + + /** + * Sets the filter expression converter. + * @param converter The filter expression converter to use + * @return The builder instance + * @throws IllegalArgumentException if converter is null + */ + public OpenSearchBuilder filterExpressionConverter(FilterExpressionConverter converter) { + Assert.notNull(converter, "filterExpressionConverter must not be null"); + this.filterExpressionConverter = converter; + return this; + } + + /** + * Sets the similarity function for vector comparison. See + * https://opensearch.org/docs/latest/search-plugins/knn/approximate-knn/#spaces + * for available functions. + * @param similarityFunction The similarity function to use + * @return The builder instance + * @throws IllegalArgumentException if similarityFunction is null or empty + */ + public OpenSearchBuilder similarityFunction(String similarityFunction) { + Assert.hasText(similarityFunction, "similarityFunction must not be null or empty"); + this.similarityFunction = similarityFunction; + return this; + } + + /** + * Builds a new OpenSearchVectorStore instance with the configured properties. + * @return A new OpenSearchVectorStore instance + * @throws IllegalStateException if the builder is in an invalid state + */ + @Override + public OpenSearchVectorStore build() { + validate(); + return new OpenSearchVectorStore(this); + } + + } + } diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverterTest.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverterTest.java similarity index 99% rename from vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverterTest.java rename to vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverterTest.java index 77e2a95a0bb..ba511a85091 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchAiSearchFilterExpressionConverterTest.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchAiSearchFilterExpressionConverterTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.util.Date; import java.util.List; diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchImage.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchImage.java similarity index 94% rename from vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchImage.java rename to vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchImage.java index 42c8d9b9c39..99bf315e3ad 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchImage.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchImage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import org.testcontainers.utility.DockerImageName; diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java similarity index 94% rename from vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreIT.java rename to vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java index 5a4a5b20ac9..e650efee830 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.io.IOException; import java.net.URISyntaxException; @@ -47,6 +47,8 @@ import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -396,9 +398,13 @@ public static class TestApplication { @Qualifier("vectorStore") public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { try { - return new OpenSearchVectorStore(new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build()), embeddingModel, true); + return OpenSearchVectorStore.builder() + .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build())) + .embeddingModel(embeddingModel) + .initializeSchema(true) + .build(); } catch (URISyntaxException e) { throw new RuntimeException(e); @@ -409,12 +415,15 @@ public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { @Qualifier("anotherVectorStore") public OpenSearchVectorStore anotherVectorStore(EmbeddingModel embeddingModel) { try { - return new OpenSearchVectorStore("another_index", - new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build()), - embeddingModel, OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION, - true); + return OpenSearchVectorStore.builder() + .index("another_index") + .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build())) + .embeddingModel(embeddingModel) + .mappingJson(OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION) + .initializeSchema(true) + .build(); } catch (URISyntaxException e) { throw new RuntimeException(e); diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreObservationIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java similarity index 92% rename from vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreObservationIT.java rename to vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java index 69a36ce52cd..cba4321fb96 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.io.IOException; import java.net.URISyntaxException; @@ -47,6 +47,8 @@ import org.springframework.ai.observation.conventions.VectorStoreSimilarityMetric; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames; import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.LowCardinalityKeyNames; @@ -205,12 +207,18 @@ public TestObservationRegistry observationRegistry() { public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { try { - return new OpenSearchVectorStore(OpenSearchVectorStore.DEFAULT_INDEX_NAME, - new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build()), - embeddingModel, OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION, true, - observationRegistry, null, new TokenCountBatchingStrategy()); + return OpenSearchVectorStore.builder() + .index(OpenSearchVectorStore.DEFAULT_INDEX_NAME) + .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build())) + .embeddingModel(embeddingModel) + .mappingJson(OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION) + .initializeSchema(true) + .observationRegistry(observationRegistry) + .customObservationConvention(null) + .batchingStrategy(new TokenCountBatchingStrategy()) + .build(); } catch (URISyntaxException e) { throw new RuntimeException(e); diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreWithOllamaIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java similarity index 89% rename from vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreWithOllamaIT.java rename to vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java index ef71b5cf4d3..5ef309c8348 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/OpenSearchVectorStoreWithOllamaIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.opensearch; import java.io.IOException; import java.net.URISyntaxException; @@ -46,6 +46,8 @@ import org.springframework.ai.ollama.management.ModelManagementOptions; import org.springframework.ai.ollama.management.OllamaModelManager; import org.springframework.ai.ollama.management.PullModelStrategy; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -167,9 +169,13 @@ public static class TestApplication { @Qualifier("vectorStore") public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { try { - return new OpenSearchVectorStore(new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build()), embeddingModel, true); + return OpenSearchVectorStore.builder() + .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build())) + .embeddingModel(embeddingModel) + .initializeSchema(true) + .build(); } catch (URISyntaxException e) { throw new RuntimeException(e); @@ -180,12 +186,15 @@ public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { @Qualifier("anotherVectorStore") public OpenSearchVectorStore anotherVectorStore(EmbeddingModel embeddingModel) { try { - return new OpenSearchVectorStore("another_index", - new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build()), - embeddingModel, OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION, - true); + return OpenSearchVectorStore.builder() + .index("another_index") + .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build())) + .embeddingModel(embeddingModel) + .mappingJson(OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION) + .initializeSchema(true) + .build(); } catch (URISyntaxException e) { throw new RuntimeException(e);