From 5beef21a4eca4fff54a4a8395419fbf36acf60cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Mon, 6 May 2024 00:21:03 +0100 Subject: [PATCH] Expose `QdrantClient` and `WeaviateClient` as beans Currently, `QdrantClient` and `WeaviateClient` are not exposed as beans. Having access to those would benefit to perform operations with an already configured client. - Deprecate QdrantVectorStoreConfig. - Update Qdrant manual config adoc. - Improve Qdrant adoc. - Update Weaviate docs. --- .../ROOT/pages/api/vectordbs/qdrant.adoc | 116 +++++----- .../ROOT/pages/api/vectordbs/weaviate.adoc | 218 +++++++++++------- .../QdrantVectorStoreAutoConfiguration.java | 29 ++- .../WeaviateVectorStoreAutoConfiguration.java | 28 ++- .../vectorstore/qdrant/QdrantVectorStore.java | 66 +----- .../ai/vectorstore/WeaviateVectorStore.java | 72 +----- .../ai/vectorstore/WeaviateVectorStoreIT.java | 9 +- 7 files changed, 248 insertions(+), 290 deletions(-) diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc index a5d4b871a..5ebaf926e 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/qdrant.adoc @@ -14,7 +14,7 @@ To set up `QdrantVectorStore`, you'll need the following information from your Q NOTE: It is recommended that the Qdrant collection is link:https://qdrant.tech/documentation/concepts/collections/#create-a-collection[created] in advance with the appropriate dimensions and configurations. If the collection is not created, the `QdrantVectorStore` will attempt to create one using the `Cosine` similarity and the dimension of the configured `EmbeddingClient`. -== Dependencies +== Auto-configuration Then add the Qdrant boot starter dependency to your project: @@ -96,53 +96,21 @@ vectorStore.add(documents); List results = vectorStore.similaritySearch(SearchRequest.query("Spring").withTopK(5)); ---- -=== Manual Configuration +[[qdrant-vectorstore-properties]] +=== Configuration properties -Instead of using the Spring Boot auto-configuration, you can manually configure the `QdrantVectorStore`. For this you need to add the `spring-ai-qdrant` dependency to your project: +You can use the following properties in your Spring Boot configuration to customize the Qdrant vector store. -[source,xml] ----- - - org.springframework.ai - spring-ai-qdrant - ----- +[cols="3,5,1"] +|=== +|Property| Description | Default value -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-qdrant' -} ----- - -To configure Qdrant in your application, you can use the following setup: - -[source,java] ----- -@Bean -public QdrantVectorStoreConfig qdrantVectorStoreConfig() { - - return QdrantVectorStoreConfig.builder() - .withHost("") - .withPort() - .withCollectionName("") - .withApiKey("") - .build(); -} ----- - -Integrate with OpenAI's embeddings by adding the Spring Boot OpenAI starter to your project. -This provides you with an implementation of the Embeddings client: - -[source,java] ----- -@Bean -public VectorStore vectorStore(QdrantVectorStoreConfig config, EmbeddingClient embeddingClient) { - return new QdrantVectorStore(config, embeddingClient); -} ----- +|`spring.ai.vectorstore.qdrant.host`| The host of the Qdrant server. | localhost +|`spring.ai.vectorstore.qdrant.port`| The gRPC port of the Qdrant server. | 6334 +|`spring.ai.vectorstore.qdrant.api-key`| The API key to use for authentication with the Qdrant server. | - +|`spring.ai.vectorstore.qdrant.collection-name`| The name of the collection to use in Qdrant. | - +|`spring.ai.vectorstore.qdrant.use-tls`| Whether to use TLS(HTTPS). | false +|=== == Metadata filtering @@ -177,18 +145,52 @@ vectorStore.similaritySearch(SearchRequest.defaults() NOTE: These filter expressions are converted into the equivalent Qdrant link:https://qdrant.tech/documentation/concepts/filtering/[filters]. -[[qdrant-vectorstore-properties]] -== Configuration properties +== Manual Configuration -You can use the following properties in your Spring Boot configuration to customize the Qdrant vector store. +Instead of using the Spring Boot auto-configuration, you can manually configure the `QdrantVectorStore`. For this you need to add the `spring-ai-qdrant` dependency to your project: -[cols="3,5,1"] -|=== -|Property| Description | Default value +[source,xml] +---- + + org.springframework.ai + spring-ai-qdrant + +---- -|`spring.ai.vectorstore.qdrant.host`| The host of the Qdrant server. | localhost -|`spring.ai.vectorstore.qdrant.port`| The gRPC port of the Qdrant server. | 6334 -|`spring.ai.vectorstore.qdrant.api-key`| The API key to use for authentication with the Qdrant server. | - -|`spring.ai.vectorstore.qdrant.collection-name`| The name of the collection to use in Qdrant. | - -|`spring.ai.vectorstore.qdrant.use-tls`| Whether to use TLS(HTTPS). | false -|=== +or to your Gradle `build.gradle` build file. + +[source,groovy] +---- +dependencies { + implementation 'org.springframework.ai:spring-ai-qdrant' +} +---- + +To configure Qdrant in your application, you can create a QdrantClient: + +[source,java] +---- +@Bean +public QdrantClient qdrantClient() { + + QdrantGrpcClient.Builder grpcClientBuilder = + QdrantGrpcClient.newBuilder( + "", + , + ); + grpcClientBuilder.withApiKey(""); + + return new QdrantClient(grpcClientBuilder.build()); +} +---- + +Integrate with OpenAI's embeddings by adding the Spring Boot OpenAI starter to your project. +This provides you with an implementation of the Embeddings client: + +[source,java] +---- +@Bean +public QdrantVectorStore vectorStore(EmbeddingClient embeddingClient, QdrantClient qdrantClient) { + return new QdrantVectorStore(qdrantClient, "", embeddingClient); +} +---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/weaviate.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/weaviate.adoc index c1ec141fa..060bb322e 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/weaviate.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/weaviate.adoc @@ -19,115 +19,106 @@ It provides tools to store document embeddings, content, and metadata and to sea On startup, the `WeaviateVectorStore` creates the required `SpringAiWeaviate` object schema if it's not already provisioned. -== Dependencies +== Auto-configuration -Add these dependencies to your project: - -* Embedding Client boot starter, required for calculating embeddings. - -* Transformers Embedding (Local) and follow the ONNX Transformers Embedding instructions. +Then add the WeaviateVectorStore boot starter dependency to your project: [source,xml] ---- - org.springframework.ai - spring-ai-transformers-spring-boot-starter + org.springframework.ai + spring-ai-weaviate-store-spring-boot-starter ---- -or use OpenAI (Cloud) +or to your Gradle `build.gradle` build file. -[source,xml] +[source,groovy] ---- - - org.springframework.ai - spring-ai-openai-spring-boot-starter - ----- - -You'll need to provide your OpenAI API Key. Set it as an environment variable like so: - -[source,bash] ----- -export SPRING_AI_OPENAI_API_KEY='Your_OpenAI_API_Key' ----- - -* Add the Weaviate VectorStore dependency - -[source,xml] ----- - - org.springframework.ai - spring-ai-weaviate-store - ----- - -TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. - -== Usage - -Create a WeaviateVectorStore instance connected to the local Weaviate cluster: - -[source,java] ----- -@Bean -public VectorStore vectorStore(EmbeddingClient embeddingClient) { - WeaviateVectorStoreConfig config = WeaviateVectorStoreConfig.builder() - .withScheme("http") - .withHost("localhost:8080") - // Define the metadata fields to be used - // in the similarity search filters. - .withFilterableMetadataFields(List.of( - MetadataField.text("country"), - MetadataField.number("year"), - MetadataField.bool("active"))) - // Consistency level can be: ONE, QUORUM, or ALL. - .withConsistencyLevel(ConsistentLevel.ONE) - .build(); - - return new WeaviateVectorStore(config, embeddingClient); +dependencies { + implementation 'org.springframework.ai:spring-ai-weaviate-store-spring-boot-starter' } ---- -> [NOTE] -> You must list explicitly all metadata field names and types (`BOOLEAN`, `TEXT`, or `NUMBER`) for any metadata key used in filter expression. -> The `withFilterableMetadataKeys` above registers filterable metadata fields: `country` of type `TEXT`, `year` of type `NUMBER`, and `active` of type `BOOLEAN`. -> -> If the filterable metadata fields are expanded with new entries, you have to (re)upload/update the documents with this metadata. -> -> You can use the following Weaviate link:https://weaviate.io/developers/weaviate/api/graphql/filters#special-cases[system metadata] fields without explicit definition: `id`, `_creationTimeUnix`, and `_lastUpdateTimeUnix`. +The Vector Store, also requires an `EmbeddingClient` instance to calculate embeddings for the documents. +You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingClient Implementations]. -Then in your main code, create some documents: +For example to use the xref:api/embeddings/openai-embeddings.adoc[OpenAI EmbeddingClient] add the following dependency to your project: + +[source,xml] +---- + + org.springframework.ai + spring-ai-openai-spring-boot-starter + +---- + +or to your Gradle `build.gradle` build file. + +[source,groovy] +---- +dependencies { + implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter' +} +---- + +TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. +Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file. + +To connect to Weaviate and use the `WeaviateVectorStore`, you need to provide access details for your instance. +A simple configuration can either be provided via Spring Boot's _application.properties_, + +[source,properties] +---- +spring.ai.vectorstore.weaviate.host= +spring.ai.vectorstore.weaviate.api-key= +spring.ai.vectorstore.weaviate.scheme=http + +# API key if needed, e.g. OpenAI +spring.ai.openai.api.key= +---- + +TIP: Check the list of xref:#weaviate-vectorstore-properties[configuration parameters] to learn about the default values and configuration options. + +Now you can Auto-wire the Weaviate Vector Store in your application and use it [source,java] ---- -List documents = List.of( - new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("country", "UK", "active", true, "year", 2020)), - new Document("The World is Big and Salvation Lurks Around the Corner", Map.of()), - new Document("You walk forward facing the past and you turn back toward the future.", Map.of("country", "NL", "active", false, "year", 2023))); +@Autowired VectorStore vectorStore; + +// ... + +List documents = List.of( + new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")), + new Document("The World is Big and Salvation Lurks Around the Corner"), + new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2"))); + +// Add the documents +vectorStore.add(documents); + +// Retrieve documents similar to a query +List results = vectorStore.similaritySearch(SearchRequest.query("Spring").withTopK(5)); ---- -Now add the documents to your vector store: +[[weaviate-vectorstore-properties]] +=== Configuration properties +You can use the following properties in your Spring Boot configuration to customize the weaviate vector store. -[source,java] ----- -vectorStore.add(List.of(document)); ----- +[cols="3,5,1"] +|=== +|Property| Description | Default value -And finally, retrieve documents similar to a query: +|`spring.ai.vectorstore.weaviate.host`| The host of the Weaviate server. | localhost:8080 +|`spring.ai.vectorstore.weaviate.scheme`| Connection schema. | http +|`spring.ai.vectorstore.weaviate.api-key`| The API key to use for authentication with the Weaviate server. | - +|`spring.ai.vectorstore.weaviate.object-class`| | "SpringAiWeaviate" +|`spring.ai.vectorstore.weaviate.consistency-level`| Desired tradeoff between consistency and speed | ConsistentLevel.ONE +|`spring.ai.vectorstore.weaviate.filter-field`| spring.ai.vectorstore.weaviate.filter-field.= | - +|`spring.ai.vectorstore.weaviate.headers`| | - +|=== -[source,java] ----- -List results = vectorStore.similaritySearch( - SearchRequest - .query("Spring") - .withTopK(5)); ----- - -If all goes well, you should retrieve the document containing the text "Spring AI rocks!!". - -=== Metadata filtering +== Metadata filtering You can leverage the generic, portable link:https://docs.spring.io/spring-ai/reference/api/vectordbs.html#_metadata_filters[metadata filters] with WeaviateVectorStore as well. @@ -194,6 +185,61 @@ operator:And }] ---- +== Manual Configuration + +Instead of using the Spring Boot auto-configuration, you can manually configure the `WeaviateVectorStore`. +For this you need to add the `spring-ai-weaviate-store` dependency to your project: + +[source,xml] +---- + + org.springframework.ai + spring-ai-weaviate-store + +---- + +or to your Gradle `build.gradle` build file. + +[source,groovy] +---- +dependencies { + implementation 'org.springframework.ai:spring-ai-weaviate-store' +} +---- + +To configure Weaviate in your application, you can create a WeaviateClient: + +[source,java] +---- +@Bean +public WeaviateClient weaviateClient() { + try { + return WeaviateAuthClient.apiKey( + new Config(, , ), + ); + } + catch (AuthException e) { + throw new IllegalArgumentException("WeaviateClient could not be created.", e); + } +} +---- + +Integrate with OpenAI's embeddings by adding the Spring Boot OpenAI starter to your project. +This provides you with an implementation of the Embeddings client: + +[source,java] +---- +@Bean +public WeaviateVectorStore vectorStore(EmbeddingClient embeddingClient, WeaviateClient weaviateClient) { + + WeaviateVectorStoreConfig.Builder configBuilder = WeaviateVectorStore.WeaviateVectorStoreConfig.builder() + .withObjectClass() + .withConsistencyLevel(); + + return new WeaviateVectorStore(configBuilder.build(), embeddingClient, weaviateClient); +} +---- + == Run Weaviate cluster in docker container Start Weaviate in a docker container: 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 5540f2977..c0dd23640 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 @@ -15,9 +15,10 @@ */ package org.springframework.ai.autoconfigure.vectorstore.qdrant; +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; -import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore.QdrantVectorStoreConfig; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -42,21 +43,25 @@ public class QdrantVectorStoreAutoConfiguration { @Bean @ConditionalOnMissingBean - public QdrantVectorStore vectorStore(EmbeddingClient embeddingClient, QdrantVectorStoreProperties properties, + public QdrantClient qdrantClient(QdrantVectorStoreProperties properties, QdrantConnectionDetails connectionDetails) { + QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder(connectionDetails.getHost(), + connectionDetails.getPort(), properties.isUseTls()); - var config = QdrantVectorStoreConfig.builder() - .withCollectionName(properties.getCollectionName()) - .withHost(connectionDetails.getHost()) - .withPort(connectionDetails.getPort()) - .withTls(properties.isUseTls()) - .withApiKey(properties.getApiKey()) - .build(); - - return new QdrantVectorStore(config, embeddingClient); + if (properties.getApiKey() != null) { + grpcClientBuilder.withApiKey(properties.getApiKey()); + } + return new QdrantClient(grpcClientBuilder.build()); } - private static class PropertiesQdrantConnectionDetails implements QdrantConnectionDetails { + @Bean + @ConditionalOnMissingBean + public QdrantVectorStore vectorStore(EmbeddingClient embeddingClient, QdrantVectorStoreProperties properties, + QdrantClient qdrantClient) { + return new QdrantVectorStore(qdrantClient, properties.getCollectionName(), embeddingClient); + } + + static class PropertiesQdrantConnectionDetails implements QdrantConnectionDetails { private final QdrantVectorStoreProperties properties; 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 3d5c84534..431b70723 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 @@ -15,6 +15,10 @@ */ package org.springframework.ai.autoconfigure.vectorstore.weaviate; +import io.weaviate.client.Config; +import io.weaviate.client.WeaviateAuthClient; +import io.weaviate.client.WeaviateClient; +import io.weaviate.client.v1.auth.exception.AuthException; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.vectorstore.WeaviateVectorStore; import org.springframework.ai.vectorstore.WeaviateVectorStore.WeaviateVectorStoreConfig; @@ -42,14 +46,24 @@ public class WeaviateVectorStoreAutoConfiguration { @Bean @ConditionalOnMissingBean - public WeaviateVectorStore vectorStore(EmbeddingClient embeddingClient, WeaviateVectorStoreProperties properties, + public WeaviateClient weaviateClient(WeaviateVectorStoreProperties properties, WeaviateConnectionDetails connectionDetails) { + try { + return WeaviateAuthClient.apiKey( + new Config(properties.getScheme(), connectionDetails.getHost(), properties.getHeaders()), + properties.getApiKey()); + } + catch (AuthException e) { + throw new IllegalArgumentException("WeaviateClient could not be created.", e); + } + } + + @Bean + @ConditionalOnMissingBean + public WeaviateVectorStore vectorStore(EmbeddingClient embeddingClient, WeaviateClient weaviateClient, + WeaviateVectorStoreProperties properties) { WeaviateVectorStoreConfig.Builder configBuilder = WeaviateVectorStore.WeaviateVectorStoreConfig.builder() - .withScheme(properties.getScheme()) - .withApiKey(properties.getApiKey()) - .withHost(connectionDetails.getHost()) - .withHeaders(properties.getHeaders()) .withObjectClass(properties.getObjectClass()) .withFilterableMetadataFields(properties.getFilterField() .entrySet() @@ -58,10 +72,10 @@ public class WeaviateVectorStoreAutoConfiguration { .toList()) .withConsistencyLevel(properties.getConsistencyLevel()); - return new WeaviateVectorStore(configBuilder.build(), embeddingClient); + return new WeaviateVectorStore(configBuilder.build(), embeddingClient, weaviateClient); } - private static class PropertiesWeaviateConnectionDetails implements WeaviateConnectionDetails { + static class PropertiesWeaviateConnectionDetails implements WeaviateConnectionDetails { private final WeaviateVectorStoreProperties properties; diff --git a/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java b/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java index afe5f6389..67a651bad 100644 --- a/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java +++ b/vector-stores/spring-ai-qdrant/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStore.java @@ -34,7 +34,6 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import io.qdrant.client.QdrantClient; -import io.qdrant.client.QdrantGrpcClient; import io.qdrant.client.grpc.Collections.Distance; import io.qdrant.client.grpc.Collections.VectorParams; import io.qdrant.client.grpc.JsonWithInt.Value; @@ -51,6 +50,7 @@ import io.qdrant.client.grpc.Points.UpdateStatus; * * @author Anush Shetty * @author Christian Tzolov + * @author Eddú Meléndez * @since 0.8.1 */ public class QdrantVectorStore implements VectorStore, InitializingBean { @@ -69,13 +69,14 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { /** * Configuration class for the QdrantVectorStore. + * + * @deprecated since 1.0.0 in favor of {@link QdrantVectorStore}. */ + @Deprecated(since = "1.0.0", forRemoval = true) public static final class QdrantVectorStoreConfig { private final String collectionName; - private QdrantClient qdrantClient; - /* * Constructor using the builder. * @@ -83,15 +84,6 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { */ private QdrantVectorStoreConfig(Builder builder) { this.collectionName = builder.collectionName; - - QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder(builder.host, builder.port, - builder.useTls); - - if (builder.apiKey != null) { - grpcClientBuilder.withApiKey(builder.apiKey); - } - - this.qdrantClient = new QdrantClient(grpcClientBuilder.build()); } /** @@ -113,26 +105,9 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { private String collectionName; - private String host = "localhost"; - - private int port = 6334; - - private boolean useTls = false; - - private String apiKey = null; - private Builder() { } - /** - * @param host The host of the Qdrant instance. Defaults to "localhost". - */ - public Builder withHost(String host) { - Assert.notNull(host, "host cannot be null"); - this.host = host; - return this; - } - /** * @param collectionName REQUIRED. The name of the collection. */ @@ -141,32 +116,6 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { return this; } - /** - * @param port The GRPC port of the Qdrant instance. Defaults to 6334. - * @return - */ - public Builder withPort(int port) { - this.port = port; - return this; - } - - /** - * @param useTls Whether to use TLS(HTTPS). Defaults to false. - * @return - */ - public Builder withTls(boolean useTls) { - this.useTls = useTls; - return this; - } - - /** - * @param apiKey The Qdrant API key to authenticate with. Defaults to null. - */ - public Builder withApiKey(String apiKey) { - this.apiKey = apiKey; - return this; - } - /** * {@return the immutable configuration} */ @@ -183,9 +132,12 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { * Constructs a new QdrantVectorStore. * @param config The configuration for the store. * @param embeddingClient The client for embedding operations. + * @deprecated since 1.0.0 in favor of {@link QdrantVectorStore}. */ - public QdrantVectorStore(QdrantVectorStoreConfig config, EmbeddingClient embeddingClient) { - this(config.qdrantClient, config.collectionName, embeddingClient); + @Deprecated(since = "1.0.0", forRemoval = true) + public QdrantVectorStore(QdrantClient qdrantClient, QdrantVectorStoreConfig config, + EmbeddingClient embeddingClient) { + this(qdrantClient, config.collectionName, embeddingClient); } /** diff --git a/vector-stores/spring-ai-weaviate/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java b/vector-stores/spring-ai-weaviate/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java index d686db958..6e56e8e95 100644 --- a/vector-stores/spring-ai-weaviate/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java +++ b/vector-stores/spring-ai-weaviate/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java @@ -25,12 +25,9 @@ import java.util.stream.Collectors; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import io.weaviate.client.Config; -import io.weaviate.client.WeaviateAuthClient; import io.weaviate.client.WeaviateClient; import io.weaviate.client.base.Result; import io.weaviate.client.base.WeaviateErrorMessage; -import io.weaviate.client.v1.auth.exception.AuthException; import io.weaviate.client.v1.batch.model.BatchDeleteResponse; import io.weaviate.client.v1.batch.model.ObjectGetResponse; import io.weaviate.client.v1.data.model.WeaviateObject; @@ -63,6 +60,7 @@ import org.springframework.util.StringUtils; * expression filters. * * @author Christian Tzolov + * @author Eddú Meléndez */ public class WeaviateVectorStore implements VectorStore, InitializingBean { @@ -169,18 +167,6 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { } - /** - * The server api key. - */ - private final String apiKey; - - /** - * The URL scheme, such as 'http' or 'https'. - */ - private final String scheme; - - private final String host; - private final String weaviateObjectClass; private final ConsistentLevel consistencyLevel; @@ -199,9 +185,6 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { * @param builder The configuration builder. */ public WeaviateVectorStoreConfig(Builder builder) { - this.apiKey = builder.apiKey; - this.scheme = builder.scheme; - this.host = builder.host; this.weaviateObjectClass = builder.objectClass; this.consistencyLevel = builder.consistencyLevel; this.filterMetadataFields = builder.filterMetadataFields; @@ -225,12 +208,6 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { public static class Builder { - private String apiKey = ""; - - private String scheme = "http"; - - private String host = "localhost:8080"; - private String objectClass = "SpringAiWeaviate"; private ConsistentLevel consistencyLevel = WeaviateVectorStoreConfig.ConsistentLevel.ONE; @@ -242,39 +219,6 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { private Builder() { } - /** - * Weaviate api key. - * @param apiKey key to use. - * @return this builder. - */ - public Builder withApiKey(String apiKey) { - Assert.notNull(apiKey, "The apiKey can not be null."); - this.apiKey = apiKey; - return this; - } - - /** - * Weaviate scheme. - * @param scheme scheme to use. - * @return this builder. - */ - public Builder withScheme(String scheme) { - Assert.hasText(scheme, "The scheme can not be empty."); - this.scheme = scheme; - return this; - } - - /** - * Weaviate host. - * @param host host to use. - * @return this builder. - */ - public Builder withHost(String host) { - Assert.hasText(host, "The host can not be empty."); - this.host = host; - return this; - } - /** * Weaviate known, filterable metadata fields. * @param filterMetadataFields known metadata fields to use. @@ -335,7 +279,8 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { * @param vectorStoreConfig The configuration for the store. * @param embeddingClient The client for embedding operations. */ - public WeaviateVectorStore(WeaviateVectorStoreConfig vectorStoreConfig, EmbeddingClient embeddingClient) { + public WeaviateVectorStore(WeaviateVectorStoreConfig vectorStoreConfig, EmbeddingClient embeddingClient, + WeaviateClient weaviateClient) { Assert.notNull(vectorStoreConfig, "WeaviateVectorStoreConfig must not be null"); Assert.notNull(embeddingClient, "EmbeddingClient must not be null"); @@ -345,16 +290,7 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { this.filterMetadataFields = vectorStoreConfig.filterMetadataFields; this.filterExpressionConverter = new WeaviateFilterExpressionConverter( this.filterMetadataFields.stream().map(MetadataField::name).toList()); - - try { - this.weaviateClient = WeaviateAuthClient.apiKey( - new Config(vectorStoreConfig.scheme, vectorStoreConfig.host, vectorStoreConfig.headers), - vectorStoreConfig.apiKey); - } - catch (AuthException e) { - throw new IllegalArgumentException(e); - } - + this.weaviateClient = weaviateClient; this.weaviateSimilaritySearchFields = buildWeaviateSimilaritySearchFields(); } diff --git a/vector-stores/spring-ai-weaviate/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java b/vector-stores/spring-ai-weaviate/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java index 9b9053257..013ebfaa4 100644 --- a/vector-stores/spring-ai-weaviate/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java +++ b/vector-stores/spring-ai-weaviate/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import io.weaviate.client.Config; +import io.weaviate.client.WeaviateClient; import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -242,14 +244,15 @@ public class WeaviateVectorStoreIT { @Bean public VectorStore vectorStore(EmbeddingClient embeddingClient) { + WeaviateClient weaviateClient = new WeaviateClient( + new Config("http", weaviateContainer.getHttpHostAddress())); + WeaviateVectorStoreConfig config = WeaviateVectorStore.WeaviateVectorStoreConfig.builder() - .withScheme("http") - .withHost(weaviateContainer.getHttpHostAddress()) .withFilterableMetadataFields(List.of(MetadataField.text("country"), MetadataField.number("year"))) .withConsistencyLevel(WeaviateVectorStoreConfig.ConsistentLevel.ONE) .build(); - WeaviateVectorStore vectorStore = new WeaviateVectorStore(config, embeddingClient); + WeaviateVectorStore vectorStore = new WeaviateVectorStore(config, embeddingClient, weaviateClient); return vectorStore; }