diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfiguration.java index 37e02e18db9..5b2ae6d1c79 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfiguration.java @@ -21,7 +21,7 @@ import org.springframework.ai.embedding.BatchingStrategy; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.embedding.TokenCountBatchingStrategy; -import org.springframework.ai.vectorstore.GemFireVectorStore; +import org.springframework.ai.vectorstore.gemfire.GemFireVectorStore; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -63,20 +63,23 @@ public GemFireVectorStore gemfireVectorStore(EmbeddingModel embeddingModel, GemF GemFireConnectionDetails gemFireConnectionDetails, ObjectProvider observationRegistry, ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - var builder = new GemFireVectorStore.GemFireVectorStoreConfig.Builder(); - builder.setHost(gemFireConnectionDetails.getHost()) - .setPort(gemFireConnectionDetails.getPort()) - .setIndexName(properties.getIndexName()) - .setBeamWidth(properties.getBeamWidth()) - .setMaxConnections(properties.getMaxConnections()) - .setBuckets(properties.getBuckets()) - .setVectorSimilarityFunction(properties.getVectorSimilarityFunction()) - .setFields(properties.getFields()) - .setSslEnabled(properties.isSslEnabled()); - return new GemFireVectorStore(builder.build(), embeddingModel, properties.isInitializeSchema(), - observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP), - customObservationConvention.getIfAvailable(() -> null), batchingStrategy); + return GemFireVectorStore.builder() + .host(gemFireConnectionDetails.getHost()) + .port(gemFireConnectionDetails.getPort()) + .indexName(properties.getIndexName()) + .beamWidth(properties.getBeamWidth()) + .maxConnections(properties.getMaxConnections()) + .buckets(properties.getBuckets()) + .vectorSimilarityFunction(properties.getVectorSimilarityFunction()) + .fields(properties.getFields()) + .sslEnabled(properties.isSslEnabled()) + .embeddingModel(embeddingModel) + .initializeSchema(properties.isInitializeSchema()) + .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) + .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) + .batchingStrategy(batchingStrategy) + .build(); } private static class PropertiesGemFireConnectionDetails implements GemFireConnectionDetails { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreProperties.java index 81900788032..fcdfee049b3 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreProperties.java @@ -17,7 +17,7 @@ package org.springframework.ai.autoconfigure.vectorstore.gemfire; import org.springframework.ai.autoconfigure.vectorstore.CommonVectorStoreProperties; -import org.springframework.ai.vectorstore.GemFireVectorStore; +import org.springframework.ai.vectorstore.gemfire.GemFireVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -39,31 +39,31 @@ public class GemFireVectorStoreProperties extends CommonVectorStoreProperties { * "spring.ai.vectorstore.gemfire.host"; * */ - private String host = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_HOST; + private String host = GemFireVectorStore.DEFAULT_HOST; /** * The port of the GemFire to connect to. To specify a custom port, use * "spring.ai.vectorstore.gemfire.port"; */ - private int port = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_PORT; + private int port = GemFireVectorStore.DEFAULT_PORT; /** * The name of the index in the GemFire. To specify a custom index, use * "spring.ai.vectorstore.gemfire.index-name"; */ - private String indexName = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_INDEX_NAME; + private String indexName = GemFireVectorStore.DEFAULT_INDEX_NAME; /** * The beam width for similarity queries. Default value is {@code 100}. To specify a * custom beam width, use "spring.ai.vectorstore.gemfire.beam-width"; */ - private int beamWidth = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_BEAM_WIDTH; + private int beamWidth = GemFireVectorStore.DEFAULT_BEAM_WIDTH; /** * The maximum number of connections allowed. Default value is {@code 16}. To specify * custom number of connections, use "spring.ai.vectorstore.gemfire.max-connections"; */ - private int maxConnections = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_MAX_CONNECTIONS; + private int maxConnections = GemFireVectorStore.DEFAULT_MAX_CONNECTIONS; /** * The similarity function to be used for vector comparisons. Default value is @@ -71,14 +71,14 @@ public class GemFireVectorStoreProperties extends CommonVectorStoreProperties { * "spring.ai.vectorstore.gemfire.vector-similarity-function"; * */ - private String vectorSimilarityFunction = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_SIMILARITY_FUNCTION; + private String vectorSimilarityFunction = GemFireVectorStore.DEFAULT_SIMILARITY_FUNCTION; /** * The fields to be used for queries. Default value is an array containing * {@code "vector"}. To specify custom fields, use * "spring.ai.vectorstore.gemfire.fields" */ - private String[] fields = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_FIELDS; + private String[] fields = GemFireVectorStore.DEFAULT_FIELDS; /** * The number of buckets to use for partitioning the data. Default value is {@code 0}. @@ -86,14 +86,14 @@ public class GemFireVectorStoreProperties extends CommonVectorStoreProperties { * To specify custom buckets, use "spring.ai.vectorstore.gemfire.buckets"; * */ - private int buckets = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_BUCKETS; + private int buckets = GemFireVectorStore.DEFAULT_BUCKETS; /** * Set to true if GemFire cluster is ssl enabled * * To specify sslEnabled, use "spring.ai.vectorstore.gemfire.ssl-enabled"; */ - private boolean sslEnabled = GemFireVectorStore.GemFireVectorStoreConfig.DEFAULT_SSL_ENABLED; + private boolean sslEnabled = GemFireVectorStore.DEFAULT_SSL_ENABLED; public int getBeamWidth() { return this.beamWidth; diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfigurationIT.java index 749e7c2cc5f..1a1debd554e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStoreAutoConfigurationIT.java @@ -38,7 +38,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.GemFireVectorStore; +import org.springframework.ai.vectorstore.gemfire.GemFireVectorStore; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext; diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStorePropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStorePropertiesTests.java index 5f69d6ebbef..e8339a36fad 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStorePropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/gemfire/GemFireVectorStorePropertiesTests.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.Test; -import org.springframework.ai.vectorstore.GemFireVectorStore; +import org.springframework.ai.vectorstore.gemfire.GemFireVectorStore; import static org.assertj.core.api.Assertions.assertThat; diff --git a/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/GemFireVectorStore.java b/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java similarity index 63% rename from vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/GemFireVectorStore.java rename to vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java index 76deb5af01d..f2a74d83e28 100644 --- a/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/GemFireVectorStore.java +++ b/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.gemfire; import java.util.HashMap; import java.util.List; @@ -40,6 +40,8 @@ import org.springframework.ai.embedding.TokenCountBatchingStrategy; import org.springframework.ai.observation.conventions.VectorStoreProvider; import org.springframework.ai.util.JacksonUtils; +import org.springframework.ai.vectorstore.AbstractVectorStoreBuilder; +import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore; import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; @@ -71,25 +73,62 @@ public class GemFireVectorStore extends AbstractObservationVectorStore implement private static final String EMBEDDINGS = "/embeddings"; - private final WebClient client; - - private final EmbeddingModel embeddingModel; + // Query Defaults + private static final String QUERY = "/query"; private static final String DOCUMENT_FIELD = "document"; + // Create Index DEFAULT Values + public static final String DEFAULT_HOST = "localhost"; + + public static final int DEFAULT_PORT = 8080; + + public static final String DEFAULT_INDEX_NAME = "spring-ai-gemfire-index"; + + public static final int UPPER_BOUND_BEAM_WIDTH = 3200; + + public static final int DEFAULT_BEAM_WIDTH = 100; + + private static final int UPPER_BOUND_MAX_CONNECTIONS = 512; + + public static final int DEFAULT_MAX_CONNECTIONS = 16; + + public static final String DEFAULT_SIMILARITY_FUNCTION = "COSINE"; + + public static final String[] DEFAULT_FIELDS = new String[] {}; + + public static final int DEFAULT_BUCKETS = 0; + + public static final boolean DEFAULT_SSL_ENABLED = false; + + private final WebClient client; + private final boolean initializeSchema; private final BatchingStrategy batchingStrategy; private final ObjectMapper objectMapper; + private final String indexName; + + private final int beamWidth; + + private final int maxConnections; + + private final int buckets; + + private final String vectorSimilarityFunction; + + private final String[] fields; + /** - * Configures and initializes a GemFireVectorStore instance based on the provided - * configuration. - * @param config the configuration for the GemFireVectorStore - * @param embeddingModel the embedding client used for generating embeddings - * @param initializeSchema whether to initialize the schema during initialization + * Creates a new GemFireVectorStore with basic configuration. + * @param config the vector store configuration + * @param embeddingModel the embedding model to use + * @param initializeSchema whether to initialize schema + * @deprecated Since 1.0.0-M5, use {@link #builder()} instead */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public GemFireVectorStore(GemFireVectorStoreConfig config, EmbeddingModel embeddingModel, boolean initializeSchema) { this(config, embeddingModel, initializeSchema, ObservationRegistry.NOOP, null, @@ -97,82 +136,87 @@ public GemFireVectorStore(GemFireVectorStoreConfig config, EmbeddingModel embedd } /** - * Configures and initializes a GemFireVectorStore instance based on the provided - * configuration. - * @param config the configuration for the GemFireVectorStore - * @param embeddingModel the embedding client used for generating embeddings - * @param initializeSchema whether to initialize the schema during initialization - * @param observationRegistry the observation registry to use for recording - * observations - * @param customObservationConvention the custom observation convention to use for - * observing operations + * Creates a new GemFireVectorStore with observation configuration. + * @param config the vector store configuration + * @param embeddingModel the embedding model to use + * @param initializeSchema whether to initialize schema + * @param observationRegistry the observation registry + * @param customObservationConvention the custom observation convention + * @deprecated Since 1.0.0-M5, use {@link #builder()} instead */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public GemFireVectorStore(GemFireVectorStoreConfig config, EmbeddingModel embeddingModel, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - super(observationRegistry, customObservationConvention); + this(builder().embeddingModel(embeddingModel) + .host(config.host) + .port(config.port) + .sslEnabled(config.sslEnabled) + .indexName(config.indexName) + .beamWidth(config.beamWidth) + .maxConnections(config.maxConnections) + .buckets(config.buckets) + .vectorSimilarityFunction(config.vectorSimilarityFunction) + .fields(config.fields) + .initializeSchema(initializeSchema) + .observationRegistry(observationRegistry) + .customObservationConvention(customObservationConvention) + .batchingStrategy(batchingStrategy)); + } - Assert.notNull(config, "GemFireVectorStoreConfig must not be null"); - Assert.notNull(embeddingModel, "EmbeddingModel must not be null"); - this.initializeSchema = initializeSchema; - this.indexName = config.indexName; - this.embeddingModel = embeddingModel; - this.beamWidth = config.beamWidth; - this.maxConnections = config.maxConnections; - this.buckets = config.buckets; - this.vectorSimilarityFunction = config.vectorSimilarityFunction; - this.fields = config.fields; + /** + * Protected constructor that accepts a builder instance. This is the preferred way to + * create new GemFireVectorStore instances. + * @param builder the configured builder instance + */ + protected GemFireVectorStore(GemFireBuilder builder) { + super(builder); + + this.initializeSchema = builder.initializeSchema; + this.indexName = builder.indexName; + this.beamWidth = builder.beamWidth; + this.maxConnections = builder.maxConnections; + this.buckets = builder.buckets; + this.vectorSimilarityFunction = builder.vectorSimilarityFunction; + this.fields = builder.fields; + this.batchingStrategy = builder.batchingStrategy; String base = UriComponentsBuilder.fromUriString(DEFAULT_URI) - .build(config.sslEnabled ? "s" : "", config.host, config.port) + .build(builder.sslEnabled ? "s" : "", builder.host, builder.port) .toString(); this.client = WebClient.create(base); - this.batchingStrategy = batchingStrategy; this.objectMapper = JsonMapper.builder().addModules(JacksonUtils.instantiateAvailableModules()).build(); } - // Create Index Parameters - - private String indexName; + public static GemFireBuilder builder() { + return new GemFireBuilder(); + } public String getIndexName() { return this.indexName; } - private int beamWidth; - public int getBeamWidth() { return this.beamWidth; } - private int maxConnections; - public int getMaxConnections() { return this.maxConnections; } - private int buckets; - public int getBuckets() { return this.buckets; } - private String vectorSimilarityFunction; - public String getVectorSimilarityFunction() { return this.vectorSimilarityFunction; } - private String[] fields; - public String[] getFields() { return this.fields; } - // Query Defaults - private static final String QUERY = "/query"; - /** * Initializes the GemFireVectorStore after properties are set. This method is called * after all bean properties have been set and allows the bean to perform any @@ -556,6 +600,12 @@ public void setDeleteData(boolean deleteData) { } + /** + * Configuration class for GemFire Vector Store. + * + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public static final class GemFireVectorStoreConfig { // Create Index DEFAULT Values @@ -599,6 +649,10 @@ public static final class GemFireVectorStoreConfig { boolean sslEnabled; + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) private GemFireVectorStoreConfig(Builder builder) { this.host = builder.host; this.port = builder.port; @@ -614,11 +668,17 @@ private GemFireVectorStoreConfig(Builder builder) { /** * Start building a new configuration. * @return The entry point for creating a new configuration. + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} instead */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public static Builder builder() { return new Builder(); } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public static class Builder { // Create Index DEFAULT Values @@ -640,29 +700,54 @@ public static class Builder { boolean sslEnabled = GemFireVectorStoreConfig.DEFAULT_SSL_ENABLED; + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setHost(String host) { Assert.hasText(host, "host must have a value"); this.host = host; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setPort(int port) { Assert.isTrue(port > 0, "port must be positive"); this.port = port; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setSslEnabled(boolean sslEnabled) { this.sslEnabled = sslEnabled; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setIndexName(String indexName) { Assert.hasText(indexName, "indexName must have a value"); this.indexName = indexName; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setBeamWidth(int beamWidth) { Assert.isTrue(beamWidth > 0, "beamWidth must be positive"); Assert.isTrue(beamWidth <= GemFireVectorStoreConfig.UPPER_BOUND_BEAM_WIDTH, @@ -671,6 +756,11 @@ public Builder setBeamWidth(int beamWidth) { return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setMaxConnections(int maxConnections) { Assert.isTrue(maxConnections > 0, "maxConnections must be positive"); Assert.isTrue(maxConnections <= GemFireVectorStoreConfig.UPPER_BOUND_MAX_CONNECTIONS, @@ -680,23 +770,43 @@ public Builder setMaxConnections(int maxConnections) { return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setBuckets(int buckets) { Assert.isTrue(buckets >= 0, "bucket must be 1 or more"); this.buckets = buckets; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setVectorSimilarityFunction(String vectorSimilarityFunction) { Assert.hasText(vectorSimilarityFunction, "vectorSimilarityFunction must have a value"); this.vectorSimilarityFunction = vectorSimilarityFunction; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public Builder setFields(String[] fields) { this.fields = fields; return this; } + /** + * @deprecated Since 1.0.0-M5, use {@link GemFireVectorStore#builder()} + * instead + */ + @Deprecated(since = "1.0.0-M5", forRemoval = true) public GemFireVectorStoreConfig build() { return new GemFireVectorStoreConfig(this); } @@ -705,4 +815,173 @@ public GemFireVectorStoreConfig build() { } + /** + * Builder class for creating {@link GemFireVectorStore} instances. + *

+ * Provides a fluent API for configuring all aspects of the GemFire vector store. + * + * @since 1.0.0 + */ + public static class GemFireBuilder extends AbstractVectorStoreBuilder { + + private String host = GemFireVectorStore.DEFAULT_HOST; + + private int port = GemFireVectorStore.DEFAULT_PORT; + + private boolean sslEnabled = GemFireVectorStore.DEFAULT_SSL_ENABLED; + + private String indexName = GemFireVectorStore.DEFAULT_INDEX_NAME; + + private int beamWidth = GemFireVectorStore.DEFAULT_BEAM_WIDTH; + + private int maxConnections = GemFireVectorStore.DEFAULT_MAX_CONNECTIONS; + + private int buckets = GemFireVectorStore.DEFAULT_BUCKETS; + + private String vectorSimilarityFunction = GemFireVectorStore.DEFAULT_SIMILARITY_FUNCTION; + + private String[] fields = GemFireVectorStore.DEFAULT_FIELDS; + + private boolean initializeSchema = false; + + private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); + + /** + * Sets the host for the GemFire connection. + * @param host the host to connect to + * @return the builder instance + * @throws IllegalArgumentException if host is null or empty + */ + public GemFireBuilder host(String host) { + Assert.hasText(host, "host must have a value"); + this.host = host; + return this; + } + + /** + * Sets the port for the GemFire connection. + * @param port the port to connect to + * @return the builder instance + * @throws IllegalArgumentException if port is not positive + */ + public GemFireBuilder port(int port) { + Assert.isTrue(port > 0, "port must be positive"); + this.port = port; + return this; + } + + /** + * Sets whether SSL is enabled for the connection. + * @param sslEnabled true to enable SSL, false otherwise + * @return the builder instance + */ + public GemFireBuilder sslEnabled(boolean sslEnabled) { + this.sslEnabled = sslEnabled; + return this; + } + + /** + * Sets the index name. + * @param indexName the name of the index + * @return the builder instance + * @throws IllegalArgumentException if indexName is null or empty + */ + public GemFireBuilder indexName(String indexName) { + Assert.hasText(indexName, "indexName must have a value"); + this.indexName = indexName; + return this; + } + + /** + * Sets the beam width. + * @param beamWidth the beam width value + * @return the builder instance + * @throws IllegalArgumentException if beamWidth is not within valid range + */ + public GemFireBuilder beamWidth(int beamWidth) { + Assert.isTrue(beamWidth > 0, "beamWidth must be positive"); + Assert.isTrue(beamWidth <= GemFireVectorStore.UPPER_BOUND_BEAM_WIDTH, + "beamWidth must be less than or equal to " + GemFireVectorStore.UPPER_BOUND_BEAM_WIDTH); + this.beamWidth = beamWidth; + return this; + } + + /** + * Sets the maximum number of connections. + * @param maxConnections the maximum connections value + * @return the builder instance + * @throws IllegalArgumentException if maxConnections is not within valid range + */ + public GemFireBuilder maxConnections(int maxConnections) { + Assert.isTrue(maxConnections > 0, "maxConnections must be positive"); + Assert.isTrue(maxConnections <= GemFireVectorStore.UPPER_BOUND_MAX_CONNECTIONS, + "maxConnections must be less than or equal to " + GemFireVectorStore.UPPER_BOUND_MAX_CONNECTIONS); + this.maxConnections = maxConnections; + return this; + } + + /** + * Sets the number of buckets. + * @param buckets the number of buckets + * @return the builder instance + * @throws IllegalArgumentException if buckets is negative + */ + public GemFireBuilder buckets(int buckets) { + Assert.isTrue(buckets >= 0, "buckets must not be negative"); + this.buckets = buckets; + return this; + } + + /** + * Sets the vector similarity function. + * @param vectorSimilarityFunction the similarity function to use + * @return the builder instance + * @throws IllegalArgumentException if vectorSimilarityFunction is null or empty + */ + public GemFireBuilder vectorSimilarityFunction(String vectorSimilarityFunction) { + Assert.hasText(vectorSimilarityFunction, "vectorSimilarityFunction must have a value"); + this.vectorSimilarityFunction = vectorSimilarityFunction; + return this; + } + + /** + * Sets the fields array. + * @param fields the fields to use + * @return the builder instance + */ + public GemFireBuilder fields(String[] fields) { + this.fields = fields; + return this; + } + + /** + * Sets whether to initialize the schema. + * @param initializeSchema true to initialize schema, false otherwise + * @return the builder instance + */ + public GemFireBuilder initializeSchema(boolean initializeSchema) { + this.initializeSchema = initializeSchema; + return this; + } + + /** + * Sets the batching strategy. + * @param batchingStrategy the strategy to use + * @return the builder instance + * @throws IllegalArgumentException if batchingStrategy is null + */ + public GemFireBuilder batchingStrategy(BatchingStrategy batchingStrategy) { + Assert.notNull(batchingStrategy, "BatchingStrategy must not be null"); + this.batchingStrategy = batchingStrategy; + return this; + } + + @Override + public GemFireVectorStore build() { + validate(); + return new GemFireVectorStore(this); + } + + } + } diff --git a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireImage.java b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireImage.java similarity index 94% rename from vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireImage.java rename to vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireImage.java index f267634a249..4bab6892b3d 100644 --- a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireImage.java +++ b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireImage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.gemfire; import org.testcontainers.utility.DockerImageName; diff --git a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreIT.java b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java similarity index 96% rename from vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreIT.java rename to vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java index 1430520fe2c..8fe5bb069d7 100644 --- a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreIT.java +++ b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.gemfire; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -37,6 +37,8 @@ import org.springframework.ai.document.DocumentMetadata; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.transformers.TransformersEmbeddingModel; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -216,11 +218,13 @@ public static class TestApplication { @Bean public GemFireVectorStore vectorStore(EmbeddingModel embeddingModel) { - return new GemFireVectorStore(GemFireVectorStore.GemFireVectorStoreConfig.builder() - .setHost("localhost") - .setPort(HTTP_SERVICE_PORT) - .setIndexName(INDEX_NAME) - .build(), embeddingModel, true); + return GemFireVectorStore.builder() + .host("localhost") + .port(HTTP_SERVICE_PORT) + .indexName(INDEX_NAME) + .embeddingModel(embeddingModel) + .initializeSchema(true) + .build(); } @Bean diff --git a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreObservationIT.java b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java similarity index 94% rename from vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreObservationIT.java rename to vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java index 4a780955ac2..b3f17e09220 100644 --- a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/GemFireVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.ai.vectorstore; +package org.springframework.ai.vectorstore.gemfire; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -40,6 +40,8 @@ import org.springframework.ai.observation.conventions.SpringAiKind; import org.springframework.ai.observation.conventions.VectorStoreProvider; import org.springframework.ai.transformers.TransformersEmbeddingModel; +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; @@ -198,11 +200,16 @@ public TestObservationRegistry observationRegistry() { @Bean public GemFireVectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return new GemFireVectorStore(GemFireVectorStore.GemFireVectorStoreConfig.builder() - .setHost("localhost") - .setPort(HTTP_SERVICE_PORT) - .setIndexName(TEST_INDEX_NAME) - .build(), embeddingModel, true, observationRegistry, null, new TokenCountBatchingStrategy()); + return GemFireVectorStore.builder() + .host("localhost") + .port(HTTP_SERVICE_PORT) + .indexName(TEST_INDEX_NAME) + .embeddingModel(embeddingModel) + .initializeSchema(true) + .observationRegistry(observationRegistry) + .customObservationConvention(null) + .batchingStrategy(new TokenCountBatchingStrategy()) + .build(); } @Bean