From ee8bf373592800c9d206499f3701d20d40ff4f9e Mon Sep 17 00:00:00 2001 From: Soby Chacko Date: Thu, 19 Dec 2024 11:47:19 -0500 Subject: [PATCH] Require essential dependencies in vector store builder constructors This commit refactors the builder pattern implementation across all VectorStore implementations to make the EmbeddingModel a required constructor parameter rather than an optional builder method. Key changes include: - Move embeddingModel from being a builder method to a required constructor parameter - Make embeddingModel final in AbstractVectorStoreBuilder - Remove redundant validate() methods since EmbeddingModel validation now happens in constructor - Update all VectorStore builder instantiations to pass EmbeddingModel in builder creation - Add @Nullable annotations to appropriate methods in VectorStore interface This change improves the API design by: 1. Enforcing that EmbeddingModel is provided at builder creation time 2. Removing the possibility of forgotten EmbeddingModel configuration 3. Simplifying the builder implementation by moving validation to construction 4. Making the dependency on EmbeddingModel more explicit in the API Breaking Changes: - VectorStore builders must now be created with an EmbeddingModel parameter - The embeddingModel() builder method has been removed from all implementations --- .../ai/embedding/package-info.java | 25 ++++++++ .../AbstractVectorStoreBuilder.java | 20 +++--- .../ai/vectorstore/SimpleVectorStore.java | 12 ++-- .../ai/vectorstore/VectorStore.java | 6 +- .../AbstractObservationVectorStore.java | 6 +- .../vectorstore/SimpleVectorStoreTests.java | 2 +- .../AzureVectorStoreAutoConfiguration.java | 4 +- ...CassandraVectorStoreAutoConfiguration.java | 3 +- .../ChromaVectorStoreAutoConfiguration.java | 4 +- ...ticsearchVectorStoreAutoConfiguration.java | 4 +- .../GemFireVectorStoreAutoConfiguration.java | 3 +- ...HanaCloudVectorStoreAutoConfiguration.java | 4 +- .../MariaDbStoreAutoConfiguration.java | 3 +- .../MilvusVectorStoreAutoConfiguration.java | 4 +- ...goDBAtlasVectorStoreAutoConfiguration.java | 4 +- .../Neo4jVectorStoreAutoConfiguration.java | 4 +- ...penSearchVectorStoreAutoConfiguration.java | 4 +- .../OracleVectorStoreAutoConfiguration.java | 4 +- .../PgVectorStoreAutoConfiguration.java | 4 +- .../PineconeVectorStoreAutoConfiguration.java | 3 +- .../QdrantVectorStoreAutoConfiguration.java | 3 +- .../RedisVectorStoreAutoConfiguration.java | 6 +- ...TypesenseVectorStoreAutoConfiguration.java | 4 +- .../WeaviateVectorStoreAutoConfiguration.java | 4 +- .../cosmosdb/CosmosDBVectorStore.java | 15 ++--- .../cosmosdb/CosmosDBVectorStoreIT.java | 4 +- .../vectorstore/azure/AzureVectorStore.java | 15 ++--- .../vectorstore/azure/AzureVectorStoreIT.java | 4 +- .../azure/AzureVectorStoreObservationIT.java | 4 +- .../cassandra/CassandraVectorStore.java | 33 +++++----- .../CassandraRichSchemaVectorStoreIT.java | 5 +- .../cassandra/CassandraVectorStoreIT.java | 23 +++---- .../CassandraVectorStoreObservationIT.java | 3 +- .../cassandra/WikiVectorStoreExample.java | 3 +- .../ai/chroma/vectorstore/ChromaApi.java | 27 +++++--- .../chroma/vectorstore/ChromaVectorStore.java | 29 ++++----- .../vectorstore/BasicAuthChromaWhereIT.java | 4 +- .../ai/chroma/vectorstore/ChromaApiIT.java | 10 +-- .../vectorstore/ChromaVectorStoreIT.java | 4 +- .../ChromaVectorStoreObservationIT.java | 4 +- .../TokenSecuredChromaWhereIT.java | 4 +- .../coherence/CoherenceVectorStore.java | 13 ++-- .../coherence/CoherenceVectorStoreIT.java | 4 +- .../ElasticsearchVectorStore.java | 15 ++--- .../ElasticsearchVectorStoreIT.java | 14 +---- ...ElasticsearchVectorStoreObservationIT.java | 4 +- .../gemfire/GemFireVectorStore.java | 12 ++-- .../gemfire/GemFireVectorStoreIT.java | 3 +- .../GemFireVectorStoreObservationIT.java | 3 +- .../hanadb/HanaCloudVectorStore.java | 17 +++--- .../hanadb/HanaCloudVectorStoreIT.java | 4 +- .../hanadb/HanaVectorStoreObservationIT.java | 4 +- .../mariadb/MariaDBVectorStore.java | 11 ++-- .../MariaDBEmbeddingDimensionsTests.java | 9 +-- .../mariadb/MariaDBStoreCustomNamesIT.java | 3 +- .../vectorstore/mariadb/MariaDBStoreIT.java | 3 +- .../mariadb/MariaDBStoreObservationIT.java | 3 +- .../mariadb/MariaDBStoreTests.java | 3 +- .../MariaDBVectorStoreBuilderTests.java | 61 ++++++++----------- .../milvus/vectorstore/MilvusVectorStore.java | 17 +++--- .../MilvusEmbeddingDimensionsTests.java | 16 ++--- .../MilvusVectorStoreCustomFieldNamesIT.java | 4 +- .../vectorstore/MilvusVectorStoreIT.java | 4 +- .../MilvusVectorStoreObservationIT.java | 4 +- .../atlas/MongoDBAtlasVectorStore.java | 15 ++--- .../atlas/MongoDBAtlasVectorStoreIT.java | 4 +- .../MongoDbVectorStoreObservationIT.java | 4 +- .../vectorstore/neo4j/Neo4jVectorStore.java | 15 ++--- .../vectorstore/neo4j/Neo4jVectorStoreIT.java | 6 +- .../neo4j/Neo4jVectorStoreObservationIT.java | 4 +- .../opensearch/OpenSearchVectorStore.java | 27 ++------ .../opensearch/OpenSearchVectorStoreIT.java | 20 +++--- .../OpenSearchVectorStoreObservationIT.java | 9 ++- .../OpenSearchVectorStoreWithOllamaIT.java | 20 +++--- .../vectorstore/oracle/OracleVectorStore.java | 13 ++-- .../oracle/OracleVectorStoreIT.java | 4 +- .../OracleVectorStoreObservationIT.java | 4 +- .../vectorstore/pgvector/PgVectorStore.java | 16 ++--- .../PgVectorEmbeddingDimensionsTests.java | 14 +---- .../pgvector/PgVectorStoreCustomNamesIT.java | 4 +- .../vectorstore/pgvector/PgVectorStoreIT.java | 4 +- .../pgvector/PgVectorStoreObservationIT.java | 4 +- .../pgvector/PgVectorStoreTests.java | 6 +- .../pinecone/PineconeVectorStore.java | 12 ++-- .../pinecone/PineconeVectorStoreIT.java | 3 +- .../PineconeVectorStoreObservationIT.java | 3 +- .../vectorstore/qdrant/QdrantVectorStore.java | 15 +++-- .../qdrant/QdrantVectorStoreBuilderTests.java | 19 +++--- .../qdrant/QdrantVectorStoreIT.java | 3 +- .../QdrantVectorStoreObservationIT.java | 3 +- .../vectorstore/redis/RedisVectorStore.java | 15 ++--- .../vectorstore/redis/RedisVectorStoreIT.java | 6 +- .../redis/RedisVectorStoreObservationIT.java | 6 +- .../typesense/TypesenseVectorStore.java | 15 ++--- .../TypesenseVectorStoreBuilderTests.java | 38 ++++-------- .../typesense/TypesenseVectorStoreIT.java | 4 +- .../TypesenseVectorStoreObservationIT.java | 4 +- .../weaviate/WeaviateVectorStore.java | 15 ++--- .../WeaviateVectorStoreBuilderTests.java | 39 +++++------- .../weaviate/WeaviateVectorStoreIT.java | 4 +- .../WeaviateVectorStoreObservationIT.java | 4 +- 101 files changed, 382 insertions(+), 581 deletions(-) create mode 100644 spring-ai-core/src/main/java/org/springframework/ai/embedding/package-info.java diff --git a/spring-ai-core/src/main/java/org/springframework/ai/embedding/package-info.java b/spring-ai-core/src/main/java/org/springframework/ai/embedding/package-info.java new file mode 100644 index 000000000..e28a215d4 --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/embedding/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright 2023-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Provides the API for embedding observations. + */ +@NonNullApi +@NonNullFields +package org.springframework.ai.embedding; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/AbstractVectorStoreBuilder.java b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/AbstractVectorStoreBuilder.java index 0affbdcc8..8ee7f88b5 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/AbstractVectorStoreBuilder.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/AbstractVectorStoreBuilder.java @@ -33,13 +33,18 @@ import org.springframework.util.Assert; public abstract class AbstractVectorStoreBuilder> implements VectorStore.Builder { - protected EmbeddingModel embeddingModel; + protected final EmbeddingModel embeddingModel; protected ObservationRegistry observationRegistry = ObservationRegistry.NOOP; @Nullable protected VectorStoreObservationConvention customObservationConvention; + public AbstractVectorStoreBuilder(EmbeddingModel embeddingModel) { + Assert.notNull(embeddingModel, "EmbeddingModel must be configured"); + this.embeddingModel = embeddingModel; + } + public EmbeddingModel getEmbeddingModel() { return this.embeddingModel; } @@ -71,20 +76,9 @@ public abstract class AbstractVectorStoreBuilder { + private SimpleVectorStoreBuilder(EmbeddingModel embeddingModel) { + super(embeddingModel); + } + @Override public SimpleVectorStore build() { - validate(); return new SimpleVectorStore(this); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/VectorStore.java b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/VectorStore.java index faea243a7..5c2dd00da 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/VectorStore.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/VectorStore.java @@ -23,7 +23,6 @@ import io.micrometer.observation.ObservationRegistry; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentWriter; -import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; import org.springframework.lang.Nullable; @@ -59,6 +58,7 @@ public interface VectorStore extends DocumentWriter { * @param idList list of document ids for which documents will be removed. * @return Returns true if the documents were successfully deleted. */ + @Nullable Optional delete(List idList); /** @@ -68,6 +68,7 @@ public interface VectorStore extends DocumentWriter { * topK, similarity threshold and metadata filter expressions. * @return Returns documents th match the query request conditions. */ + @Nullable List similaritySearch(SearchRequest request); /** @@ -77,6 +78,7 @@ public interface VectorStore extends DocumentWriter { * @return Returns a list of documents that have embeddings similar to the query text * embedding. */ + @Nullable default List similaritySearch(String query) { return this.similaritySearch(SearchRequest.query(query)); } @@ -90,8 +92,6 @@ public interface VectorStore extends DocumentWriter { */ interface Builder> { - T embeddingModel(EmbeddingModel embeddingModel); - /** * Sets the registry for collecting observations and metrics. Defaults to * {@link ObservationRegistry#NOOP} if not specified. diff --git a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java index 81e704d99..ec6c641be 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java @@ -45,7 +45,6 @@ public abstract class AbstractObservationVectorStore implements VectorStore { @Nullable private final VectorStoreObservationConvention customObservationConvention; - @Nullable protected final EmbeddingModel embeddingModel; /** @@ -59,8 +58,7 @@ public abstract class AbstractObservationVectorStore implements VectorStore { this(null, observationRegistry, customObservationConvention); } - private AbstractObservationVectorStore(@Nullable EmbeddingModel embeddingModel, - ObservationRegistry observationRegistry, + private AbstractObservationVectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry, @Nullable VectorStoreObservationConvention customObservationConvention) { this.embeddingModel = embeddingModel; this.observationRegistry = observationRegistry; @@ -94,6 +92,7 @@ public abstract class AbstractObservationVectorStore implements VectorStore { } @Override + @Nullable public Optional delete(List deleteDocIds) { VectorStoreObservationContext observationContext = this @@ -107,6 +106,7 @@ public abstract class AbstractObservationVectorStore implements VectorStore { } @Override + @Nullable public List similaritySearch(SearchRequest request) { VectorStoreObservationContext searchObservationContext = this diff --git a/spring-ai-core/src/test/java/org/springframework/ai/vectorstore/SimpleVectorStoreTests.java b/spring-ai-core/src/test/java/org/springframework/ai/vectorstore/SimpleVectorStoreTests.java index 41bdbb457..6e05264a6 100644 --- a/spring-ai-core/src/test/java/org/springframework/ai/vectorstore/SimpleVectorStoreTests.java +++ b/spring-ai-core/src/test/java/org/springframework/ai/vectorstore/SimpleVectorStoreTests.java @@ -57,7 +57,7 @@ class SimpleVectorStoreTests { when(this.mockEmbeddingModel.dimensions()).thenReturn(3); when(this.mockEmbeddingModel.embed(any(String.class))).thenReturn(new float[] { 0.1f, 0.2f, 0.3f }); when(this.mockEmbeddingModel.embed(any(Document.class))).thenReturn(new float[] { 0.1f, 0.2f, 0.3f }); - this.vectorStore = new SimpleVectorStore(SimpleVectorStore.builder().embeddingModel(this.mockEmbeddingModel)); + this.vectorStore = new SimpleVectorStore(SimpleVectorStore.builder(this.mockEmbeddingModel)); } @Test diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreAutoConfiguration.java index 7db2a7936..d3f702a2a 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreAutoConfiguration.java @@ -84,9 +84,7 @@ public class AzureVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - var builder = AzureVectorStore.builder() - .searchIndexClient(searchIndexClient) - .embeddingModel(embeddingModel) + var builder = AzureVectorStore.builder(searchIndexClient, embeddingModel) .initializeSchema(properties.isInitializeSchema()) .filterMetadataFields(List.of()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/cassandra/CassandraVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/cassandra/CassandraVectorStoreAutoConfiguration.java index 64890673b..2e63baf7a 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/cassandra/CassandraVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/cassandra/CassandraVectorStoreAutoConfiguration.java @@ -62,7 +62,7 @@ public class CassandraVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return CassandraVectorStore.builder() + return CassandraVectorStore.builder(embeddingModel) .session(cqlSession) .keyspace(properties.getKeyspace()) .table(properties.getTable()) @@ -72,7 +72,6 @@ public class CassandraVectorStoreAutoConfiguration { .fixedThreadPoolExecutorSize(properties.getFixedThreadPoolExecutorSize()) .disallowSchemaChanges(!properties.isInitializeSchema()) .returnEmbeddings(properties.getReturnEmbeddings()) - .embeddingModel(embeddingModel) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) .batchingStrategy(batchingStrategy) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfiguration.java index 50f758918..898a04444 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfiguration.java @@ -86,9 +86,7 @@ public class ChromaVectorStoreAutoConfiguration { ChromaVectorStoreProperties storeProperties, ObjectProvider observationRegistry, ObjectProvider customObservationConvention, BatchingStrategy chromaBatchingStrategy) { - return ChromaVectorStore.builder() - .chromaApi(chromaApi) - .embeddingModel(embeddingModel) + return ChromaVectorStore.builder(chromaApi, embeddingModel) .collectionName(storeProperties.getCollectionName()) .initializeSchema(storeProperties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreAutoConfiguration.java index 33d0c2810..8541e8e83 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreAutoConfiguration.java @@ -73,10 +73,8 @@ public class ElasticsearchVectorStoreAutoConfiguration { elasticsearchVectorStoreOptions.setSimilarity(properties.getSimilarity()); } - return ElasticsearchVectorStore.builder() - .restClient(restClient) + return ElasticsearchVectorStore.builder(restClient, embeddingModel) .options(elasticsearchVectorStoreOptions) - .embeddingModel(embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) 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 5b2ae6d1c..26eb432cd 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 @@ -64,7 +64,7 @@ public class GemFireVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return GemFireVectorStore.builder() + return GemFireVectorStore.builder(embeddingModel) .host(gemFireConnectionDetails.getHost()) .port(gemFireConnectionDetails.getPort()) .indexName(properties.getIndexName()) @@ -74,7 +74,6 @@ public class GemFireVectorStoreAutoConfiguration { .vectorSimilarityFunction(properties.getVectorSimilarityFunction()) .fields(properties.getFields()) .sslEnabled(properties.isSslEnabled()) - .embeddingModel(embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfiguration.java index 8c0c85628..3870f8d60 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfiguration.java @@ -53,9 +53,7 @@ public class HanaCloudVectorStoreAutoConfiguration { ObjectProvider observationRegistry, ObjectProvider customObservationConvention) { - return HanaCloudVectorStore.builder() - .repository(repository) - .embeddingModel(embeddingModel) + return HanaCloudVectorStore.builder(repository, embeddingModel) .tableName(properties.getTableName()) .topK(properties.getTopK()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mariadb/MariaDbStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mariadb/MariaDbStoreAutoConfiguration.java index b5b69e53e..e3c72674e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mariadb/MariaDbStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mariadb/MariaDbStoreAutoConfiguration.java @@ -57,8 +57,7 @@ public class MariaDbStoreAutoConfiguration { var initializeSchema = properties.isInitializeSchema(); - return MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + return MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName(properties.getSchemaName()) .vectorTableName(properties.getTableName()) .schemaValidation(properties.isSchemaValidation()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreAutoConfiguration.java index 1dc3eb5df..029a1be61 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreAutoConfiguration.java @@ -71,9 +71,7 @@ public class MilvusVectorStoreAutoConfiguration { ObjectProvider observationRegistry, ObjectProvider customObservationConvention) { - return MilvusVectorStore.builder() - .milvusClient(milvusClient) - .embeddingModel(embeddingModel) + return MilvusVectorStore.builder(milvusClient, embeddingModel) .initializeSchema(properties.isInitializeSchema()) .batchingStrategy(batchingStrategy) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java index ec3a9eb98..8bb976346 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreAutoConfiguration.java @@ -66,9 +66,7 @@ public class MongoDBAtlasVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - MongoDBAtlasVectorStore.MongoDBBuilder builder = MongoDBAtlasVectorStore.builder() - .mongoTemplate(mongoTemplate) - .embeddingModel(embeddingModel) + MongoDBAtlasVectorStore.MongoDBBuilder builder = MongoDBAtlasVectorStore.builder(mongoTemplate, embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java index aac5576d1..5d3d114c1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java @@ -58,9 +58,7 @@ public class Neo4jVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return Neo4jVectorStore.builder() - .driver(driver) - .embeddingModel(embeddingModel) + return Neo4jVectorStore.builder(driver, embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) 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 28a4e4529..b844e9bbf 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 @@ -79,10 +79,8 @@ public class OpenSearchVectorStoreAutoConfiguration { var mappingJson = Optional.ofNullable(properties.getMappingJson()) .orElse(OpenSearchVectorStore.DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION); - return OpenSearchVectorStore.builder() + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel) .index(indexName) - .openSearchClient(openSearchClient) - .embeddingModel(embeddingModel) .mappingJson(mappingJson) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/oracle/OracleVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/oracle/OracleVectorStoreAutoConfiguration.java index f8fcff20d..5e2d22b69 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/oracle/OracleVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/oracle/OracleVectorStoreAutoConfiguration.java @@ -60,9 +60,7 @@ public class OracleVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return OracleVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return OracleVectorStore.builder(jdbcTemplate, embeddingModel) .tableName(properties.getTableName()) .indexType(properties.getIndexType()) .distanceType(properties.getDistanceType()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreAutoConfiguration.java index 441aca334..95075ed20 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreAutoConfiguration.java @@ -62,9 +62,7 @@ public class PgVectorStoreAutoConfiguration { var initializeSchema = properties.isInitializeSchema(); - return PgVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return PgVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName(properties.getSchemaName()) .vectorTableName(properties.getTableName()) .vectorTableValidationsEnabled(properties.isSchemaValidation()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pinecone/PineconeVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pinecone/PineconeVectorStoreAutoConfiguration.java index ba39ecec7..f56d596c1 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pinecone/PineconeVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pinecone/PineconeVectorStoreAutoConfiguration.java @@ -55,8 +55,7 @@ public class PineconeVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return PineconeVectorStore.builder() - .embeddingModel(embeddingModel) + return PineconeVectorStore.builder(embeddingModel) .apiKey(properties.getApiKey()) .environment(properties.getEnvironment()) .projectId(properties.getProjectId()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java index 790b53c3a..0521484be 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreAutoConfiguration.java @@ -77,9 +77,8 @@ public class QdrantVectorStoreAutoConfiguration { QdrantClient qdrantClient, ObjectProvider observationRegistry, ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return QdrantVectorStore.builder(qdrantClient) + return QdrantVectorStore.builder(qdrantClient, embeddingModel) .collectionName(properties.getCollectionName()) - .embeddingModel(embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreAutoConfiguration.java index 42516395c..9b3187671 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreAutoConfiguration.java @@ -60,9 +60,9 @@ public class RedisVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return RedisVectorStore.builder() - .jedis(new JedisPooled(jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort())) - .embeddingModel(embeddingModel) + JedisPooled jedisPooled = new JedisPooled(jedisConnectionFactory.getHostName(), + jedisConnectionFactory.getPort()); + return RedisVectorStore.builder(jedisPooled, embeddingModel) .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/typesense/TypesenseVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/typesense/TypesenseVectorStoreAutoConfiguration.java index 9d259a274..823c32566 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/typesense/TypesenseVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/typesense/TypesenseVectorStoreAutoConfiguration.java @@ -70,9 +70,7 @@ public class TypesenseVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return TypesenseVectorStore.builder() - .client(typesenseClient) - .embeddingModel(embeddingModel) + return TypesenseVectorStore.builder(typesenseClient, embeddingModel) .collectionName(properties.getCollectionName()) .embeddingDimension(properties.getEmbeddingDimension()) .initializeSchema(properties.isInitializeSchema()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreAutoConfiguration.java index 1e7101700..3fd8d7c51 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreAutoConfiguration.java @@ -81,9 +81,7 @@ public class WeaviateVectorStoreAutoConfiguration { ObjectProvider customObservationConvention, BatchingStrategy batchingStrategy) { - return WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) + return WeaviateVectorStore.builder(weaviateClient, embeddingModel) .objectClass(properties.getObjectClass()) .filterMetadataFields(properties.getFilterField() .entrySet() diff --git a/vector-stores/spring-ai-azure-cosmos-db-store/src/main/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStore.java b/vector-stores/spring-ai-azure-cosmos-db-store/src/main/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStore.java index 8de1f30d3..34a2d89fd 100644 --- a/vector-stores/spring-ai-azure-cosmos-db-store/src/main/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStore.java +++ b/vector-stores/spring-ai-azure-cosmos-db-store/src/main/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStore.java @@ -132,9 +132,7 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen public CosmosDBVectorStore(ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, CosmosAsyncClient cosmosClient, CosmosDBVectorStoreConfig properties, EmbeddingModel embeddingModel, BatchingStrategy batchingStrategy) { - this(builder().cosmosClient(cosmosClient) - .embeddingModel(embeddingModel) - .containerName(properties.getContainerName()) + this(builder(cosmosClient, embeddingModel).containerName(properties.getContainerName()) .databaseName(properties.getDatabaseName()) .partitionKeyPath(properties.getPartitionKeyPath()) .vectorStoreThroughput(properties.getVectorStoreThroughput()) @@ -171,8 +169,8 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen initializeContainer(containerName, databaseName, vectorStoreThroughput, vectorDimensions, partitionKeyPath); } - public static CosmosDBBuilder builder() { - return new CosmosDBBuilder(); + public static CosmosDBBuilder builder(CosmosAsyncClient cosmosClient, EmbeddingModel embeddingModel) { + return new CosmosDBBuilder(cosmosClient, embeddingModel); } private void initializeContainer(String containerName, String databaseName, int vectorStoreThroughput, @@ -430,7 +428,7 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen */ public static class CosmosDBBuilder extends AbstractVectorStoreBuilder { - private CosmosAsyncClient cosmosClient; + private final CosmosAsyncClient cosmosClient; private String containerName; @@ -452,10 +450,10 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen * @return the builder instance * @throws IllegalArgumentException if cosmosClient is null */ - public CosmosDBBuilder cosmosClient(CosmosAsyncClient cosmosClient) { + public CosmosDBBuilder(CosmosAsyncClient cosmosClient, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(cosmosClient, "CosmosClient must not be null"); this.cosmosClient = cosmosClient; - return this; } /** @@ -543,7 +541,6 @@ public class CosmosDBVectorStore extends AbstractObservationVectorStore implemen @Override public CosmosDBVectorStore build() { - validate(); return new CosmosDBVectorStore(this); } diff --git a/vector-stores/spring-ai-azure-cosmos-db-store/src/test/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStoreIT.java b/vector-stores/spring-ai-azure-cosmos-db-store/src/test/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStoreIT.java index 10acb4c69..1b07505d9 100644 --- a/vector-stores/spring-ai-azure-cosmos-db-store/src/test/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStoreIT.java +++ b/vector-stores/spring-ai-azure-cosmos-db-store/src/test/java/org/springframework/ai/vectorstore/cosmosdb/CosmosDBVectorStoreIT.java @@ -167,13 +167,11 @@ public class CosmosDBVectorStoreIT { @Bean public VectorStore vectorStore(CosmosAsyncClient cosmosClient, EmbeddingModel embeddingModel, VectorStoreObservationConvention convention) { - return CosmosDBVectorStore.builder() + return CosmosDBVectorStore.builder(cosmosClient, embeddingModel) .databaseName("test-database") .containerName("test-container") .metadataFields(List.of("country", "year", "city")) .vectorStoreThroughput(1000) - .cosmosClient(cosmosClient) - .embeddingModel(embeddingModel) .customObservationConvention(convention) .build(); } diff --git a/vector-stores/spring-ai-azure-store/src/main/java/org/springframework/ai/vectorstore/azure/AzureVectorStore.java b/vector-stores/spring-ai-azure-store/src/main/java/org/springframework/ai/vectorstore/azure/AzureVectorStore.java index 0151927e0..1e0364e59 100644 --- a/vector-stores/spring-ai-azure-store/src/main/java/org/springframework/ai/vectorstore/azure/AzureVectorStore.java +++ b/vector-stores/spring-ai-azure-store/src/main/java/org/springframework/ai/vectorstore/azure/AzureVectorStore.java @@ -173,9 +173,7 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements boolean initializeSchema, List filterMetadataFields, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().searchIndexClient(searchIndexClient) - .embeddingModel(embeddingModel) - .initializeSchema(initializeSchema) + this(builder(searchIndexClient, embeddingModel).initializeSchema(initializeSchema) .filterMetadataFields(filterMetadataFields) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) @@ -203,8 +201,8 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements this.filterExpressionConverter = new AzureAiSearchFilterExpressionConverter(filterMetadataFields); } - public static AzureBuilder builder() { - return new AzureBuilder(); + public static AzureBuilder builder(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) { + return new AzureBuilder(searchIndexClient, embeddingModel); } /** @@ -469,7 +467,7 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements */ public static class AzureBuilder extends AbstractVectorStoreBuilder { - private SearchIndexClient searchIndexClient; + private final SearchIndexClient searchIndexClient; private boolean initializeSchema = false; @@ -489,10 +487,10 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements * @return the builder instance * @throws IllegalArgumentException if searchIndexClient is null */ - public AzureBuilder searchIndexClient(SearchIndexClient searchIndexClient) { + public AzureBuilder(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(searchIndexClient, "SearchIndexClient must not be null"); this.searchIndexClient = searchIndexClient; - return this; } /** @@ -567,7 +565,6 @@ public class AzureVectorStore extends AbstractObservationVectorStore implements @Override public AzureVectorStore build() { - validate(); return new AzureVectorStore(this); } diff --git a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java index abf622a30..380cfff2b 100644 --- a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java +++ b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java @@ -310,9 +310,7 @@ public class AzureVectorStoreIT { @Bean public VectorStore vectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) { - return AzureVectorStore.builder() - .searchIndexClient(searchIndexClient) - .embeddingModel(embeddingModel) + return AzureVectorStore.builder(searchIndexClient, embeddingModel) .initializeSchema(true) .filterMetadataFields(List.of(MetadataField.text("country"), MetadataField.int64("year"), MetadataField.date("activationDate"))) diff --git a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreObservationIT.java b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreObservationIT.java index 59f905c19..0c4da707f 100644 --- a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreObservationIT.java @@ -183,9 +183,7 @@ public class AzureVectorStoreObservationIT { @Bean public VectorStore vectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return AzureVectorStore.builder() - .searchIndexClient(searchIndexClient) - .embeddingModel(embeddingModel) + return AzureVectorStore.builder(searchIndexClient, embeddingModel) .initializeSchema(true) .filterMetadataFields(List.of(MetadataField.text("country"), MetadataField.int64("year"), MetadataField.date("activationDate"))) diff --git a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java index b6790a367..bb7ad63fb 100644 --- a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java +++ b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java @@ -249,8 +249,7 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme public CassandraVectorStore(CassandraVectorStoreConfig conf, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().session(conf.session) - .embeddingModel(embeddingModel) + this(builder(embeddingModel).session(conf.session) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) .batchingStrategy(batchingStrategy)); @@ -289,8 +288,8 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme this.returnEmbeddings = builder.returnEmbeddings; } - public static CassandraBuilder builder() { - return new CassandraBuilder(); + public static CassandraBuilder builder(EmbeddingModel embeddingModel) { + return new CassandraBuilder(embeddingModel); } private static Float[] toFloatArray(float[] embedding) { @@ -827,16 +826,9 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme private boolean returnEmbeddings = false; - /** - * Executor to use when adding documents. The hotspot is the call to the - * embeddingModel. For remote transformers you probably want a higher value to - * utilize network. For local transformers you probably want a lower value to - * avoid saturation. - **/ - public CassandraBuilder fixedThreadPoolExecutorSize(int threads) { - Preconditions.checkArgument(0 < threads); - this.fixedThreadPoolExecutorSize = threads; - return this; + private CassandraBuilder(EmbeddingModel embeddingModel) { + super(embeddingModel); + Assert.notNull(session, "Session must not be null"); } /** @@ -851,6 +843,18 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme return this; } + /** + * Executor to use when adding documents. The hotspot is the call to the + * embeddingModel. For remote transformers you probably want a higher value to + * utilize network. For local transformers you probably want a lower value to + * avoid saturation. + **/ + public CassandraBuilder fixedThreadPoolExecutorSize(int threads) { + Preconditions.checkArgument(0 < threads); + this.fixedThreadPoolExecutorSize = threads; + return this; + } + /** * Sets the keyspace name. * @param keyspace the keyspace name @@ -1073,7 +1077,6 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme @Override public CassandraVectorStore build() { - validate(); if (session == null && sessionBuilder != null) { session = sessionBuilder.build(); closeSessionOnClose = true; diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java index a48cb29e9..98820eb1a 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java @@ -120,7 +120,7 @@ class CassandraRichSchemaVectorStoreIT { List partitionKeys = List.of(wikiSC, langSC, titleSC); List clusteringKeys = List.of(chunkNoSC); - return CassandraVectorStore.builder() + return CassandraVectorStore.builder(context.getBean(EmbeddingModel.class)) .session(context.getBean(CqlSession.class)) .keyspace("test_wikidata") .table("articles") @@ -253,7 +253,6 @@ class CassandraRichSchemaVectorStoreIT { this.contextRunner.run(context -> { try (CassandraVectorStore store = storeBuilder(context, List.of()).fixedThreadPoolExecutorSize(nThreads) - .embeddingModel(context.getBean(EmbeddingModel.class)) .build()) { var executor = Executors.newFixedThreadPool((int) (nThreads * 1.2)); @@ -552,7 +551,6 @@ class CassandraRichSchemaVectorStoreIT { CassandraVectorStore.dropKeyspace(builder); } - builder.embeddingModel(context.getBean(EmbeddingModel.class)); return new CassandraVectorStore(builder); } @@ -569,7 +567,6 @@ class CassandraRichSchemaVectorStoreIT { CassandraVectorStore.dropKeyspace(builder); } - builder.embeddingModel(context.getBean(EmbeddingModel.class)); return builder; } diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java index b86a95086..f25b4aab5 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java @@ -85,14 +85,16 @@ class CassandraVectorStoreIT { } } - private static CassandraVectorStore.CassandraBuilder storeBuilder(CqlSession cqlSession) { - return CassandraVectorStore.builder() + private static CassandraVectorStore.CassandraBuilder storeBuilder(CqlSession cqlSession, + EmbeddingModel embeddingModel) { + return CassandraVectorStore.builder(embeddingModel) .session(cqlSession) .keyspace("test_" + CassandraVectorStore.DEFAULT_KEYSPACE_NAME); } private static CassandraVectorStore createTestStore(ApplicationContext context, SchemaColumn... metadataFields) { - CassandraVectorStore.CassandraBuilder builder = storeBuilder(context.getBean(CqlSession.class)) + CassandraVectorStore.CassandraBuilder builder = storeBuilder(context.getBean(CqlSession.class), + context.getBean(EmbeddingModel.class)) .addMetadataColumns(metadataFields); return createTestStore(context, builder); @@ -101,7 +103,6 @@ class CassandraVectorStoreIT { private static CassandraVectorStore createTestStore(ApplicationContext context, CassandraVectorStore.CassandraBuilder builder) { CassandraVectorStore.dropKeyspace(builder); - builder.embeddingModel(context.getBean(EmbeddingModel.class)); CassandraVectorStore store = builder.build(); return store; } @@ -149,7 +150,8 @@ class CassandraVectorStoreIT { @Test void addAndSearchReturnEmbeddings() { this.contextRunner.run(context -> { - CassandraVectorStore.CassandraBuilder builder = storeBuilder(context.getBean(CqlSession.class)) + CassandraVectorStore.CassandraBuilder builder = storeBuilder(context.getBean(CqlSession.class), + context.getBean(EmbeddingModel.class)) .returnEmbeddings(true); try (CassandraVectorStore store = createTestStore(context, builder)) { @@ -395,12 +397,11 @@ class CassandraVectorStoreIT { @Bean public CassandraVectorStore store(CqlSession cqlSession, EmbeddingModel embeddingModel) { - CassandraVectorStore.CassandraBuilder builder = storeBuilder(cqlSession) - .addMetadataColumns(new CassandraVectorStore.SchemaColumn("meta1", DataTypes.TEXT), - new CassandraVectorStore.SchemaColumn("meta2", DataTypes.TEXT), - new CassandraVectorStore.SchemaColumn("country", DataTypes.TEXT), - new CassandraVectorStore.SchemaColumn("year", DataTypes.SMALLINT)) - .embeddingModel(embeddingModel); + CassandraVectorStore.CassandraBuilder builder = storeBuilder(cqlSession, embeddingModel).addMetadataColumns( + new CassandraVectorStore.SchemaColumn("meta1", DataTypes.TEXT), + new CassandraVectorStore.SchemaColumn("meta2", DataTypes.TEXT), + new CassandraVectorStore.SchemaColumn("country", DataTypes.TEXT), + new CassandraVectorStore.SchemaColumn("year", DataTypes.SMALLINT)); CassandraVectorStore.dropKeyspace(builder); return builder.build(); diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreObservationIT.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreObservationIT.java index 6aba243e6..f65e7508f 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreObservationIT.java @@ -172,7 +172,7 @@ public class CassandraVectorStoreObservationIT { public CassandraVectorStore store(CqlSession cqlSession, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - CassandraVectorStore.CassandraBuilder builder = CassandraVectorStore.builder() + CassandraVectorStore.CassandraBuilder builder = CassandraVectorStore.builder(embeddingModel) .session(cqlSession) .session(cqlSession) .keyspace("test_" + CassandraVectorStore.DEFAULT_KEYSPACE_NAME) @@ -180,7 +180,6 @@ public class CassandraVectorStoreObservationIT { new CassandraVectorStore.SchemaColumn("meta2", DataTypes.TEXT), new CassandraVectorStore.SchemaColumn("country", DataTypes.TEXT), new CassandraVectorStore.SchemaColumn("year", DataTypes.SMALLINT)) - .embeddingModel(embeddingModel) .observationRegistry(observationRegistry) .batchingStrategy(new TokenCountBatchingStrategy()); diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java index 82846a2d6..66a4261b3 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java @@ -93,7 +93,7 @@ class WikiVectorStoreExample { List extraColumns = List.of(new SchemaColumn("revision", DataTypes.INT), new SchemaColumn("id", DataTypes.INT)); - return CassandraVectorStore.builder() + return CassandraVectorStore.builder(embeddingModel) .session(cqlSession) .keyspace("wikidata") .table("articles") @@ -118,7 +118,6 @@ class WikiVectorStoreExample { int chunk_no = 0 < parts.length ? Integer.parseInt(parts[1]) : 0; return List.of("simplewiki", "en", title, chunk_no, 0); }) - .embeddingModel(embeddingModel()) .build(); } diff --git a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaApi.java b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaApi.java index c67a969c8..04c12129d 100644 --- a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaApi.java +++ b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaApi.java @@ -33,6 +33,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.client.HttpClientErrorException; @@ -58,6 +59,7 @@ public class ChromaApi { private RestClient restClient; + @Nullable private String keyToken; public ChromaApi(String baseUrl) { @@ -99,7 +101,7 @@ public class ChromaApi { return this; } - public List toEmbeddingResponseList(QueryResponse queryResponse) { + public List toEmbeddingResponseList(@Nullable QueryResponse queryResponse) { List result = new ArrayList<>(); if (queryResponse != null && !CollectionUtils.isEmpty(queryResponse.ids())) { @@ -113,6 +115,7 @@ public class ChromaApi { return result; } + @Nullable public Collection createCollection(CreateCollectionRequest createCollectionRequest) { return this.restClient.post() @@ -138,6 +141,7 @@ public class ChromaApi { .toBodilessEntity(); } + @Nullable public Collection getCollection(String collectionName) { try { @@ -157,6 +161,7 @@ public class ChromaApi { } } + @Nullable public List listCollections() { return this.restClient.get() @@ -167,7 +172,7 @@ public class ChromaApi { .getBody(); } - public void upsertEmbeddings(String collectionId, AddEmbeddingsRequest embedding) { + public void upsertEmbeddings(@Nullable String collectionId, AddEmbeddingsRequest embedding) { this.restClient.post() .uri("/api/v1/collections/{collection_id}/upsert", collectionId) @@ -177,7 +182,7 @@ public class ChromaApi { .toBodilessEntity(); } - public int deleteEmbeddings(String collectionId, DeleteEmbeddingsRequest deleteRequest) { + public int deleteEmbeddings(@Nullable String collectionId, DeleteEmbeddingsRequest deleteRequest) { return this.restClient.post() .uri("/api/v1/collections/{collection_id}/delete", collectionId) .headers(this::httpHeaders) @@ -188,6 +193,7 @@ public class ChromaApi { .value(); } + @Nullable public Long countEmbeddings(String collectionId) { return this.restClient.get() @@ -198,7 +204,8 @@ public class ChromaApi { .getBody(); } - public QueryResponse queryCollection(String collectionId, QueryRequest queryRequest) { + @Nullable + public QueryResponse queryCollection(@Nullable String collectionId, QueryRequest queryRequest) { return this.restClient.post() .uri("/api/v1/collections/{collection_id}/query", collectionId) @@ -212,7 +219,7 @@ public class ChromaApi { // // Chroma Client API (https://docs.trychroma.com/js_reference/Client) // - + @Nullable public GetEmbeddingResponse getEmbeddings(String collectionId, GetEmbeddingsRequest getEmbeddingsRequest) { return this.restClient.post() @@ -332,7 +339,7 @@ public class ChromaApi { @JsonInclude(JsonInclude.Include.NON_NULL) public record DeleteEmbeddingsRequest(// @formatter:off @JsonProperty("ids") List ids, - @JsonProperty("where") Map where) { // @formatter:on + @Nullable @JsonProperty("where") Map where) { // @formatter:on public DeleteEmbeddingsRequest(List ids) { this(ids, null); @@ -353,7 +360,7 @@ public class ChromaApi { @JsonInclude(JsonInclude.Include.NON_NULL) public record GetEmbeddingsRequest(// @formatter:off @JsonProperty("ids") List ids, - @JsonProperty("where") Map where, + @Nullable @JsonProperty("where") Map where, @JsonProperty("limit") Integer limit, @JsonProperty("offset") Integer offset, @JsonProperty("include") List include) { // @formatter:on @@ -404,7 +411,7 @@ public class ChromaApi { public record QueryRequest(// @formatter:off @JsonProperty("query_embeddings") List queryEmbeddings, @JsonProperty("n_results") Integer nResults, - @JsonProperty("where") Map where, + @Nullable @JsonProperty("where") Map where, @JsonProperty("include") List include) { // @formatter:on /** @@ -414,7 +421,7 @@ public class ChromaApi { this(List.of(queryEmbedding), nResults, null, Include.all); } - public QueryRequest(float[] queryEmbedding, Integer nResults, Map where) { + public QueryRequest(float[] queryEmbedding, Integer nResults, @Nullable Map where) { this(List.of(queryEmbedding), nResults, CollectionUtils.isEmpty(where) ? null : where, Include.all); } @@ -471,7 +478,7 @@ public class ChromaApi { @JsonProperty("id") String id, @JsonProperty("embedding") float[] embedding, @JsonProperty("document") String document, - @JsonProperty("metadata") Map metadata, + @Nullable @JsonProperty("metadata") Map metadata, @JsonProperty("distances") Double distances) { // @formatter:on } diff --git a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStore.java b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStore.java index 1773804d1..bed32ec93 100644 --- a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStore.java +++ b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStore.java @@ -100,11 +100,9 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements @Deprecated(since = "1.0.0-M5", forRemoval = true) public ChromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, String collectionName, boolean initializeSchema, ObservationRegistry observationRegistry, - VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { + @Nullable VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().chromaApi(chromaApi) - .embeddingModel(embeddingModel) - .collectionName(collectionName) + this(builder(chromaApi, embeddingModel).collectionName(collectionName) .initializeSchema(initializeSchema) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) @@ -117,8 +115,6 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements protected ChromaVectorStore(ChromaBuilder builder) { super(builder); - Assert.notNull(builder.chromaApi, "ChromaApi must not be null"); - this.chromaApi = builder.chromaApi; this.collectionName = builder.collectionName; this.initializeSchema = builder.initializeSchema; @@ -136,6 +132,10 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements } } + public static ChromaBuilder builder(ChromaApi chromaApi, EmbeddingModel embeddingModel) { + return new ChromaBuilder(chromaApi, embeddingModel); + } + @Override public void afterPropertiesSet() throws Exception { if (!this.initialized) { @@ -150,15 +150,13 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements + " doesn't exist and won't be created as the initializeSchema is set to false."); } } - this.collectionId = collection.id(); + if (collection != null) { + this.collectionId = collection.id(); + } this.initialized = true; } } - public static ChromaBuilder builder() { - return new ChromaBuilder(); - } - @Override public void doAdd(@NonNull List documents) { Assert.notNull(documents, "Documents must not be null"); @@ -177,7 +175,7 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements for (Document document : documents) { ids.add(document.getId()); metadatas.add(document.getMetadata()); - contents.add(document.getContent()); + contents.add(document.getText()); embeddings.add(documentEmbeddings.get(documents.indexOf(document))); } @@ -278,7 +276,7 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements public static class ChromaBuilder extends AbstractVectorStoreBuilder { - private ChromaApi chromaApi; + private final ChromaApi chromaApi; private String collectionName = DEFAULT_COLLECTION_NAME; @@ -290,10 +288,10 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements private boolean initializeImmediately = false; - public ChromaBuilder chromaApi(ChromaApi chromaApi) { + private ChromaBuilder(ChromaApi chromaApi, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(chromaApi, "ChromaApi must not be null"); this.chromaApi = chromaApi; - return this; } /** @@ -358,7 +356,6 @@ public class ChromaVectorStore extends AbstractObservationVectorStore implements * @throws IllegalStateException if the builder is in an invalid state */ public ChromaVectorStore build() { - validate(); return new ChromaVectorStore(this); } diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/BasicAuthChromaWhereIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/BasicAuthChromaWhereIT.java index 8654f7d5b..7b966a1c9 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/BasicAuthChromaWhereIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/BasicAuthChromaWhereIT.java @@ -111,9 +111,7 @@ public class BasicAuthChromaWhereIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return ChromaVectorStore.builder() - .chromaApi(chromaApi) - .embeddingModel(embeddingModel) + return ChromaVectorStore.builder(chromaApi, embeddingModel) .collectionName("TestCollection") .initializeSchema(true) .build(); diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaApiIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaApiIT.java index f0c5b1511..270dcd306 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaApiIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaApiIT.java @@ -207,9 +207,7 @@ public class ChromaApiIT { assertThat(collection).isNotNull(); assertThat(collection.name()).isEqualTo("test-collection"); - ChromaVectorStore store = ChromaVectorStore.builder() - .chromaApi(this.chromaApi) - .embeddingModel(this.embeddingModel) + ChromaVectorStore store = ChromaVectorStore.builder(this.chromaApi, this.embeddingModel) .collectionName("test-collection") .initializeImmediately(true) .build(); @@ -220,8 +218,7 @@ public class ChromaApiIT { @Test void shouldCreateNewCollectionWhenSchemaInitializationEnabled() { - ChromaVectorStore store = new ChromaVectorStore.ChromaBuilder().chromaApi(this.chromaApi) - .embeddingModel(this.embeddingModel) + ChromaVectorStore store = ChromaVectorStore.builder(this.chromaApi, this.embeddingModel) .collectionName("new-collection") .initializeSchema(true) .initializeImmediately(true) @@ -237,8 +234,7 @@ public class ChromaApiIT { @Test void shouldFailWhenCollectionDoesNotExist() { - assertThatThrownBy(() -> new ChromaVectorStore.ChromaBuilder().chromaApi(this.chromaApi) - .embeddingModel(this.embeddingModel) + assertThatThrownBy(() -> ChromaVectorStore.builder(this.chromaApi, this.embeddingModel) .collectionName("non-existent") .initializeSchema(false) .initializeImmediately(true) diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreIT.java index c48c57a77..4a396a520 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreIT.java @@ -252,9 +252,7 @@ public class ChromaVectorStoreIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return ChromaVectorStore.builder() - .chromaApi(chromaApi) - .embeddingModel(embeddingModel) + return ChromaVectorStore.builder(chromaApi, embeddingModel) .collectionName("TestCollection") .initializeSchema(true) .build(); diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreObservationIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreObservationIT.java index 22157fee4..a7ebe1913 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/ChromaVectorStoreObservationIT.java @@ -176,9 +176,7 @@ public class ChromaVectorStoreObservationIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, ObservationRegistry observationRegistry) { - return ChromaVectorStore.builder() - .chromaApi(chromaApi) - .embeddingModel(embeddingModel) + return ChromaVectorStore.builder(chromaApi, embeddingModel) .collectionName("TestCollection") .initializeSchema(true) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/TokenSecuredChromaWhereIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/TokenSecuredChromaWhereIT.java index 88b5f56b8..0b0414e00 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/TokenSecuredChromaWhereIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/chroma/vectorstore/TokenSecuredChromaWhereIT.java @@ -144,9 +144,7 @@ public class TokenSecuredChromaWhereIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return ChromaVectorStore.builder() - .chromaApi(chromaApi) - .embeddingModel(embeddingModel) + return ChromaVectorStore.builder(chromaApi, embeddingModel) .collectionName("TestCollection") .initializeSchema(true) .build(); diff --git a/vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStore.java b/vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStore.java index 208588bed..df56d2da9 100644 --- a/vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStore.java +++ b/vector-stores/spring-ai-coherence-store/src/main/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStore.java @@ -147,7 +147,7 @@ public class CoherenceVectorStore extends AbstractObservationVectorStore impleme */ @Deprecated(since = "1.0.0-M5", forRemoval = true) public CoherenceVectorStore(EmbeddingModel embeddingModel, Session session) { - this(builder().embeddingModel(embeddingModel).session(session)); + this(builder(session, embeddingModel)); } /** @@ -172,8 +172,8 @@ public class CoherenceVectorStore extends AbstractObservationVectorStore impleme * Creates a new builder for configuring and creating CoherenceVectorStore instances. * @return a new builder instance */ - public static CoherenceBuilder builder() { - return new CoherenceBuilder(); + public static CoherenceBuilder builder(Session session, EmbeddingModel embeddingModel) { + return new CoherenceBuilder(session, embeddingModel); } /** @@ -332,7 +332,7 @@ public class CoherenceVectorStore extends AbstractObservationVectorStore impleme */ public static class CoherenceBuilder extends AbstractVectorStoreBuilder { - private Session session; + private final Session session; private String mapName = DEFAULT_MAP_NAME; @@ -348,10 +348,10 @@ public class CoherenceVectorStore extends AbstractObservationVectorStore impleme * @return the builder instance * @throws IllegalArgumentException if session is null */ - public CoherenceBuilder session(Session session) { + public CoherenceBuilder(Session session, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(session, "Session must not be null"); this.session = session; - return this; } /** @@ -402,7 +402,6 @@ public class CoherenceVectorStore extends AbstractObservationVectorStore impleme @Override public CoherenceVectorStore build() { - validate(); return new CoherenceVectorStore(this); } diff --git a/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStoreIT.java b/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStoreIT.java index 6e8734b8c..996344ed7 100644 --- a/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStoreIT.java +++ b/vector-stores/spring-ai-coherence-store/src/test/java/org/springframework/ai/vectorstore/coherence/CoherenceVectorStoreIT.java @@ -311,9 +311,7 @@ public class CoherenceVectorStoreIT { @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel, Session session) { - return CoherenceVectorStore.builder() - .embeddingModel(embeddingModel) - .session(session) + return CoherenceVectorStore.builder(session, embeddingModel) .distanceType(this.distanceType) .indexType(this.indexType) .forcedNormalization(this.distanceType == CoherenceVectorStore.DistanceType.COSINE diff --git a/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java b/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java index 52f84ad11..937dc99db 100644 --- a/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java +++ b/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java @@ -187,9 +187,7 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp EmbeddingModel embeddingModel, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().restClient(restClient) - .options(options) - .embeddingModel(embeddingModel) + this(builder(restClient, embeddingModel).options(options) .initializeSchema(initializeSchema) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) @@ -389,13 +387,13 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp * Creates a new builder instance for ElasticsearchVectorStore. * @return a new ElasticsearchBuilder instance */ - public static ElasticsearchBuilder builder() { - return new ElasticsearchBuilder(); + public static ElasticsearchBuilder builder(RestClient restClient, EmbeddingModel embeddingModel) { + return new ElasticsearchBuilder(restClient, embeddingModel); } public static class ElasticsearchBuilder extends AbstractVectorStoreBuilder { - private RestClient restClient; + private final RestClient restClient; private ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions(); @@ -411,10 +409,10 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp * @return the builder instance * @throws IllegalArgumentException if restClient is null */ - public ElasticsearchBuilder restClient(RestClient restClient) { + public ElasticsearchBuilder(RestClient restClient, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(restClient, "RestClient must not be null"); this.restClient = restClient; - return this; } /** @@ -470,7 +468,6 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp */ @Override public ElasticsearchVectorStore build() { - validate(); return new ElasticsearchVectorStore(this); } diff --git a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreIT.java b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreIT.java index 4f1de5fac..54e56bb2b 100644 --- a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreIT.java +++ b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreIT.java @@ -377,11 +377,7 @@ class ElasticsearchVectorStoreIT { @Bean("vectorStore_cosine") public ElasticsearchVectorStore vectorStoreDefault(EmbeddingModel embeddingModel, RestClient restClient) { - return ElasticsearchVectorStore.builder() - .restClient(restClient) - .embeddingModel(embeddingModel) - .initializeSchema(true) - .build(); + return ElasticsearchVectorStore.builder(restClient, embeddingModel).initializeSchema(true).build(); } @Bean("vectorStore_l2_norm") @@ -389,9 +385,7 @@ class ElasticsearchVectorStoreIT { ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions(); options.setIndexName("index_l2"); options.setSimilarity(SimilarityFunction.l2_norm); - return ElasticsearchVectorStore.builder() - .restClient(restClient) - .embeddingModel(embeddingModel) + return ElasticsearchVectorStore.builder(restClient, embeddingModel) .initializeSchema(true) .options(options) .build(); @@ -402,9 +396,7 @@ class ElasticsearchVectorStoreIT { ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions(); options.setIndexName("index_dot_product"); options.setSimilarity(SimilarityFunction.dot_product); - return ElasticsearchVectorStore.builder() - .restClient(restClient) - .embeddingModel(embeddingModel) + return ElasticsearchVectorStore.builder(restClient, embeddingModel) .initializeSchema(true) .options(options) .build(); diff --git a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreObservationIT.java b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreObservationIT.java index ae19e2ff0..77c451492 100644 --- a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreObservationIT.java @@ -208,9 +208,7 @@ public class ElasticsearchVectorStoreObservationIT { @Bean public ElasticsearchVectorStore vectorStoreDefault(EmbeddingModel embeddingModel, RestClient restClient, ObservationRegistry observationRegistry) { - return ElasticsearchVectorStore.builder() - .restClient(restClient) - .embeddingModel(embeddingModel) + return ElasticsearchVectorStore.builder(restClient, embeddingModel) .initializeSchema(true) .options(new ElasticsearchVectorStoreOptions()) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java b/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java index dbd1c9fc6..ac73a58a3 100644 --- a/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java +++ b/vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java @@ -149,8 +149,7 @@ public class GemFireVectorStore extends AbstractObservationVectorStore implement ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().embeddingModel(embeddingModel) - .host(config.host) + this(builder(embeddingModel).host(config.host) .port(config.port) .sslEnabled(config.sslEnabled) .indexName(config.indexName) @@ -189,8 +188,8 @@ public class GemFireVectorStore extends AbstractObservationVectorStore implement this.objectMapper = JsonMapper.builder().addModules(JacksonUtils.instantiateAvailableModules()).build(); } - public static GemFireBuilder builder() { - return new GemFireBuilder(); + public static GemFireBuilder builder(EmbeddingModel embeddingModel) { + return new GemFireBuilder(embeddingModel); } public String getIndexName() { @@ -846,6 +845,10 @@ public class GemFireVectorStore extends AbstractObservationVectorStore implement private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); + private GemFireBuilder(EmbeddingModel embeddingModel) { + super(embeddingModel); + } + /** * Sets the host for the GemFire connection. * @param host the host to connect to @@ -978,7 +981,6 @@ public class GemFireVectorStore extends AbstractObservationVectorStore implement @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/gemfire/GemFireVectorStoreIT.java b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java index 8fe5bb069..a8a1b09e3 100644 --- a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java +++ b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreIT.java @@ -218,11 +218,10 @@ public class GemFireVectorStoreIT { @Bean public GemFireVectorStore vectorStore(EmbeddingModel embeddingModel) { - return GemFireVectorStore.builder() + return GemFireVectorStore.builder(embeddingModel) .host("localhost") .port(HTTP_SERVICE_PORT) .indexName(INDEX_NAME) - .embeddingModel(embeddingModel) .initializeSchema(true) .build(); } diff --git a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java index b3f17e092..4fcf24763 100644 --- a/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-gemfire-store/src/test/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStoreObservationIT.java @@ -200,11 +200,10 @@ public class GemFireVectorStoreObservationIT { @Bean public GemFireVectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return GemFireVectorStore.builder() + return GemFireVectorStore.builder(embeddingModel) .host("localhost") .port(HTTP_SERVICE_PORT) .indexName(TEST_INDEX_NAME) - .embeddingModel(embeddingModel) .initializeSchema(true) .observationRegistry(observationRegistry) .customObservationConvention(null) diff --git a/vector-stores/spring-ai-hanadb-store/src/main/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStore.java b/vector-stores/spring-ai-hanadb-store/src/main/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStore.java index 51d8bb083..685ffb35f 100644 --- a/vector-stores/spring-ai-hanadb-store/src/main/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStore.java +++ b/vector-stores/spring-ai-hanadb-store/src/main/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStore.java @@ -115,9 +115,7 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore { EmbeddingModel embeddingModel, HanaCloudVectorStoreConfig config, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention) { - this(builder().repository(repository) - .embeddingModel(embeddingModel) - .tableName(config.getTableName()) + this(builder(repository, embeddingModel).tableName(config.getTableName()) .topK(config.getTopK()) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention)); @@ -143,8 +141,9 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore { * Creates a new builder for configuring and creating HanaCloudVectorStore instances. * @return a new builder instance */ - public static HanaCloudBuilder builder() { - return new HanaCloudBuilder(); + public static HanaCloudBuilder builder(HanaVectorRepository repository, + EmbeddingModel embeddingModel) { + return new HanaCloudBuilder(repository, embeddingModel); } @Override @@ -233,7 +232,7 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore { */ public static class HanaCloudBuilder extends AbstractVectorStoreBuilder { - private HanaVectorRepository repository; + private final HanaVectorRepository repository; private String tableName; @@ -245,10 +244,11 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore { * @return the builder instance * @throws IllegalArgumentException if repository is null */ - public HanaCloudBuilder repository(HanaVectorRepository repository) { + public HanaCloudBuilder(HanaVectorRepository repository, + EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(repository, "Repository must not be null"); this.repository = repository; - return this; } /** @@ -273,7 +273,6 @@ public class HanaCloudVectorStore extends AbstractObservationVectorStore { @Override public HanaCloudVectorStore build() { - validate(); return new HanaCloudVectorStore(this); } diff --git a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStoreIT.java b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStoreIT.java index 7015c31b6..6a4131f34 100644 --- a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStoreIT.java +++ b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaCloudVectorStoreIT.java @@ -91,9 +91,7 @@ public class HanaCloudVectorStoreIT { public VectorStore hanaCloudVectorStore(CricketWorldCupRepository cricketWorldCupRepository, EmbeddingModel embeddingModel) { - return HanaCloudVectorStore.builder() - .repository(cricketWorldCupRepository) - .embeddingModel(embeddingModel) + return HanaCloudVectorStore.builder(cricketWorldCupRepository, embeddingModel) .tableName("CRICKET_WORLD_CUP") .topK(1) .build(); diff --git a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaVectorStoreObservationIT.java b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaVectorStoreObservationIT.java index d537aec42..a37d5af13 100644 --- a/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-hanadb-store/src/test/java/org/springframework/ai/vectorstore/hanadb/HanaVectorStoreObservationIT.java @@ -167,9 +167,7 @@ public class HanaVectorStoreObservationIT { public VectorStore hanaCloudVectorStore(CricketWorldCupRepository cricketWorldCupRepository, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return HanaCloudVectorStore.builder() - .repository(cricketWorldCupRepository) - .embeddingModel(embeddingModel) + return HanaCloudVectorStore.builder(cricketWorldCupRepository, embeddingModel) .tableName(TEST_TABLE_NAME) .topK(1) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-mariadb-store/src/main/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStore.java b/vector-stores/spring-ai-mariadb-store/src/main/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStore.java index e801c3ad5..10e3c5b3d 100644 --- a/vector-stores/spring-ai-mariadb-store/src/main/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStore.java +++ b/vector-stores/spring-ai-mariadb-store/src/main/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStore.java @@ -256,8 +256,7 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement int maxDocumentBatchSize, String contentFieldName, String embeddingFieldName, String idFieldName, String metadataFieldName) { - this(builder(jdbcTemplate).vectorTableName(vectorTableName) - .embeddingModel(embeddingModel) + this(builder(jdbcTemplate, embeddingModel).vectorTableName(vectorTableName) .dimensions(dimensions) .distanceType(distanceType) .removeExistingVectorStoreTable(removeExistingVectorStoreTable) @@ -319,8 +318,8 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement * MariaDBVectorStore. * @return a new MariaDBBuilder instance */ - public static MariaDBBuilder builder(JdbcTemplate jdbcTemplate) { - return new MariaDBBuilder(jdbcTemplate); + public static MariaDBBuilder builder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + return new MariaDBBuilder(jdbcTemplate, embeddingModel); } public MariaDBDistanceType getDistanceType() { @@ -595,7 +594,8 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement * @param jdbcTemplate the JDBC template for database operations * @throws IllegalArgumentException if jdbcTemplate is null */ - MariaDBBuilder(JdbcTemplate jdbcTemplate) { + private MariaDBBuilder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null"); this.jdbcTemplate = jdbcTemplate; } @@ -758,7 +758,6 @@ public class MariaDBVectorStore extends AbstractObservationVectorStore implement */ @Override public MariaDBVectorStore build() { - validate(); return new MariaDBVectorStore(this); } diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBEmbeddingDimensionsTests.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBEmbeddingDimensionsTests.java index c57f8e676..2e7ec9abe 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBEmbeddingDimensionsTests.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBEmbeddingDimensionsTests.java @@ -47,8 +47,7 @@ public class MariaDBEmbeddingDimensionsTests { final int explicitDimensions = 696; - MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) + MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel) .dimensions(explicitDimensions) .build(); var dim = mariaDBVectorStore.embeddingDimensions(); @@ -61,8 +60,7 @@ public class MariaDBEmbeddingDimensionsTests { public void embeddingModelDimensions() { when(this.embeddingModel.dimensions()).thenReturn(969); - MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) + MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel) .build(); var dim = mariaDBVectorStore.embeddingDimensions(); @@ -76,8 +74,7 @@ public class MariaDBEmbeddingDimensionsTests { when(this.embeddingModel.dimensions()).thenThrow(new RuntimeException()); - MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) + MariaDBVectorStore mariaDBVectorStore = MariaDBVectorStore.builder(this.jdbcTemplate, this.embeddingModel) .build(); var dim = mariaDBVectorStore.embeddingDimensions(); diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreCustomNamesIT.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreCustomNamesIT.java index 3f60e501e..7c24948b2 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreCustomNamesIT.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreCustomNamesIT.java @@ -217,8 +217,7 @@ public class MariaDBStoreCustomNamesIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { - return MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + return MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName(this.schemaName) .vectorTableName(this.vectorTableName) .schemaValidation(this.schemaValidation) diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreIT.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreIT.java index 54ab39ab9..8a1431140 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreIT.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreIT.java @@ -347,8 +347,7 @@ public class MariaDBStoreIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { - return MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + return MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .dimensions(MariaDBVectorStore.INVALID_EMBEDDING_DIMENSION) .distanceType(this.distanceType) .removeExistingVectorStoreTable(true) diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreObservationIT.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreObservationIT.java index 2e183bc52..caca46eea 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreObservationIT.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreObservationIT.java @@ -177,8 +177,7 @@ public class MariaDBStoreObservationIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + return MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName(schemaName) .distanceType(MariaDBVectorStore.MariaDBDistanceType.COSINE) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreTests.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreTests.java index defe99548..be36e0792 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreTests.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBStoreTests.java @@ -70,8 +70,7 @@ public class MariaDBStoreTests { // Given var jdbcTemplate = mock(JdbcTemplate.class); var embeddingModel = mock(EmbeddingModel.class); - var mariadbVectorStore = MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + var mariadbVectorStore = MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .maxDocumentBatchSize(1000) .build(); diff --git a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStoreBuilderTests.java b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStoreBuilderTests.java index 4e0e1eeb7..ed28a7f25 100644 --- a/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStoreBuilderTests.java +++ b/vector-stores/spring-ai-mariadb-store/src/test/java/org/springframework/ai/vectorstore/mariadb/MariaDBVectorStoreBuilderTests.java @@ -38,22 +38,21 @@ class MariaDBVectorStoreBuilderTests { @Test void shouldFailOnMissingEmbeddingModel() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate).build()) + assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, null).build()) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("EmbeddingModel must be configured"); } @Test void shouldFailOnMissingJdbcTemplate() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(null).build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> MariaDBVectorStore.builder(null, embeddingModel).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("JdbcTemplate must not be null"); } @Test void shouldUseDefaultValues() { - MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .build(); + MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).build(); assertThat(vectorStore).hasFieldOrPropertyWithValue("vectorTableName", "vector_store") .hasFieldOrPropertyWithValue("schemaName", null) @@ -71,8 +70,7 @@ class MariaDBVectorStoreBuilderTests { @Test void shouldConfigureCustomValues() { - MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) + MariaDBVectorStore vectorStore = MariaDBVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName("custom_schema") .vectorTableName("custom_vectors") .schemaValidation(true) @@ -103,60 +101,49 @@ class MariaDBVectorStoreBuilderTests { @Test void shouldValidateFieldNames() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .contentFieldName("") - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).contentFieldName("").build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("ContentFieldName must not be empty"); - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .embeddingFieldName("") - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy( + () -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).embeddingFieldName("").build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("EmbeddingFieldName must not be empty"); - assertThatThrownBy( - () -> MariaDBVectorStore.builder(jdbcTemplate).embeddingModel(embeddingModel).idFieldName("").build()) + assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).idFieldName("").build()) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("IdFieldName must not be empty"); - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .metadataFieldName("") - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).metadataFieldName("").build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("MetadataFieldName must not be empty"); } @Test void shouldValidateMaxDocumentBatchSize() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .maxDocumentBatchSize(0) - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy( + () -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).maxDocumentBatchSize(0).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("MaxDocumentBatchSize must be positive"); - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .maxDocumentBatchSize(-1) - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy( + () -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).maxDocumentBatchSize(-1).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("MaxDocumentBatchSize must be positive"); } @Test void shouldValidateDistanceType() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .distanceType(null) - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).distanceType(null).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("DistanceType must not be null"); } @Test void shouldValidateBatchingStrategy() { - assertThatThrownBy(() -> MariaDBVectorStore.builder(jdbcTemplate) - .embeddingModel(embeddingModel) - .batchingStrategy(null) - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy( + () -> MariaDBVectorStore.builder(jdbcTemplate, embeddingModel).batchingStrategy(null).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("BatchingStrategy must not be null"); } diff --git a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStore.java b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStore.java index 7976b31bb..dd1bf72a6 100644 --- a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStore.java +++ b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStore.java @@ -230,9 +230,7 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements MilvusVectorStoreConfig config, boolean initializeSchema, BatchingStrategy batchingStrategy, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention) { - this(builder().milvusClient(milvusClient) - .embeddingModel(embeddingModel) - .observationRegistry(observationRegistry) + this(builder(milvusClient, embeddingModel).observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) .initializeSchema(initializeSchema) .batchingStrategy(batchingStrategy)); @@ -268,8 +266,8 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements * recommended way to instantiate a MilvusBuilder. * @return a new MilvusBuilder instance */ - public static MilvusBuilder builder() { - return new MilvusBuilder(); + public static MilvusBuilder builder(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) { + return new MilvusBuilder(milvusClient, embeddingModel); } @Override @@ -579,6 +577,8 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements public static final class MilvusBuilder extends AbstractVectorStoreBuilder { + private final MilvusServiceClient milvusClient; + private String databaseName = DEFAULT_DATABASE_NAME; private String collectionName = DEFAULT_COLLECTION_NAME; @@ -603,18 +603,16 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements private boolean initializeSchema = false; - private MilvusServiceClient milvusClient; - private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); /** * @param milvusClient the Milvus service client to use for database operations * @throws IllegalArgumentException if milvusClient is null */ - public MilvusBuilder milvusClient(MilvusServiceClient milvusClient) { + private MilvusBuilder(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(milvusClient, "milvusClient must not be null"); this.milvusClient = milvusClient; - return this; } /** @@ -773,7 +771,6 @@ public class MilvusVectorStore extends AbstractObservationVectorStore implements * @throws IllegalStateException if the builder configuration is invalid */ public MilvusVectorStore build() { - validate(); return new MilvusVectorStore(this); } diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusEmbeddingDimensionsTests.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusEmbeddingDimensionsTests.java index 32cb665e9..86315749b 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusEmbeddingDimensionsTests.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusEmbeddingDimensionsTests.java @@ -53,9 +53,7 @@ public class MilvusEmbeddingDimensionsTests { final int explicitDimensions = 696; - MilvusVectorStore build = MilvusVectorStore.builder() - .milvusClient(this.milvusClient) - .embeddingModel(this.embeddingModel) + MilvusVectorStore build = MilvusVectorStore.builder(this.milvusClient, this.embeddingModel) .initializeSchema(true) .batchingStrategy(new TokenCountBatchingStrategy()) .embeddingDimension(explicitDimensions) @@ -70,9 +68,7 @@ public class MilvusEmbeddingDimensionsTests { public void embeddingModelDimensions() { given(this.embeddingModel.dimensions()).willReturn(969); - MilvusVectorStore build = MilvusVectorStore.builder() - .milvusClient(this.milvusClient) - .embeddingModel(this.embeddingModel) + MilvusVectorStore build = MilvusVectorStore.builder(this.milvusClient, this.embeddingModel) .initializeSchema(true) .batchingStrategy(new TokenCountBatchingStrategy()) .build(); @@ -88,9 +84,7 @@ public class MilvusEmbeddingDimensionsTests { given(this.embeddingModel.dimensions()).willThrow(new RuntimeException()); - MilvusVectorStore build = MilvusVectorStore.builder() - .milvusClient(this.milvusClient) - .embeddingModel(this.embeddingModel) + MilvusVectorStore build = MilvusVectorStore.builder(this.milvusClient, this.embeddingModel) .initializeSchema(true) .batchingStrategy(new TokenCountBatchingStrategy()) .build(); @@ -104,8 +98,8 @@ public class MilvusEmbeddingDimensionsTests { @ValueSource(ints = { 0, 32769 }) public void invalidDimensionsThrowException(final int explicitDimensions) { // when - ThrowableAssert.ThrowingCallable actual = () -> MilvusVectorStore.builder() - .milvusClient(this.milvusClient) + ThrowableAssert.ThrowingCallable actual = () -> MilvusVectorStore + .builder(this.milvusClient, this.embeddingModel) .embeddingDimension(explicitDimensions) .build(); diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreCustomFieldNamesIT.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreCustomFieldNamesIT.java index 0934fcc3c..cc6eddbe1 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreCustomFieldNamesIT.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreCustomFieldNamesIT.java @@ -230,9 +230,7 @@ class MilvusVectorStoreCustomFieldNamesIT { @Bean VectorStore vectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) { - return MilvusVectorStore.builder() - .milvusClient(milvusClient) - .embeddingModel(embeddingModel) + return MilvusVectorStore.builder(milvusClient, embeddingModel) .collectionName("test_vector_store_custom_fields") .databaseName("default") .indexType(IndexType.IVF_FLAT) diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreIT.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreIT.java index b3f08670a..18cd23f57 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreIT.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreIT.java @@ -269,9 +269,7 @@ public class MilvusVectorStoreIT { @Bean public VectorStore vectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) { - return MilvusVectorStore.builder() - .milvusClient(milvusClient) - .embeddingModel(embeddingModel) + return MilvusVectorStore.builder(milvusClient, embeddingModel) .collectionName("test_vector_store") .databaseName("default") .indexType(IndexType.IVF_FLAT) diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreObservationIT.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreObservationIT.java index 1df3ac1ae..89e4df509 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/milvus/vectorstore/MilvusVectorStoreObservationIT.java @@ -170,9 +170,7 @@ public class MilvusVectorStoreObservationIT { @Bean public VectorStore vectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return MilvusVectorStore.builder() - .milvusClient(milvusClient) - .embeddingModel(embeddingModel) + return MilvusVectorStore.builder(milvusClient, embeddingModel) .observationRegistry(observationRegistry) .collectionName(TEST_COLLECTION_NAME) .databaseName("default") diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStore.java b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStore.java index 067a7292d..65ce0957b 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStore.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStore.java @@ -187,9 +187,7 @@ public class MongoDBAtlasVectorStore extends AbstractObservationVectorStore impl MongoDBVectorStoreConfig config, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().mongoTemplate(mongoTemplate) - .embeddingModel(embeddingModel) - .collectionName(config.collectionName) + this(builder(mongoTemplate, embeddingModel).collectionName(config.collectionName) .vectorIndexName(config.vectorIndexName) .pathName(config.pathName) .numCandidates(config.numCandidates) @@ -354,13 +352,13 @@ public class MongoDBAtlasVectorStore extends AbstractObservationVectorStore impl * Creates a new builder instance for MongoDBAtlasVectorStore. * @return a new MongoDBBuilder instance */ - public static MongoDBBuilder builder() { - return new MongoDBBuilder(); + public static MongoDBBuilder builder(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { + return new MongoDBBuilder(mongoTemplate, embeddingModel); } public static class MongoDBBuilder extends AbstractVectorStoreBuilder { - private MongoTemplate mongoTemplate; + private final MongoTemplate mongoTemplate; private String collectionName = DEFAULT_VECTOR_COLLECTION_NAME; @@ -381,10 +379,10 @@ public class MongoDBAtlasVectorStore extends AbstractObservationVectorStore impl /** * @throws IllegalArgumentException if mongoTemplate is null */ - public MongoDBBuilder mongoTemplate(MongoTemplate mongoTemplate) { + public MongoDBBuilder(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(mongoTemplate, "MongoTemplate must not be null"); this.mongoTemplate = mongoTemplate; - return this; } /** @@ -489,7 +487,6 @@ public class MongoDBAtlasVectorStore extends AbstractObservationVectorStore impl */ @Override public MongoDBAtlasVectorStore build() { - validate(); return new MongoDBAtlasVectorStore(this); } diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStoreIT.java b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStoreIT.java index 9152a2752..9c332e66a 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStoreIT.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasVectorStoreIT.java @@ -259,9 +259,7 @@ class MongoDBAtlasVectorStoreIT { @Bean public VectorStore vectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { - return MongoDBAtlasVectorStore.builder() - .mongoTemplate(mongoTemplate) - .embeddingModel(embeddingModel) + return MongoDBAtlasVectorStore.builder(mongoTemplate, embeddingModel) .metadataFieldsToFilter(List.of("country", "year")) .initializeSchema(true) .build(); diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDbVectorStoreObservationIT.java b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDbVectorStoreObservationIT.java index 7a83cbf90..38f1ad88e 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDbVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDbVectorStoreObservationIT.java @@ -187,9 +187,7 @@ public class MongoDbVectorStoreObservationIT { @Bean public VectorStore vectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return MongoDBAtlasVectorStore.builder() - .mongoTemplate(mongoTemplate) - .embeddingModel(embeddingModel) + return MongoDBAtlasVectorStore.builder(mongoTemplate, embeddingModel) .metadataFieldsToFilter(List.of("country", "year")) .initializeSchema(true) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java b/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java index b91278405..75108e37c 100644 --- a/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java +++ b/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java @@ -196,9 +196,7 @@ public class Neo4jVectorStore extends AbstractObservationVectorStore implements boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().driver(driver) - .embeddingModel(embeddingModel) - .sessionConfig(config.sessionConfig) + this(builder(driver, embeddingModel).sessionConfig(config.sessionConfig) .embeddingDimension(config.embeddingDimension) .distanceType(config.distanceType) .embeddingProperty(config.embeddingProperty) @@ -400,13 +398,13 @@ public class Neo4jVectorStore extends AbstractObservationVectorStore implements } - public static Neo4jBuilder builder() { - return new Neo4jBuilder(); + public static Neo4jBuilder builder(Driver driver, EmbeddingModel embeddingModel) { + return new Neo4jBuilder(driver, embeddingModel); } public static class Neo4jBuilder extends AbstractVectorStoreBuilder { - private Driver driver; + private final Driver driver; private SessionConfig sessionConfig = SessionConfig.defaultConfig(); @@ -428,10 +426,10 @@ public class Neo4jVectorStore extends AbstractObservationVectorStore implements private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); - public Neo4jBuilder driver(Driver driver) { + public Neo4jBuilder(Driver driver, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(driver, "Neo4j driver must not be null"); this.driver = driver; - return this; } /** @@ -565,7 +563,6 @@ public class Neo4jVectorStore extends AbstractObservationVectorStore implements @Override public Neo4jVectorStore build() { - validate(); return new Neo4jVectorStore(this); } diff --git a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreIT.java b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreIT.java index 401b8a559..b0d145c2d 100644 --- a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreIT.java +++ b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreIT.java @@ -291,11 +291,7 @@ class Neo4jVectorStoreIT { @Bean public VectorStore vectorStore(Driver driver, EmbeddingModel embeddingModel) { - return Neo4jVectorStore.builder() - .driver(driver) - .embeddingModel(embeddingModel) - .initializeSchema(true) - .build(); + return Neo4jVectorStore.builder(driver, embeddingModel).initializeSchema(true).build(); } @Bean diff --git a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreObservationIT.java b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreObservationIT.java index 0239f5454..4e48a0ba7 100644 --- a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStoreObservationIT.java @@ -178,9 +178,7 @@ public class Neo4jVectorStoreObservationIT { public VectorStore vectorStore(Driver driver, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return Neo4jVectorStore.builder() - .driver(driver) - .embeddingModel(embeddingModel) + return Neo4jVectorStore.builder(driver, embeddingModel) .initializeSchema(true) .observationRegistry(observationRegistry) .customObservationConvention(null) diff --git a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java index 7a9bd4b41..13de4f672 100644 --- a/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java +++ b/vector-stores/spring-ai-opensearch-store/src/main/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStore.java @@ -238,9 +238,7 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem String mappingJson, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().openSearchClient(openSearchClient) - .embeddingModel(embeddingModel) - .index(index) + this(builder(openSearchClient, embeddingModel).index(index) .mappingJson(mappingJson) .initializeSchema(initializeSchema) .observationRegistry(observationRegistry) @@ -272,8 +270,8 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem * Creates a new builder instance for configuring an OpenSearchVectorStore. * @return A new OpenSearchBuilder instance */ - public static OpenSearchBuilder builder() { - return new OpenSearchBuilder(); + public static OpenSearchBuilder builder(OpenSearchClient openSearchClient, EmbeddingModel embeddingModel) { + return new OpenSearchBuilder(openSearchClient, embeddingModel); } public OpenSearchVectorStore withSimilarityFunction(String similarityFunction) { @@ -450,7 +448,7 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem */ public static class OpenSearchBuilder extends AbstractVectorStoreBuilder { - private OpenSearchClient openSearchClient; + private final OpenSearchClient openSearchClient; private String index = DEFAULT_INDEX_NAME; @@ -470,22 +468,10 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem * @return The builder instance * @throws IllegalArgumentException if openSearchClient is null */ - public OpenSearchBuilder openSearchClient(OpenSearchClient openSearchClient) { + public OpenSearchBuilder(OpenSearchClient openSearchClient, EmbeddingModel embeddingModel) { + super(embeddingModel); 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; } /** @@ -567,7 +553,6 @@ public class OpenSearchVectorStore extends AbstractObservationVectorStore implem */ @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/opensearch/OpenSearchVectorStoreIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java index e650efee8..ece9987b3 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreIT.java @@ -398,13 +398,10 @@ class OpenSearchVectorStoreIT { @Qualifier("vectorStore") public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { try { - return OpenSearchVectorStore.builder() - .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build())) - .embeddingModel(embeddingModel) - .initializeSchema(true) - .build(); + OpenSearchClient openSearchClient = new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build()); + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel).initializeSchema(true).build(); } catch (URISyntaxException e) { throw new RuntimeException(e); @@ -415,12 +412,11 @@ class OpenSearchVectorStoreIT { @Qualifier("anotherVectorStore") public OpenSearchVectorStore anotherVectorStore(EmbeddingModel embeddingModel) { try { - return OpenSearchVectorStore.builder() + OpenSearchClient openSearchClient = new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build()); + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel) .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(); diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java index cba4321fb..8ae941939 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreObservationIT.java @@ -207,12 +207,11 @@ public class OpenSearchVectorStoreObservationIT { public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { try { - return OpenSearchVectorStore.builder() + OpenSearchClient openSearchClient = new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build()); + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel) .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) diff --git a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java index e6f802951..f34ae5293 100644 --- a/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java +++ b/vector-stores/spring-ai-opensearch-store/src/test/java/org/springframework/ai/vectorstore/opensearch/OpenSearchVectorStoreWithOllamaIT.java @@ -169,13 +169,10 @@ class OpenSearchVectorStoreWithOllamaIT { @Qualifier("vectorStore") public OpenSearchVectorStore vectorStore(EmbeddingModel embeddingModel) { try { - return OpenSearchVectorStore.builder() - .openSearchClient(new OpenSearchClient(ApacheHttpClient5TransportBuilder - .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) - .build())) - .embeddingModel(embeddingModel) - .initializeSchema(true) - .build(); + OpenSearchClient openSearchClient = new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build()); + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel).initializeSchema(true).build(); } catch (URISyntaxException e) { throw new RuntimeException(e); @@ -186,12 +183,11 @@ class OpenSearchVectorStoreWithOllamaIT { @Qualifier("anotherVectorStore") public OpenSearchVectorStore anotherVectorStore(EmbeddingModel embeddingModel) { try { - return OpenSearchVectorStore.builder() + OpenSearchClient openSearchClient = new OpenSearchClient(ApacheHttpClient5TransportBuilder + .builder(HttpHost.create(opensearchContainer.getHttpHostAddress())) + .build()); + return OpenSearchVectorStore.builder(openSearchClient, embeddingModel) .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(); diff --git a/vector-stores/spring-ai-oracle-store/src/main/java/org/springframework/ai/vectorstore/oracle/OracleVectorStore.java b/vector-stores/spring-ai-oracle-store/src/main/java/org/springframework/ai/vectorstore/oracle/OracleVectorStore.java index c2a5a0e38..2f91346c7 100644 --- a/vector-stores/spring-ai-oracle-store/src/main/java/org/springframework/ai/vectorstore/oracle/OracleVectorStore.java +++ b/vector-stores/spring-ai-oracle-store/src/main/java/org/springframework/ai/vectorstore/oracle/OracleVectorStore.java @@ -220,9 +220,7 @@ public class OracleVectorStore extends AbstractObservationVectorStore implements boolean forcedNormalization, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) - .tableName(tableName) + this(builder(jdbcTemplate, embeddingModel).tableName(tableName) .indexType(indexType) .distanceType(distanceType) .dimensions(dimensions) @@ -257,8 +255,8 @@ public class OracleVectorStore extends AbstractObservationVectorStore implements this.batchingStrategy = builder.batchingStrategy; } - public static OracleBuilder builder() { - return new OracleBuilder(); + public static OracleBuilder builder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + return new OracleBuilder(jdbcTemplate, embeddingModel); } @Override @@ -773,10 +771,10 @@ public class OracleVectorStore extends AbstractObservationVectorStore implements * @return the builder instance * @throws IllegalArgumentException if jdbcTemplate is null */ - public OracleBuilder jdbcTemplate(JdbcTemplate jdbcTemplate) { + public OracleBuilder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null"); this.jdbcTemplate = jdbcTemplate; - return this; } /** @@ -890,7 +888,6 @@ public class OracleVectorStore extends AbstractObservationVectorStore implements @Override public OracleVectorStore build() { - validate(); return new OracleVectorStore(this); } diff --git a/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreIT.java b/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreIT.java index 3130ff16b..48bedd937 100644 --- a/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreIT.java +++ b/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreIT.java @@ -310,9 +310,7 @@ public class OracleVectorStoreIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { - return OracleVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return OracleVectorStore.builder(jdbcTemplate, embeddingModel) .tableName(OracleVectorStore.DEFAULT_TABLE_NAME) .indexType(OracleVectorStore.OracleVectorStoreIndexType.IVF) .distanceType(distanceType) diff --git a/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreObservationIT.java b/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreObservationIT.java index cd566647a..ab5a92af7 100644 --- a/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-oracle-store/src/test/java/org/springframework/ai/vectorstore/oracle/OracleVectorStoreObservationIT.java @@ -187,9 +187,7 @@ public class OracleVectorStoreObservationIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return OracleVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return OracleVectorStore.builder(jdbcTemplate, embeddingModel) .tableName(OracleVectorStore.DEFAULT_TABLE_NAME) .indexType(OracleVectorStore.OracleVectorStoreIndexType.IVF) .distanceType(OracleVectorStoreDistanceType.COSINE) diff --git a/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorStore.java b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorStore.java index cdd055316..8c29d1a63 100644 --- a/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorStore.java +++ b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorStore.java @@ -239,8 +239,7 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini int dimensions, PgDistanceType distanceType, boolean removeExistingVectorStoreTable, PgIndexType createIndexMethod, boolean initializeSchema) { - this(builder().jdbcTemplate(jdbcTemplate) - .schemaName(DEFAULT_SCHEMA_NAME) + this(builder(jdbcTemplate, embeddingModel).schemaName(DEFAULT_SCHEMA_NAME) .vectorTableName(vectorTableName) .vectorTableValidationsEnabled(DEFAULT_SCHEMA_VALIDATION) .dimensions(dimensions) @@ -286,8 +285,8 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini return this.distanceType; } - public static PgVectorStoreBuilder builder() { - return new PgVectorStoreBuilder(); + public static PgVectorStoreBuilder builder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + return new PgVectorStoreBuilder(jdbcTemplate, embeddingModel); } @Override @@ -647,10 +646,10 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini private int maxDocumentBatchSize = MAX_DOCUMENT_BATCH_SIZE; - public PgVectorStoreBuilder jdbcTemplate(JdbcTemplate jdbcTemplate) { + private PgVectorStoreBuilder(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null"); this.jdbcTemplate = jdbcTemplate; - return this; } public PgVectorStoreBuilder schemaName(String schemaName) { @@ -704,7 +703,6 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini } public PgVectorStore build() { - validate(); return new PgVectorStore(this); } @@ -811,9 +809,7 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini } public PgVectorStore build() { - return PgVectorStore.builder() - .jdbcTemplate(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) + return PgVectorStore.builder(this.jdbcTemplate, this.embeddingModel) .schemaName(this.schemaName) .vectorTableName(this.vectorTableName) .vectorTableValidationsEnabled(this.vectorTableValidationsEnabled) diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorEmbeddingDimensionsTests.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorEmbeddingDimensionsTests.java index f2ace8540..e3bee959e 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorEmbeddingDimensionsTests.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorEmbeddingDimensionsTests.java @@ -47,9 +47,7 @@ public class PgVectorEmbeddingDimensionsTests { final int explicitDimensions = 696; - PgVectorStore pgVectorStore = PgVectorStore.builder() - .jdbcTemplate(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) + PgVectorStore pgVectorStore = PgVectorStore.builder(this.jdbcTemplate, this.embeddingModel) .dimensions(explicitDimensions) .build(); var dim = pgVectorStore.embeddingDimensions(); @@ -62,10 +60,7 @@ public class PgVectorEmbeddingDimensionsTests { public void embeddingModelDimensions() { given(this.embeddingModel.dimensions()).willReturn(969); - PgVectorStore pgVectorStore = PgVectorStore.builder() - .jdbcTemplate(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) - .build(); + PgVectorStore pgVectorStore = PgVectorStore.builder(this.jdbcTemplate, this.embeddingModel).build(); var dim = pgVectorStore.embeddingDimensions(); assertThat(dim).isEqualTo(969); @@ -78,10 +73,7 @@ public class PgVectorEmbeddingDimensionsTests { given(this.embeddingModel.dimensions()).willThrow(new RuntimeException()); - PgVectorStore pgVectorStore = PgVectorStore.builder() - .jdbcTemplate(this.jdbcTemplate) - .embeddingModel(this.embeddingModel) - .build(); + PgVectorStore pgVectorStore = PgVectorStore.builder(this.jdbcTemplate, this.embeddingModel).build(); var dim = pgVectorStore.embeddingDimensions(); assertThat(dim).isEqualTo(PgVectorStore.OPENAI_EMBEDDING_DIMENSION_SIZE); diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreCustomNamesIT.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreCustomNamesIT.java index e6f6fbc77..8c3ddd751 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreCustomNamesIT.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreCustomNamesIT.java @@ -196,9 +196,7 @@ public class PgVectorStoreCustomNamesIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { - return PgVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return PgVectorStore.builder(jdbcTemplate, embeddingModel) .schemaName(this.schemaName) .vectorTableName(this.vectorTableName) .vectorTableValidationsEnabled(this.schemaValidation) diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreIT.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreIT.java index 4dbf74e95..7e926fa1d 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreIT.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreIT.java @@ -356,9 +356,7 @@ public class PgVectorStoreIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { - return PgVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return PgVectorStore.builder(jdbcTemplate, embeddingModel) .dimensions(PgVectorStore.INVALID_EMBEDDING_DIMENSION) .distanceType(this.distanceType) .initializeSchema(true) diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreObservationIT.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreObservationIT.java index 88aba5b80..4dae0f1a6 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreObservationIT.java @@ -187,9 +187,7 @@ public class PgVectorStoreObservationIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return PgVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) + return PgVectorStore.builder(jdbcTemplate, embeddingModel) .distanceType(PgVectorStore.PgDistanceType.COSINE_DISTANCE) .indexType(PgIndexType.HNSW) .observationRegistry(observationRegistry) diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreTests.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreTests.java index 656220e71..cfe63b81e 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreTests.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorStoreTests.java @@ -79,11 +79,7 @@ public class PgVectorStoreTests { // Given var jdbcTemplate = mock(JdbcTemplate.class); var embeddingModel = mock(EmbeddingModel.class); - var pgVectorStore = PgVectorStore.builder() - .jdbcTemplate(jdbcTemplate) - .embeddingModel(embeddingModel) - .maxDocumentBatchSize(1000) - .build(); + var pgVectorStore = PgVectorStore.builder(jdbcTemplate, embeddingModel).maxDocumentBatchSize(1000).build(); // Testing with 9989 documents var documents = Collections.nCopies(9989, new Document("foo")); diff --git a/vector-stores/spring-ai-pinecone-store/src/main/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStore.java b/vector-stores/spring-ai-pinecone-store/src/main/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStore.java index df471a796..b34c6ced3 100644 --- a/vector-stores/spring-ai-pinecone-store/src/main/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStore.java +++ b/vector-stores/spring-ai-pinecone-store/src/main/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStore.java @@ -109,8 +109,7 @@ public class PineconeVectorStore extends AbstractObservationVectorStore { public PineconeVectorStore(PineconeVectorStoreConfig config, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().embeddingModel(embeddingModel) - .apiKey(config.clientConfig.getApiKey()) + this(builder(embeddingModel).apiKey(config.clientConfig.getApiKey()) .projectId(config.clientConfig.getProjectName()) .environment(config.clientConfig.getEnvironment()) .indexName(config.connectionConfig.getIndexName()) @@ -156,8 +155,8 @@ public class PineconeVectorStore extends AbstractObservationVectorStore { * Creates a new builder instance for configuring a PineconeVectorStore. * @return A new PineconeBuilder instance */ - public static PineconeBuilder builder() { - return new PineconeBuilder(); + public static PineconeBuilder builder(EmbeddingModel embeddingModel) { + return new PineconeBuilder(embeddingModel); } /** @@ -358,6 +357,10 @@ public class PineconeVectorStore extends AbstractObservationVectorStore { private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); + private PineconeBuilder(EmbeddingModel embeddingModel) { + super(embeddingModel); + } + /** * Sets the Pinecone API key. * @param apiKey The API key to use @@ -467,7 +470,6 @@ public class PineconeVectorStore extends AbstractObservationVectorStore { */ @Override public PineconeVectorStore build() { - validate(); return new PineconeVectorStore(this); } diff --git a/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreIT.java b/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreIT.java index 4e05e1e12..c128acaef 100644 --- a/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreIT.java +++ b/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreIT.java @@ -275,8 +275,7 @@ public class PineconeVectorStoreIT { @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { String apikey = System.getenv("PINECONE_API_KEY"); - return PineconeVectorStore.builder() - .embeddingModel(embeddingModel) + return PineconeVectorStore.builder(embeddingModel) .apiKey(apikey) .environment(PINECONE_ENVIRONMENT) .projectId(PINECONE_PROJECT_ID) diff --git a/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreObservationIT.java b/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreObservationIT.java index 02c611576..5cf5573b3 100644 --- a/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-pinecone-store/src/test/java/org/springframework/ai/vectorstore/pinecone/PineconeVectorStoreObservationIT.java @@ -187,8 +187,7 @@ public class PineconeVectorStoreObservationIT { @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return PineconeVectorStore.builder() - .embeddingModel(embeddingModel) + return PineconeVectorStore.builder(embeddingModel) .apiKey(System.getenv("PINECONE_API_KEY")) .environment(PINECONE_ENVIRONMENT) .projectId(PINECONE_PROJECT_ID) diff --git a/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java b/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java index 0630fa160..be315413b 100644 --- a/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java +++ b/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java @@ -149,7 +149,7 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements * @param collectionName The name of the collection to use in Qdrant. * @param embeddingModel The client for embedding operations. * @param initializeSchema A boolean indicating whether to initialize the schema. - * @deprecated Use {@link #builder(QdrantClient)} + * @deprecated Use {@link #builder(QdrantClient, EmbeddingModel)} */ @Deprecated(forRemoval = true, since = "1.0.0-M5") public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel, @@ -166,15 +166,14 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements * @param initializeSchema A boolean indicating whether to initialize the schema. * @param observationRegistry The observation registry to use. * @param customObservationConvention The custom search observation convention to use. - * @deprecated Use {@link #builder(QdrantClient)} + * @deprecated Use {@link #builder(QdrantClient, EmbeddingModel)} */ @Deprecated(forRemoval = true, since = "1.0.0-M5") public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel, boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder(qdrantClient).embeddingModel(embeddingModel) - .collectionName(collectionName) + this(builder(qdrantClient, embeddingModel).collectionName(collectionName) .initializeSchema(initializeSchema) .observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) @@ -206,8 +205,8 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements * @param qdrantClient the client for interfacing with Qdrant * @return a new QdrantBuilder instance */ - public static QdrantBuilder builder(QdrantClient qdrantClient) { - return new QdrantBuilder(qdrantClient); + public static QdrantBuilder builder(QdrantClient qdrantClient, EmbeddingModel embeddingModel) { + return new QdrantBuilder(qdrantClient, embeddingModel); } /** @@ -386,7 +385,8 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements * @param qdrantClient the client for Qdrant operations * @throws IllegalArgumentException if qdrantClient is null */ - QdrantBuilder(QdrantClient qdrantClient) { + private QdrantBuilder(QdrantClient qdrantClient, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(qdrantClient, "QdrantClient must not be null"); this.qdrantClient = qdrantClient; } @@ -434,7 +434,6 @@ public class QdrantVectorStore extends AbstractObservationVectorStore implements */ @Override public QdrantVectorStore build() { - validate(); return new QdrantVectorStore(this); } diff --git a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreBuilderTests.java b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreBuilderTests.java index e681a40bb..bbdfa73fa 100644 --- a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreBuilderTests.java +++ b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreBuilderTests.java @@ -46,7 +46,7 @@ class QdrantVectorStoreBuilderTests { @Test void defaultConfiguration() { - QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient).embeddingModel(embeddingModel).build(); + QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient, embeddingModel).build(); // Verify default values assertThat(vectorStore).hasFieldOrPropertyWithValue("collectionName", "vector_store"); @@ -56,8 +56,7 @@ class QdrantVectorStoreBuilderTests { @Test void customConfiguration() { - QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient) - .embeddingModel(embeddingModel) + QdrantVectorStore vectorStore = QdrantVectorStore.builder(qdrantClient, embeddingModel) .collectionName("custom_collection") .initializeSchema(true) .batchingStrategy(new TokenCountBatchingStrategy()) @@ -70,31 +69,29 @@ class QdrantVectorStoreBuilderTests { @Test void nullQdrantClientInConstructorShouldThrowException() { - assertThatThrownBy(() -> QdrantVectorStore.builder(null)).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> QdrantVectorStore.builder(null, null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("QdrantClient must not be null"); } @Test void nullEmbeddingModelShouldThrowException() { - assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient).embeddingModel(null).build()) + assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, null).build()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("EmbeddingModel must not be null"); } @Test void emptyCollectionNameShouldThrowException() { - assertThatThrownBy( - () -> QdrantVectorStore.builder(qdrantClient).embeddingModel(embeddingModel).collectionName("").build()) + assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, embeddingModel).collectionName("").build()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("collectionName must not be empty"); } @Test void nullBatchingStrategyShouldThrowException() { - assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient) - .embeddingModel(embeddingModel) - .batchingStrategy(null) - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("BatchingStrategy must not be null"); + assertThatThrownBy(() -> QdrantVectorStore.builder(qdrantClient, embeddingModel).batchingStrategy(null).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("BatchingStrategy must not be null"); } } diff --git a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java index 282fb5577..b5a89c893 100644 --- a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java +++ b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java @@ -254,9 +254,8 @@ public class QdrantVectorStoreIT { @Bean public VectorStore qdrantVectorStore(EmbeddingModel embeddingModel, QdrantClient qdrantClient) { - return QdrantVectorStore.builder(qdrantClient) + return QdrantVectorStore.builder(qdrantClient, embeddingModel) .collectionName(COLLECTION_NAME) - .embeddingModel(embeddingModel) .initializeSchema(true) .build(); } diff --git a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreObservationIT.java b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreObservationIT.java index f54a2b480..a227b7d54 100644 --- a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreObservationIT.java @@ -195,9 +195,8 @@ public class QdrantVectorStoreObservationIT { @Bean public VectorStore qdrantVectorStore(EmbeddingModel embeddingModel, QdrantClient qdrantClient, ObservationRegistry observationRegistry) { - return QdrantVectorStore.builder(qdrantClient) + return QdrantVectorStore.builder(qdrantClient, embeddingModel) .collectionName(COLLECTION_NAME) - .embeddingModel(embeddingModel) .initializeSchema(true) .observationRegistry(observationRegistry) .customObservationConvention(null) diff --git a/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java b/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java index ad801d089..a6aeed0d8 100644 --- a/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java +++ b/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java @@ -248,9 +248,7 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().jedis(jedis) - .embeddingModel(embeddingModel) - .indexName(config.indexName) + this(builder(jedis, embeddingModel).indexName(config.indexName) .prefix(config.prefix) .contentFieldName(config.contentFieldName) .embeddingFieldName(config.embeddingFieldName) @@ -483,13 +481,13 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements } - public static RedisBuilder builder() { - return new RedisBuilder(); + public static RedisBuilder builder(JedisPooled jedis, EmbeddingModel embeddingModel) { + return new RedisBuilder(jedis, embeddingModel); } public static class RedisBuilder extends AbstractVectorStoreBuilder { - private JedisPooled jedis; + private final JedisPooled jedis; private String indexName = DEFAULT_INDEX_NAME; @@ -507,10 +505,10 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements private BatchingStrategy batchingStrategy = new TokenCountBatchingStrategy(); - public RedisBuilder jedis(JedisPooled jedis) { + public RedisBuilder(JedisPooled jedis, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(jedis, "JedisPooled must not be null"); this.jedis = jedis; - return this; } /** @@ -618,7 +616,6 @@ public class RedisVectorStore extends AbstractObservationVectorStore implements @Override public RedisVectorStore build() { - validate(); return new RedisVectorStore(this); } diff --git a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreIT.java b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreIT.java index 250f07b25..8973e56f2 100644 --- a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreIT.java +++ b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreIT.java @@ -256,9 +256,9 @@ class RedisVectorStoreIT { @Bean public RedisVectorStore vectorStore(EmbeddingModel embeddingModel, JedisConnectionFactory jedisConnectionFactory) { - return RedisVectorStore.builder() - .jedis(new JedisPooled(jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort())) - .embeddingModel(embeddingModel) + return RedisVectorStore + .builder(new JedisPooled(jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort()), + embeddingModel) .metadataFields(MetadataField.tag("meta1"), MetadataField.tag("meta2"), MetadataField.tag("country"), MetadataField.numeric("year")) .initializeSchema(true) diff --git a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreObservationIT.java b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreObservationIT.java index b88928f04..8b8ed2130 100644 --- a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/redis/RedisVectorStoreObservationIT.java @@ -176,9 +176,9 @@ public class RedisVectorStoreObservationIT { @Bean public RedisVectorStore vectorStore(EmbeddingModel embeddingModel, JedisConnectionFactory jedisConnectionFactory, ObservationRegistry observationRegistry) { - return RedisVectorStore.builder() - .jedis(new JedisPooled(jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort())) - .embeddingModel(embeddingModel) + return RedisVectorStore + .builder(new JedisPooled(jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort()), + embeddingModel) .observationRegistry(observationRegistry) .customObservationConvention(null) .initializeSchema(true) diff --git a/vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStore.java b/vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStore.java index d15103680..73f129c4e 100644 --- a/vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStore.java +++ b/vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStore.java @@ -194,9 +194,7 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme boolean initializeSchema, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().client(client) - .embeddingModel(embeddingModel) - .collectionName(config.collectionName) + this(builder(client, embeddingModel).collectionName(config.collectionName) .embeddingDimension(config.embeddingDimension) .initializeSchema(initializeSchema) .observationRegistry(observationRegistry) @@ -232,8 +230,8 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme * a TypesenseVectorStore. * @return a new TypesenseBuilder instance */ - public static TypesenseBuilder builder() { - return new TypesenseBuilder(); + public static TypesenseBuilder builder(Client client, EmbeddingModel embeddingModel) { + return new TypesenseBuilder(client, embeddingModel); } @Override @@ -455,7 +453,7 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme private int embeddingDimension = INVALID_EMBEDDING_DIMENSION; - private Client client; + private final Client client; private boolean initializeSchema = false; @@ -467,10 +465,10 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme * @return this builder instance * @throws IllegalArgumentException if client is null */ - public TypesenseBuilder client(Client client) { + public TypesenseBuilder(Client client, EmbeddingModel embeddingModel) { + super(embeddingModel); Assert.notNull(client, "client must not be null"); this.client = client; - return this; } /** @@ -521,7 +519,6 @@ public class TypesenseVectorStore extends AbstractObservationVectorStore impleme @Override public TypesenseVectorStore build() { - validate(); return new TypesenseVectorStore(this); } diff --git a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreBuilderTests.java b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreBuilderTests.java index abb51de80..4e1bde08a 100644 --- a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreBuilderTests.java +++ b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreBuilderTests.java @@ -51,10 +51,7 @@ class TypesenseVectorStoreBuilderTests { @Test void defaultConfiguration() { - TypesenseVectorStore vectorStore = TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) - .build(); + TypesenseVectorStore vectorStore = TypesenseVectorStore.builder(client, embeddingModel).build(); // Verify default values assertThat(vectorStore).hasFieldOrPropertyWithValue("collectionName", "vector_store"); @@ -65,9 +62,7 @@ class TypesenseVectorStoreBuilderTests { @Test void customConfiguration() { - TypesenseVectorStore vectorStore = TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) + TypesenseVectorStore vectorStore = TypesenseVectorStore.builder(client, embeddingModel) .collectionName("custom_collection") .embeddingDimension(1536) .initializeSchema(true) @@ -80,44 +75,37 @@ class TypesenseVectorStoreBuilderTests { @Test void nullClientShouldThrowException() { - assertThatThrownBy(() -> TypesenseVectorStore.builder().client(null).build()) + assertThatThrownBy(() -> TypesenseVectorStore.builder(null, embeddingModel).build()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("client must not be null"); } @Test void nullEmbeddingModelShouldThrowException() { - assertThatThrownBy(() -> TypesenseVectorStore.builder().client(client).embeddingModel(null).build()) + assertThatThrownBy(() -> TypesenseVectorStore.builder(client, null).build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("EmbeddingModel must not be null"); + .hasMessage("EmbeddingModel must be configured"); } @Test void invalidEmbeddingDimensionShouldThrowException() { - assertThatThrownBy(() -> TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) - .embeddingDimension(0) - .build()).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> TypesenseVectorStore.builder(client, embeddingModel).embeddingDimension(0).build()) + .isInstanceOf(IllegalArgumentException.class) .hasMessage("Embedding dimension must be greater than 0"); } @Test void emptyCollectionNameShouldThrowException() { - assertThatThrownBy(() -> TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) - .collectionName("") - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("collectionName must not be empty"); + assertThatThrownBy(() -> TypesenseVectorStore.builder(client, embeddingModel).collectionName("").build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("collectionName must not be empty"); } @Test void nullBatchingStrategyShouldThrowException() { - assertThatThrownBy(() -> TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) - .batchingStrategy(null) - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("batchingStrategy must not be null"); + assertThatThrownBy(() -> TypesenseVectorStore.builder(client, embeddingModel).batchingStrategy(null).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("batchingStrategy must not be null"); } } diff --git a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreIT.java b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreIT.java index 6cd76c8fd..c44953bc7 100644 --- a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreIT.java +++ b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreIT.java @@ -242,9 +242,7 @@ public class TypesenseVectorStoreIT { @Bean public VectorStore vectorStore(Client client, EmbeddingModel embeddingModel) { - return TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) + return TypesenseVectorStore.builder(client, embeddingModel) .collectionName("test_vector_store") .embeddingDimension(embeddingModel.dimensions()) .initializeSchema(true) diff --git a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreObservationIT.java b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreObservationIT.java index 86223036c..e94d76d2a 100644 --- a/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-typesense-store/src/test/java/org/springframework/ai/vectorstore/typesense/TypesenseVectorStoreObservationIT.java @@ -170,9 +170,7 @@ public class TypesenseVectorStoreObservationIT { public VectorStore vectorStore(Client client, EmbeddingModel embeddingModel, ObservationRegistry observationRegistry) { - return TypesenseVectorStore.builder() - .client(client) - .embeddingModel(embeddingModel) + return TypesenseVectorStore.builder(client, embeddingModel) .collectionName(TEST_COLLECTION_NAME) .embeddingDimension(embeddingModel.dimensions()) .initializeSchema(true) diff --git a/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStore.java b/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStore.java index 836450069..35e5814e0 100644 --- a/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStore.java +++ b/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStore.java @@ -181,9 +181,7 @@ public class WeaviateVectorStore extends AbstractObservationVectorStore { WeaviateClient weaviateClient, ObservationRegistry observationRegistry, VectorStoreObservationConvention customObservationConvention, BatchingStrategy batchingStrategy) { - this(builder().embeddingModel(embeddingModel) - .weaviateClient(weaviateClient) - .observationRegistry(observationRegistry) + this(builder(weaviateClient, embeddingModel).observationRegistry(observationRegistry) .customObservationConvention(customObservationConvention) .batchingStrategy(batchingStrategy)); } @@ -217,8 +215,8 @@ public class WeaviateVectorStore extends AbstractObservationVectorStore { * a WeaviateVectorStore. * @return a new WeaviateBuilder instance */ - public static WeaviateBuilder builder() { - return new WeaviateBuilder(); + public static WeaviateBuilder builder(WeaviateClient weaviateClient, EmbeddingModel embeddingModel) { + return new WeaviateBuilder(weaviateClient, embeddingModel); } private Field[] buildWeaviateSimilaritySearchFields() { @@ -550,10 +548,10 @@ public class WeaviateVectorStore extends AbstractObservationVectorStore { * @return this builder instance * @throws IllegalArgumentException if weaviateClient is null */ - public WeaviateBuilder weaviateClient(WeaviateClient weaviateClient) { - Assert.notNull(weaviateClient, "weaviateClient must not be null"); + private WeaviateBuilder(WeaviateClient weaviateClient, EmbeddingModel embeddingModel) { + super(embeddingModel); + Assert.notNull(weaviateClient, "WeaviateClient must not be null"); this.weaviateClient = weaviateClient; - return this; } /** @@ -612,7 +610,6 @@ public class WeaviateVectorStore extends AbstractObservationVectorStore { */ @Override public WeaviateVectorStore build() { - validate(); return new WeaviateVectorStore(this); } diff --git a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreBuilderTests.java b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreBuilderTests.java index 739ed525a..03986de31 100644 --- a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreBuilderTests.java +++ b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreBuilderTests.java @@ -47,10 +47,7 @@ class WeaviateVectorStoreBuilderTests { void shouldBuildWithMinimalConfiguration() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - WeaviateVectorStore vectorStore = WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) - .build(); + WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, embeddingModel).build(); assertThat(vectorStore).isNotNull(); } @@ -59,9 +56,7 @@ class WeaviateVectorStoreBuilderTests { void shouldBuildWithCustomConfiguration() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - WeaviateVectorStore vectorStore = WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) + WeaviateVectorStore vectorStore = WeaviateVectorStore.builder(weaviateClient, embeddingModel) .objectClass("CustomClass") .consistencyLevel(ConsistentLevel.QUORUM) .filterMetadataFields(List.of(MetadataField.text("country"), MetadataField.number("year"))) @@ -72,7 +67,7 @@ class WeaviateVectorStoreBuilderTests { @Test void shouldFailWithoutWeaviateClient() { - assertThatThrownBy(() -> WeaviateVectorStore.builder().embeddingModel(embeddingModel).build()) + assertThatThrownBy(() -> WeaviateVectorStore.builder(null, embeddingModel).build()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("WeaviateClient must not be null"); } @@ -81,7 +76,7 @@ class WeaviateVectorStoreBuilderTests { void shouldFailWithoutEmbeddingModel() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - assertThatThrownBy(() -> WeaviateVectorStore.builder().weaviateClient(weaviateClient).build()) + assertThatThrownBy(() -> WeaviateVectorStore.builder(weaviateClient, null).build()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("EmbeddingModel must be configured"); } @@ -90,33 +85,29 @@ class WeaviateVectorStoreBuilderTests { void shouldFailWithInvalidObjectClass() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - assertThatThrownBy(() -> WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) - .objectClass("") - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("objectClass must not be empty"); + assertThatThrownBy(() -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).objectClass("").build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("objectClass must not be empty"); } @Test void shouldFailWithNullConsistencyLevel() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - assertThatThrownBy(() -> WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) - .consistencyLevel(null) - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("consistencyLevel must not be null"); + assertThatThrownBy( + () -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).consistencyLevel(null).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("consistencyLevel must not be null"); } @Test void shouldFailWithNullFilterMetadataFields() { WeaviateClient weaviateClient = new WeaviateClient(new Config("http", "localhost:8080")); - assertThatThrownBy(() -> WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) - .filterMetadataFields(null) - .build()).isInstanceOf(IllegalArgumentException.class).hasMessage("filterMetadataFields must not be null"); + assertThatThrownBy( + () -> WeaviateVectorStore.builder(weaviateClient, embeddingModel).filterMetadataFields(null).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("filterMetadataFields must not be null"); } @Test diff --git a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreIT.java b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreIT.java index b675b5f96..28c45b721 100644 --- a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreIT.java +++ b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreIT.java @@ -252,9 +252,7 @@ public class WeaviateVectorStoreIT { WeaviateClient weaviateClient = new WeaviateClient( new Config("http", weaviateContainer.getHttpHostAddress())); - return WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) + return WeaviateVectorStore.builder(weaviateClient, embeddingModel) .filterMetadataFields(List.of(WeaviateVectorStore.MetadataField.text("country"), WeaviateVectorStore.MetadataField.number("year"))) .consistencyLevel(WeaviateVectorStore.ConsistentLevel.ONE) diff --git a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreObservationIT.java b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreObservationIT.java index b3b8ea8f7..23f012491 100644 --- a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreObservationIT.java +++ b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStoreObservationIT.java @@ -166,9 +166,7 @@ public class WeaviateVectorStoreObservationIT { WeaviateClient weaviateClient = new WeaviateClient( new io.weaviate.client.Config("http", weaviateContainer.getHttpHostAddress())); - return WeaviateVectorStore.builder() - .weaviateClient(weaviateClient) - .embeddingModel(embeddingModel) + return WeaviateVectorStore.builder(weaviateClient, embeddingModel) .consistencyLevel(WeaviateVectorStore.ConsistentLevel.ONE) .observationRegistry(observationRegistry) .batchingStrategy(new TokenCountBatchingStrategy())