diff --git a/README.md b/README.md index e3e9c3378..18a8f487b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,27 @@ For further information go to our [Spring AI reference documentation](https://do On our march to release 1.0.0 M1 we have made several breaking changes. Apologies, it is for the best! +**(22.25.2024)** + +Vector stores that have a schema are now *not* initialized by default. +As is the convention with other Spring projects that rely on a schema, you must opt into allowing Spring to create a schema for you. +A new configuration property named `initialize-schema` has been introduced, with `false` being the default value. +Check the documentation section for your vector store's configuration properties for the full syntax. +The following vector stores have been impacted by this change + +* Azure AI Search +* Chroma +* Elasticsearch +* SAP Hana +* Milvus +* MongoDB +* Neo4j +* PGVector +* Pinecone +* Qdrant +* Redis +* Weaviate + **(22.05.2024)** A major change was made that took the 'old' `ChatClient` and moved the functionality into `ChatModel`. The 'new' `ChatClient` now takes an instance of `ChatModel`. This was done do support a fluent API for creating and executing prompts in a style similar to other client classes in the Spring ecosystem, such as `RestClient`, `WebClient`, and `JdbcClient`. Refer to the [JavaDoc](https://docs.spring.io/spring-ai/docs/1.0.0-SNAPSHOT/api/) for more information on the Fluent API, proper reference documentation is coming shortly. diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingModel.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingModel.java index 66be40c5c..b4f0c1bd2 100644 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingModel.java +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingModel.java @@ -105,13 +105,13 @@ public class OllamaEmbeddingModel extends AbstractEmbeddingModel { List> embeddingList = new ArrayList<>(); for (String inputContent : request.getInstructions()) { - var ollamaEmbeddingRequest = ollamaEmbeddingRequest(inputContent, request.getOptions()); + EmbeddingRequest ollamaEmbeddingRequest = ollamaEmbeddingRequest(inputContent, request.getOptions()); OllamaApi.EmbeddingResponse response = this.ollamaApi.embeddings(ollamaEmbeddingRequest); embeddingList.add(response.embedding()); } - var indexCounter = new AtomicInteger(0); + AtomicInteger indexCounter = new AtomicInteger(0); List embeddings = embeddingList.stream() .map(e -> new Embedding(e, indexCounter.getAndIncrement())) diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingRequestTests.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingRequestTests.java index 82fcab7d7..258d5817e 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingRequestTests.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingRequestTests.java @@ -16,8 +16,6 @@ package org.springframework.ai.ollama; import org.junit.jupiter.api.Test; - -import org.springframework.ai.embedding.EmbeddingOptions; import org.springframework.ai.ollama.api.OllamaApi; import org.springframework.ai.ollama.api.OllamaOptions; @@ -28,7 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class OllamaEmbeddingRequestTests { - OllamaEmbeddingModel chatModel = new OllamaEmbeddingModel(new OllamaApi()).withDefaultOptions( + OllamaEmbeddingModel chatModel = new OllamaEmbeddingModel(new OllamaApi(), new OllamaOptions().withModel("DEFAULT_MODEL").withMainGPU(11).withUseMMap(true).withNumGPU(1)); @Test @@ -46,9 +44,10 @@ public class OllamaEmbeddingRequestTests { @Test public void ollamaEmbeddingRequestRequestOptions() { - EmbeddingOptions promptOptions = new OllamaOptions().withModel("PROMPT_MODEL") - .withMainGPU(22) - .withUseMMap(true) + var promptOptions = new OllamaOptions()// + .withModel("PROMPT_MODEL")// + .withMainGPU(22)// + .withUseMMap(true)// .withNumGPU(2); var request = chatModel.ollamaEmbeddingRequest("Hello", promptOptions); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java index 6bcd64408..8a664e91a 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiRetryTests.java @@ -78,7 +78,7 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class OpenAiRetryTests { - private class TestRetryListener implements RetryListener { + private static class TestRetryListener implements RetryListener { int onErrorRetryCount = 0; diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java index e50fc1b13..564c0fc56 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/ChatMemoryLongTermSystemPromptIT.java @@ -89,7 +89,7 @@ public class ChatMemoryLongTermSystemPromptIT extends BaseMemoryTest { QdrantClient qdrantClient = new QdrantClient(QdrantGrpcClient .newBuilder(qdrantContainer.getHost(), qdrantContainer.getMappedPort(QDRANT_GRPC_PORT), false) .build()); - return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel); + return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true); } @Bean diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java index 1162c9fce..f83b35cae 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/LongShortTermChatMemoryWithRagIT.java @@ -177,7 +177,7 @@ public class LongShortTermChatMemoryWithRagIT { QdrantClient qdrantClient = new QdrantClient(QdrantGrpcClient .newBuilder(qdrantContainer.getHost(), qdrantContainer.getMappedPort(QDRANT_GRPC_PORT), false) .build()); - return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel); + return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true); } @Bean diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java index 348078d2b..5c682a321 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/service/OpenAiPromptTransformingChatServiceIT.java @@ -159,7 +159,7 @@ public class OpenAiPromptTransformingChatServiceIT { QdrantClient qdrantClient = new QdrantClient(QdrantGrpcClient .newBuilder(qdrantContainer.getHost(), qdrantContainer.getMappedPort(QDRANT_GRPC_PORT), false) .build()); - return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel); + return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true); } @Bean diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc index 93539a19d..2dc4d698b 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs.adoc @@ -83,6 +83,13 @@ The `similaritySearch` methods in the interface allow for retrieving documents s Find more information on the `Filter.Expression` in the <> section. +== Schema Initialization + +Some vector stores require their backend schema to be initialized before usage. +It will not be initialized for you by default. +You must opt-in, by passing a `boolean` for the appropriate constructor argument or, if using Spring Boot, setting the appropriate `initialize-schema` property to `true` in `application.properties` or `application.yml`. +Check the documentation for the vector store you are using for the specific property name. + == Available Implementations These are the available implementations of the `VectorStore` interface: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc index 71776e4cf..099777059 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc @@ -15,10 +15,17 @@ SELECT content FROM table ORDER BY content_vector ANN OF query_embedding ; More docs on this can be read https://cassandra.apache.org/doc/latest/cassandra/getting-started/vector-search-quickstart.html[here]. -This Spring AI Vector Store is designed to work for both brand new RAG applications as well as being able to be retrofitted on top of existing data and tables. +This Spring AI Vector Store is designed to work for both brand-new RAG applications and be able to be retrofitted on top of existing data and tables. The store can also be used for non-RAG use-cases in an existing database, e.g. semantic searches, geo-proximity searches, etc. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + + The store will automatically create, or enhance, the schema as needed according to its configuration. If you don't want the schema modifications, configure the store with `disallowSchemaChanges`. == What is JVector ? diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure.adoc index e935e4e64..4c9454a28 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/azure.adoc @@ -12,7 +12,12 @@ link:https://azure.microsoft.com/en-us/products/ai-services/ai-search/[Azure AI == Configuration -On startup, the AzureVectorStore will attempt to create a new index within your AI Search service instance. Alternatively, you can create the index manually. +On startup, the `AzureVectorStore` can attempt to create a new index within your AI Search service instance if you've opted in by setting the relevant `initializeSchema` `boolean` property to `true` in the constructor or, if using Spring Boot, setting `...initialize-schema=true` in your `application.properties` file. + + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + +Alternatively, you can create the index manually. To set up an AzureVectorStore, you will need the settings retrieved from the prerequisites above along with your index name: diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/chroma.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/chroma.adoc index 19d63685a..a6e7793b9 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/chroma.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/chroma.adoc @@ -15,7 +15,7 @@ On startup, the `ChromaVectorStore` creates the required collection if one is no == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the Chroma Vector Sore. +Spring AI provides Spring Boot auto-configuration for the Chroma Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] @@ -39,6 +39,14 @@ TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Man TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + + + Additionally, you will need a configured `EmbeddingModel` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information. Here is an example of the needed bean: @@ -58,6 +66,7 @@ A simple configuration can either be provided via Spring Boot's _application.pro [source,properties] ---- # Chroma Vector Store connection properties +spring.ai.vectorstore.chroma.client.initialize-schema= spring.ai.vectorstore.chroma.client.host= spring.ai.vectorstore.chroma.client.port= spring.ai.vectorstore.chroma.client.key-token= @@ -75,7 +84,7 @@ spring.ai.openai.api.key= Please have a look at the list of xref:#_configuration_properties[configuration parameters] for the vector store to learn about the default values and configuration options. -Now you can Auto-wire the Chroma Vector Store in your application and use it +Now you can auto-wire the Chroma Vector Store in your application and use it [source,java] ---- diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/elasticsearch.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/elasticsearch.adoc index 3c0f4da8d..9fc6a895c 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/elasticsearch.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/elasticsearch.adoc @@ -39,6 +39,14 @@ TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Man TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file. + + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + + Please have a look at the list of <> for the vector store to learn about the default values and configuration options. Additionally, you will need a configured `EmbeddingModel` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information. @@ -128,6 +136,7 @@ Properties starting with the `spring.ai.vectorstore.elasticsearch.*` prefix are |`spring.ai.vectorstore.elasticsearch.dimensions` | The number of dimensions in the vector. | 1536 |`spring.ai.vectorstore.elasticsearch.dense-vector-indexing` | Whether to use dense vector indexing. | true |`spring.ai.vectorstore.elasticsearch.similarity` | The similarity function to use. | `cosine` +|`spring.ai.vectorstore.elasticsearch.initialize-schema`| whether to initialize the required schema | `false` |=== == Metadata Filtering diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc index e31c96bbd..7cebf79e2 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/hana.adoc @@ -8,7 +8,7 @@ == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the SAP Hana Vector Sore. +Spring AI provides Spring Boot auto-configuration for the SAP Hana Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] @@ -50,6 +50,7 @@ It uses `spring.datasource.*` properties to configure the Hana datasource and th |`spring.datasource.password` | Hana datasource password | - |`spring.ai.vectorstore.hanadb.top-k`| TODO | - |`spring.ai.vectorstore.hanadb.table-name`| TODO | - +|`spring.ai.vectorstore.hanadb.initialize-schema`| whether to initialize the required schema | `false` |=== diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/milvus.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/milvus.adoc index ec014670e..8b61e6956 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/milvus.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/milvus.adoc @@ -30,12 +30,21 @@ dependencies { } ---- -The Vector Store, also requires an `EmbeddingModel` instance to calculate embeddings for the documents. -You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingModel Implementations]. 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. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + + +The Vector Store, also requires an `EmbeddingModel` instance to calculate embeddings for the documents. +You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingModel Implementations]. + + To connect to and configure the `MilvusVectorStore`, you need to provide access details for your instance. A simple configuration can either be provided via Spring Boot's `application.yml` @@ -162,6 +171,7 @@ You can use the following properties in your Spring Boot configuration to custom |spring.ai.vectorstore.milvus.database-name | The name of the Milvus database to use. | default |spring.ai.vectorstore.milvus.collection-name | Milvus collection name to store the vectors | vector_store +|spring.ai.vectorstore.milvus.initialize-schema | whether to initialize Milvus' backend | false |spring.ai.vectorstore.milvus.embedding-dimension | The dimension of the vectors to be stored in the Milvus collection. | 1536 |spring.ai.vectorstore.milvus.index-type | The type of the index to be created for the Milvus collection. | IVF_FLAT |spring.ai.vectorstore.milvus.metric-type | The metric type to be used for the Milvus collection. | COSINE diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/mongodb.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/mongodb.adoc index 414ded806..57794b128 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/mongodb.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/mongodb.adoc @@ -10,7 +10,7 @@ TODO: Add prerequisites instructions == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the MongoDB Atlas Vector Sore. +Spring AI provides Spring Boot auto-configuration for the MongoDB Atlas Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] @@ -34,6 +34,16 @@ TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Man TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + + + + + Additionally, you will need a configured `EmbeddingModel` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information. Here is an example of the needed bean: @@ -88,6 +98,7 @@ You can use the following properties in your Spring Boot configuration to custom |Property| Description | Default value |`spring.ai.vectorstore.mongodb.collection-name`| The name of the collection to store the vectors. | `vector_store` +|`spring.ai.vectorstore.mongodb.initialize-schema`| whether to initialize the backend schema for you | `false` |`spring.ai.vectorstore.mongodb.path-name`| The name of the path to store the vectors. | `embedding` |`spring.ai.vectorstore.mongodb.indexName`| The name of the index to store the vectors. | `vector_index` |=== diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc index f39d6f173..873f534d3 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/neo4j.adoc @@ -41,8 +41,16 @@ dependencies { } ---- + + TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + == Configuration To connect to Neo4j and use the `Neo4jVectorStore`, you need to provide access details for your instance. @@ -79,7 +87,7 @@ Spring Boot's auto-configuration feature for the Neo4j Driver will create a bean == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the Neo4j Vector Sore. +Spring AI provides Spring Boot auto-configuration for the Neo4j Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] @@ -185,6 +193,7 @@ You can use the following properties in your Spring Boot configuration to custom |Property|Default value |`spring.ai.vectorstore.neo4j.database-name`|neo4j +|`spring.ai.vectorstore.neo4j.initialize-schema`|false |`spring.ai.vectorstore.neo4j.embedding-dimension`|1536 |`spring.ai.vectorstore.neo4j.distance-type`|cosine |`spring.ai.vectorstore.neo4j.label`|Document diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pgvector.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pgvector.adoc index 44a77421f..8fd9f24c2 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pgvector.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pgvector.adoc @@ -55,6 +55,11 @@ dependencies { } ---- +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + The Vector Store, also requires an `EmbeddingModel` instance to calculate embeddings for the documents. You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingModel Implementations]. @@ -133,6 +138,7 @@ You can use the following properties in your Spring Boot configuration to custom |`spring.ai.vectorstore.pgvector.distance-type`| Search distance type. Defaults to `COSINE_DISTANCE`. But if vectors are normalized to length 1, you can use `EUCLIDEAN_DISTANCE` or `NEGATIVE_INNER_PRODUCT` for best performance.| COSINE_DISTANCE |`spring.ai.vectorstore.pgvector.dimensions`| Embeddings dimension. If not specified explicitly the PgVectorStore will retrieve the dimensions form the provided `EmbeddingModel`. Dimensions are set to the embedding column the on table creation. If you change the dimensions your would have to re-create the vector_store table as well. | - |`spring.ai.vectorstore.pgvector.remove-existing-vector-store-table` | Deletes the existing `vector_store` table on start up. | false +|`spring.ai.vectorstore.pgvector.initialize-schema` | Whether to initialize the required schema | false |=== diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pinecone.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pinecone.adoc index 25e7f5dfd..71d614600 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pinecone.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/pinecone.adoc @@ -26,7 +26,7 @@ This information is available to you in the Pinecone UI portal. == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the Pinecone Vector Sore. +Spring AI provides Spring Boot auto-configuration for the Pinecone Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] 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 899bdc46b..b18aed4d1 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 @@ -35,6 +35,11 @@ dependencies { } ---- +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + The Vector Store, also requires an `EmbeddingModel` instance to calculate embeddings for the documents. You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingModel Implementations]. @@ -110,6 +115,7 @@ You can use the following properties in your Spring Boot configuration to custom |`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 +|`spring.ai.vectorstore.qdrant.initialize-schema`| Whether to initialize the backend schema or not | false |=== == Metadata filtering diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/redis.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/redis.adoc index 2c19ee544..73f934e32 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/redis.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/redis.adoc @@ -21,7 +21,7 @@ link:https://redis.io/docs/interact/search-and-query/[Redis Search and Query] ex == Auto-configuration -Spring AI provides Spring Boot auto-configuration for the Redis Vector Sore. +Spring AI provides Spring Boot auto-configuration for the Redis Vector Store. To enable it, add the following dependency to your project's Maven `pom.xml` file: [source, xml] @@ -45,6 +45,12 @@ TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Man TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section to add Milestone and/or Snapshot Repositories to your build file. + +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + Additionally, you will need a configured `EmbeddingModel` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information. Here is an example of the needed bean: @@ -102,6 +108,7 @@ You can use the following properties in your Spring Boot configuration to custom |`spring.ai.vectorstore.redis.uri`| Server connection URI | `redis://localhost:6379` |`spring.ai.vectorstore.redis.index`| Index name | `default-index` +|`spring.ai.vectorstore.redis.initialize-schema`| whether to initialize the required schema | `false` |`spring.ai.vectorstore.redis.prefix`| Prefix | `default:` |=== 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 6c8280796..edcead796 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 @@ -40,6 +40,11 @@ dependencies { } ---- +The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file. + +NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default. + + The Vector Store, also requires an `EmbeddingModel` instance to calculate embeddings for the documents. You can pick one of the available xref:api/embeddings.adoc#available-implementations[EmbeddingModel Implementations]. @@ -116,6 +121,7 @@ You can use the following properties in your Spring Boot configuration to custom |`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`| | - +|`spring.ai.vectorstore.weaviate.initialize-schema`| Whether to initialize the required schema | `false` |=== == Metadata filtering diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/CommonVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/CommonVectorStoreProperties.java new file mode 100644 index 000000000..b6716c6f2 --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/CommonVectorStoreProperties.java @@ -0,0 +1,18 @@ +package org.springframework.ai.autoconfigure; + +/** + * @author Josh Long + */ +public class CommonVectorStoreProperties { + + private boolean initializeSchema = false; + + public boolean isInitializeSchema() { + return initializeSchema; + } + + public void setInitializeSchema(boolean initializeSchema) { + this.initializeSchema = initializeSchema; + } + +} 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 d18527235..2d086f61e 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 @@ -50,7 +50,7 @@ public class AzureVectorStoreAutoConfiguration { public AzureVectorStore vectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel, AzureVectorStoreProperties properties) { - var vectorStore = new AzureVectorStore(searchIndexClient, embeddingModel); + var vectorStore = new AzureVectorStore(searchIndexClient, embeddingModel, properties.isInitializeSchema()); vectorStore.setIndexName(properties.getIndexName()); diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreProperties.java index 8b21a0db2..d2ad4a8ea 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/azure/AzureVectorStoreProperties.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.autoconfigure.vectorstore.azure; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.azure.AzureVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -22,7 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @author Christian Tzolov */ @ConfigurationProperties(AzureVectorStoreProperties.CONFIG_PREFIX) -public class AzureVectorStoreProperties { +public class AzureVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.azure"; 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 cd3cf9313..8da48c0bb 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 @@ -72,7 +72,8 @@ public class ChromaVectorStoreAutoConfiguration { @ConditionalOnMissingBean public ChromaVectorStore vectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, ChromaVectorStoreProperties storeProperties) { - return new ChromaVectorStore(embeddingModel, chromaApi, storeProperties.getCollectionName()); + return new ChromaVectorStore(embeddingModel, chromaApi, storeProperties.getCollectionName(), + storeProperties.isInitializeSchema()); } private static class PropertiesChromaConnectionDetails implements ChromaConnectionDetails { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreProperties.java index 686beb50a..9b2c8c860 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreProperties.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.autoconfigure.vectorstore.chroma; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.ChromaVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -22,7 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @author Christian Tzolov */ @ConfigurationProperties(ChromaVectorStoreProperties.CONFIG_PREFIX) -public class ChromaVectorStoreProperties { +public class ChromaVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.chroma.store"; 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 460ec67f5..78a8fe0fa 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 @@ -31,6 +31,7 @@ import org.springframework.util.StringUtils; /** * @author Eddú Meléndez * @author Wei Jiang + * @author Josh Long * @since 1.0.0 */ @@ -58,7 +59,8 @@ class ElasticsearchVectorStoreAutoConfiguration { elasticsearchVectorStoreOptions.setSimilarity(properties.getSimilarity()); } - return new ElasticsearchVectorStore(elasticsearchVectorStoreOptions, restClient, embeddingModel); + return new ElasticsearchVectorStore(elasticsearchVectorStoreOptions, restClient, embeddingModel, + properties.isInitializeSchema()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreProperties.java index 7241892b3..67f677f62 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/elasticsearch/ElasticsearchVectorStoreProperties.java @@ -15,15 +15,17 @@ */ package org.springframework.ai.autoconfigure.vectorstore.elasticsearch; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author Eddú Meléndez * @author Wei Jiang + * @author Josh Long * @since 1.0.0 */ @ConfigurationProperties(prefix = "spring.ai.vectorstore.elasticsearch") -public class ElasticsearchVectorStoreProperties { +public class ElasticsearchVectorStoreProperties extends CommonVectorStoreProperties { /** * The name of the index to store the vectors. 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 db325d31a..557d1f358 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 @@ -62,7 +62,7 @@ public class MilvusVectorStoreAutoConfiguration { .withEmbeddingDimension(properties.getEmbeddingDimension()) .build(); - return new MilvusVectorStore(milvusClient, embeddingModel, config); + return new MilvusVectorStore(milvusClient, embeddingModel, config, properties.isInitializeSchema()); } @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreProperties.java index 346197c2a..15a0b0cce 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/milvus/MilvusVectorStoreProperties.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.autoconfigure.vectorstore.milvus; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.MilvusVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.util.Assert; @@ -23,7 +24,7 @@ import org.springframework.util.Assert; * @author Christian Tzolov */ @ConfigurationProperties(MilvusVectorStoreProperties.CONFIG_PREFIX) -public class MilvusVectorStoreProperties { +public class MilvusVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.milvus"; 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 8baabd87f..dfbebca77 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 @@ -54,7 +54,7 @@ public class MongoDBAtlasVectorStoreAutoConfiguration { } MongoDBAtlasVectorStore.MongoDBVectorStoreConfig config = builder.build(); - return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel, config); + return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel, config, properties.isInitializeSchema()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreProperties.java index f9b5b1c51..12c16fdb8 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/mongo/MongoDBAtlasVectorStoreProperties.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.autoconfigure.vectorstore.mongo; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -23,7 +24,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @since 1.0.0 */ @ConfigurationProperties(MongoDBAtlasVectorStoreProperties.CONFIG_PREFIX) -public class MongoDBAtlasVectorStoreProperties { +public class MongoDBAtlasVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.mongodb"; 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 e5abcf5fb..e9dd97b95 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 @@ -28,6 +28,7 @@ import org.springframework.context.annotation.Bean; /** * @author Jingzhou Ou + * @author Josh Long */ @AutoConfiguration(after = Neo4jAutoConfiguration.class) @ConditionalOnClass({ Neo4jVectorStore.class, EmbeddingModel.class, Driver.class }) @@ -49,7 +50,7 @@ public class Neo4jVectorStoreAutoConfiguration { .withConstraintName(properties.getConstraintName()) .build(); - return new Neo4jVectorStore(driver, embeddingModel, config); + return new Neo4jVectorStore(driver, embeddingModel, config, properties.isInitializeSchema()); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreProperties.java index 5b13b56c4..851cd100a 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreProperties.java @@ -15,14 +15,16 @@ */ package org.springframework.ai.autoconfigure.vectorstore.neo4j; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.Neo4jVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author Jingzhou Ou + * @author Josh Long */ @ConfigurationProperties(Neo4jVectorStoreProperties.CONFIG_PREFIX) -public class Neo4jVectorStoreProperties { +public class Neo4jVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.neo4j"; 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 58ff912cf..8ccde1a76 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 @@ -19,6 +19,7 @@ import javax.sql.DataSource; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.PgVectorStore; +import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -29,6 +30,7 @@ import org.springframework.jdbc.core.JdbcTemplate; /** * @author Christian Tzolov + * @author Josh Long */ @AutoConfiguration(after = JdbcTemplateAutoConfiguration.class) @ConditionalOnClass({ PgVectorStore.class, DataSource.class, JdbcTemplate.class }) @@ -39,9 +41,9 @@ public class PgVectorStoreAutoConfiguration { @ConditionalOnMissingBean public PgVectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, PgVectorStoreProperties properties) { - + var initializeSchema = properties.isInitializeSchema(); return new PgVectorStore(jdbcTemplate, embeddingModel, properties.getDimensions(), properties.getDistanceType(), - properties.isRemoveExistingVectorStoreTable(), properties.getIndexType()); + properties.isRemoveExistingVectorStoreTable(), properties.getIndexType(), initializeSchema); } } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreProperties.java index b15e22eac..927a82193 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/pgvector/PgVectorStoreProperties.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.autoconfigure.vectorstore.pgvector; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.PgVectorStore; import org.springframework.ai.vectorstore.PgVectorStore.PgDistanceType; import org.springframework.ai.vectorstore.PgVectorStore.PgIndexType; @@ -24,7 +25,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @author Christian Tzolov */ @ConfigurationProperties(PgVectorStoreProperties.CONFIG_PREFIX) -public class PgVectorStoreProperties { +public class PgVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.pgvector"; 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 5de119d99..004d9042a 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 @@ -58,7 +58,8 @@ public class QdrantVectorStoreAutoConfiguration { @ConditionalOnMissingBean public QdrantVectorStore vectorStore(EmbeddingModel embeddingModel, QdrantVectorStoreProperties properties, QdrantClient qdrantClient) { - return new QdrantVectorStore(qdrantClient, properties.getCollectionName(), embeddingModel); + return new QdrantVectorStore(qdrantClient, properties.getCollectionName(), embeddingModel, + properties.isInitializeSchema()); } static class PropertiesQdrantConnectionDetails implements QdrantConnectionDetails { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java index 585c8f0ab..795be25b8 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/qdrant/QdrantVectorStoreProperties.java @@ -15,15 +15,17 @@ */ package org.springframework.ai.autoconfigure.vectorstore.qdrant; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author Anush Shetty + * @author Josh Long * @since 0.8.1 */ @ConfigurationProperties(QdrantVectorStoreProperties.CONFIG_PREFIX) -public class QdrantVectorStoreProperties { +public class QdrantVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.qdrant"; 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 22df3a02d..bb093f4aa 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 @@ -50,7 +50,7 @@ public class RedisVectorStoreAutoConfiguration { .withPrefix(properties.getPrefix()) .build(); - return new RedisVectorStore(config, embeddingModel); + return new RedisVectorStore(config, embeddingModel, properties.isInitializeSchema()); } private static class PropertiesRedisConnectionDetails implements RedisConnectionDetails { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreProperties.java index 705fd0cb6..8edff4ba0 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/redis/RedisVectorStoreProperties.java @@ -15,13 +15,14 @@ */ package org.springframework.ai.autoconfigure.vectorstore.redis; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author Julien Ruaux */ @ConfigurationProperties(RedisVectorStoreProperties.CONFIG_PREFIX) -public class RedisVectorStoreProperties { +public class RedisVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.redis"; 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 a358ce3dd..18869dda7 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 @@ -72,7 +72,8 @@ public class WeaviateVectorStoreAutoConfiguration { .toList()) .withConsistencyLevel(properties.getConsistencyLevel()); - return new WeaviateVectorStore(configBuilder.build(), embeddingModel, weaviateClient); + return new WeaviateVectorStore(configBuilder.build(), embeddingModel, weaviateClient, + properties.isInitializeSchema()); } static class PropertiesWeaviateConnectionDetails implements WeaviateConnectionDetails { diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreProperties.java index 54bfc73ef..654a22409 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/weaviate/WeaviateVectorStoreProperties.java @@ -17,6 +17,7 @@ package org.springframework.ai.autoconfigure.vectorstore.weaviate; import java.util.Map; +import org.springframework.ai.autoconfigure.CommonVectorStoreProperties; import org.springframework.ai.vectorstore.WeaviateVectorStore.WeaviateVectorStoreConfig; import org.springframework.ai.vectorstore.WeaviateVectorStore.WeaviateVectorStoreConfig.ConsistentLevel; import org.springframework.ai.vectorstore.WeaviateVectorStore.WeaviateVectorStoreConfig.MetadataField; @@ -26,7 +27,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @author Christian Tzolov */ @ConfigurationProperties(WeaviateVectorStoreProperties.CONFIG_PREFIX) -public class WeaviateVectorStoreProperties { +public class WeaviateVectorStoreProperties extends CommonVectorStoreProperties { public static final String CONFIG_PREFIX = "spring.ai.vectorstore.weaviate"; diff --git a/spring-ai-spring-boot-testcontainers/pom.xml b/spring-ai-spring-boot-testcontainers/pom.xml index ca44ac49f..e282291ae 100644 --- a/spring-ai-spring-boot-testcontainers/pom.xml +++ b/spring-ai-spring-boot-testcontainers/pom.xml @@ -151,6 +151,12 @@ org.testcontainers junit-jupiter test + + + com.vaadin.external.google + android-json + + 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 547bcb8eb..970ba14ca 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 @@ -15,13 +15,6 @@ */ package org.springframework.ai.vectorstore.azure; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; import com.azure.core.util.Context; @@ -43,7 +36,6 @@ import com.azure.search.documents.models.VectorSearchOptions; import com.azure.search.documents.models.VectorizedQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.SearchRequest; @@ -54,6 +46,13 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + /** * Uses Azure Cognitive Search as a backing vector store. Documents can be preloaded into * a Cognitive Search index and managed via Azure tools or added and managed through this @@ -63,6 +62,7 @@ import org.springframework.util.StringUtils; * @author Greg Meyer * @author Xiangyang Yu * @author Christian Tzolov + * @author Josh Long */ public class AzureVectorStore implements VectorStore, InitializingBean { @@ -104,12 +104,14 @@ public class AzureVectorStore implements VectorStore, InitializingBean { private String indexName = DEFAULT_INDEX_NAME; + private final boolean initializeSchema; + /** * List of metadata fields (as field name and type) that can be used in similarity * search query filter expressions. The {@link Document#getMetadata()} can contain * arbitrary number of metadata entries, but only the fields listed here can be used * in the search filter expressions. - * + *

* If new entries are added ot the filterMetadataFields the affected documents must be * (re)updated. */ @@ -148,8 +150,9 @@ public class AzureVectorStore implements VectorStore, InitializingBean { * for Azure search indexes and factory for {@link SearchClient}. * @param embeddingModel The client for embedding operations. */ - public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) { - this(searchIndexClient, embeddingModel, List.of()); + public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel, + boolean initializeSchema) { + this(searchIndexClient, embeddingModel, initializeSchema, List.of()); } /** @@ -161,12 +164,13 @@ public class AzureVectorStore implements VectorStore, InitializingBean { * can be used in similarity search query filter expressions. */ public AzureVectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel, - List filterMetadataFields) { + boolean initializeSchema, List filterMetadataFields) { Assert.notNull(embeddingModel, "The embedding model can not be null."); Assert.notNull(searchIndexClient, "The search index client can not be null."); Assert.notNull(filterMetadataFields, "The filterMetadataFields can not be null."); + this.initializeSchema = initializeSchema; this.searchIndexClient = searchIndexClient; this.embeddingModel = embeddingModel; this.filterMetadataFields = filterMetadataFields; @@ -328,6 +332,9 @@ public class AzureVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() throws Exception { + if (!this.initializeSchema) + return; + int dimensions = this.embeddingModel.dimensions(); List fields = new ArrayList<>(); 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 9c09b5879..ce58a246c 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 @@ -305,7 +305,7 @@ public class AzureVectorStoreIT { public VectorStore vectorStore(SearchIndexClient searchIndexClient, EmbeddingModel embeddingModel) { var filterableMetaFields = List.of(MetadataField.text("country"), MetadataField.int64("year"), MetadataField.date("activationDate")); - return new AzureVectorStore(searchIndexClient, embeddingModel, filterableMetaFields); + return new AzureVectorStore(searchIndexClient, embeddingModel, true, filterableMetaFields); } @Bean diff --git a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/CassandraVectorStore.java b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/CassandraVectorStore.java index 3cc2fa220..974c0ab50 100644 --- a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/CassandraVectorStore.java +++ b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/CassandraVectorStore.java @@ -34,7 +34,6 @@ import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.vectorstore.CassandraVectorStoreConfig.SchemaColumn; import org.springframework.ai.vectorstore.filter.FilterExpressionConverter; -import org.springframework.beans.factory.InitializingBean; import java.util.ArrayList; import java.util.HashMap; @@ -89,7 +88,7 @@ import java.util.concurrent.ConcurrentMap; * @see EmbeddingModel * @since 1.0.0 */ -public class CassandraVectorStore implements VectorStore, InitializingBean, AutoCloseable { +public class CassandraVectorStore implements VectorStore, AutoCloseable { /** * Indexes are automatically created with COSINE. This can be changed manually via @@ -246,10 +245,6 @@ public class CassandraVectorStore implements VectorStore, InitializingBean, Auto return documents; } - @Override - public void afterPropertiesSet() { - } - @Override public void close() throws Exception { this.conf.close(); diff --git a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/vectorstore/ChromaVectorStore.java b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/vectorstore/ChromaVectorStore.java index d14d1f8b3..e9bd80eab 100644 --- a/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/vectorstore/ChromaVectorStore.java +++ b/vector-stores/spring-ai-chroma-store/src/main/java/org/springframework/ai/vectorstore/ChromaVectorStore.java @@ -61,14 +61,18 @@ public class ChromaVectorStore implements VectorStore, InitializingBean { private String collectionId; - public ChromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - this(embeddingModel, chromaApi, DEFAULT_COLLECTION_NAME); + private final boolean initializeSchema; + + public ChromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, boolean initializeSchema) { + this(embeddingModel, chromaApi, DEFAULT_COLLECTION_NAME, initializeSchema); } - public ChromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, String collectionName) { + public ChromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi, String collectionName, + boolean initializeSchema) { this.embeddingModel = embeddingModel; this.chromaApi = chromaApi; this.collectionName = collectionName; + this.initializeSchema = initializeSchema; this.filterExpressionConverter = new ChromaFilterExpressionConverter(); } @@ -148,6 +152,10 @@ public class ChromaVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() throws Exception { + + if (!this.initializeSchema) + return; + var collection = this.chromaApi.getCollection(this.collectionName); if (collection == null) { collection = this.chromaApi.createCollection(new ChromaApi.CreateCollectionRequest(this.collectionName)); diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/BasicAuthChromaWhereIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/BasicAuthChromaWhereIT.java index 2d6c13101..460863313 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/BasicAuthChromaWhereIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/BasicAuthChromaWhereIT.java @@ -108,7 +108,7 @@ public class BasicAuthChromaWhereIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection"); + return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection", true); } @Bean diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/ChromaVectorStoreIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/ChromaVectorStoreIT.java index 918a90bdc..c29477f0d 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/ChromaVectorStoreIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/ChromaVectorStoreIT.java @@ -213,7 +213,7 @@ public class ChromaVectorStoreIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection"); + return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection", true); } @Bean diff --git a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/TokenSecuredChromaWhereIT.java b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/TokenSecuredChromaWhereIT.java index 22d08e57b..761ac1fc1 100644 --- a/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/TokenSecuredChromaWhereIT.java +++ b/vector-stores/spring-ai-chroma-store/src/test/java/org/springframework/ai/vectorstore/TokenSecuredChromaWhereIT.java @@ -140,7 +140,7 @@ public class TokenSecuredChromaWhereIT { @Bean public VectorStore chromaVectorStore(EmbeddingModel embeddingModel, ChromaApi chromaApi) { - return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection"); + return new ChromaVectorStore(embeddingModel, chromaApi, "TestCollection", true); } @Bean diff --git a/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/ElasticsearchVectorStore.java b/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/ElasticsearchVectorStore.java index 9954f1828..8f672862c 100644 --- a/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/ElasticsearchVectorStore.java +++ b/vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/ElasticsearchVectorStore.java @@ -68,12 +68,15 @@ public class ElasticsearchVectorStore implements VectorStore, InitializingBean { private String similarityFunction; - public ElasticsearchVectorStore(RestClient restClient, EmbeddingModel embeddingModel) { - this(new ElasticsearchVectorStoreOptions(), restClient, embeddingModel); + private final boolean initializeSchema; + + public ElasticsearchVectorStore(RestClient restClient, EmbeddingModel embeddingModel, boolean initializeSchema) { + this(new ElasticsearchVectorStoreOptions(), restClient, embeddingModel, initializeSchema); } public ElasticsearchVectorStore(ElasticsearchVectorStoreOptions options, RestClient restClient, - EmbeddingModel embeddingModel) { + EmbeddingModel embeddingModel, boolean initializeSchema) { + this.initializeSchema = initializeSchema; Objects.requireNonNull(embeddingModel, "RestClient must not be null"); Objects.requireNonNull(embeddingModel, "EmbeddingModel must not be null"); this.elasticsearchClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper( @@ -220,6 +223,11 @@ public class ElasticsearchVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() { + + if (!this.initializeSchema) { + return; + } + if (!indexExists()) { createIndexMapping(); } diff --git a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/ElasticsearchVectorStoreIT.java b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/ElasticsearchVectorStoreIT.java index 393cfa7e6..350c121c4 100644 --- a/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/ElasticsearchVectorStoreIT.java +++ b/vector-stores/spring-ai-elasticsearch-store/src/test/java/org/springframework/ai/vectorstore/ElasticsearchVectorStoreIT.java @@ -363,7 +363,7 @@ class ElasticsearchVectorStoreIT { public ElasticsearchVectorStore vectorStore(EmbeddingModel embeddingModel) { return new ElasticsearchVectorStore( RestClient.builder(HttpHost.create(elasticsearchContainer.getHttpHostAddress())).build(), - embeddingModel); + embeddingModel, true); } @Bean diff --git a/vector-stores/spring-ai-hanadb-store/src/test/resources/application.properties b/vector-stores/spring-ai-hanadb-store/src/test/resources/application.properties index 5f9e15ec5..faf788a4a 100644 --- a/vector-stores/spring-ai-hanadb-store/src/test/resources/application.properties +++ b/vector-stores/spring-ai-hanadb-store/src/test/resources/application.properties @@ -1,6 +1,8 @@ spring.ai.openai.api-key=${OPENAI_API_KEY} spring.ai.openai.embedding.options.model=text-embedding-ada-002 + + spring.datasource.driver-class-name=com.sap.db.jdbc.Driver spring.datasource.url=${HANA_DATASOURCE_URL} spring.datasource.username=${HANA_DATASOURCE_USERNAME} diff --git a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusVectorStore.java b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusVectorStore.java index 28627048f..8905eaabe 100644 --- a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusVectorStore.java +++ b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusVectorStore.java @@ -96,6 +96,8 @@ public class MilvusVectorStore implements VectorStore, InitializingBean { private final MilvusVectorStoreConfig config; + private final boolean initializeSchema; + /** * Configuration for the Milvus vector store. */ @@ -242,12 +244,14 @@ public class MilvusVectorStore implements VectorStore, InitializingBean { } - public MilvusVectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel) { - this(milvusClient, embeddingModel, MilvusVectorStoreConfig.defaultConfig()); + public MilvusVectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel, + boolean initializeSchema) { + this(milvusClient, embeddingModel, MilvusVectorStoreConfig.defaultConfig(), initializeSchema); } public MilvusVectorStore(MilvusServiceClient milvusClient, EmbeddingModel embeddingModel, - MilvusVectorStoreConfig config) { + MilvusVectorStoreConfig config, boolean initializeSchema) { + this.initializeSchema = initializeSchema; Assert.notNull(milvusClient, "MilvusServiceClient must not be null"); Assert.notNull(milvusClient, "EmbeddingModel must not be null"); @@ -380,6 +384,11 @@ public class MilvusVectorStore implements VectorStore, InitializingBean { // --------------------------------------------------------------------------------- @Override public void afterPropertiesSet() throws Exception { + + if (!this.initializeSchema) { + return; + } + this.createCollection(); } diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusEmbeddingDimensionsTests.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusEmbeddingDimensionsTests.java index a477cc2c8..b6a73bc3d 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusEmbeddingDimensionsTests.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusEmbeddingDimensionsTests.java @@ -51,7 +51,7 @@ public class MilvusEmbeddingDimensionsTests { .withEmbeddingDimension(explicitDimensions) .build(); - var dim = new MilvusVectorStore(milvusClient, embeddingModel, config).embeddingDimensions(); + var dim = new MilvusVectorStore(milvusClient, embeddingModel, config, true).embeddingDimensions(); assertThat(dim).isEqualTo(explicitDimensions); verify(embeddingModel, never()).dimensions(); @@ -63,7 +63,8 @@ public class MilvusEmbeddingDimensionsTests { MilvusVectorStoreConfig config = MilvusVectorStoreConfig.builder().build(); - var dim = new MilvusVectorStore(milvusClient, embeddingModel, config).embeddingDimensions(); + var dim = new MilvusVectorStore(milvusClient, embeddingModel, config ,true) + .embeddingDimensions(); assertThat(dim).isEqualTo(969); @@ -76,7 +77,7 @@ public class MilvusEmbeddingDimensionsTests { when(embeddingModel.dimensions()).thenThrow(new RuntimeException()); var dim = new MilvusVectorStore(milvusClient, embeddingModel, - MilvusVectorStoreConfig.builder().build()) + MilvusVectorStoreConfig.builder().build() ,true) .embeddingDimensions(); assertThat(dim).isEqualTo(MilvusVectorStore.OPENAI_EMBEDDING_DIMENSION_SIZE); diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusVectorStoreIT.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusVectorStoreIT.java index 4a1c00bab..ab340b55f 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusVectorStoreIT.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusVectorStoreIT.java @@ -265,7 +265,7 @@ public class MilvusVectorStoreIT { .withIndexType(IndexType.IVF_FLAT) .withMetricType(metricType) .build(); - return new MilvusVectorStore(milvusClient, embeddingModel, config); + return new MilvusVectorStore(milvusClient, embeddingModel, config, true); } @Bean diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStore.java b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStore.java index de7d8cc06..d3a1e14ff 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStore.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStore.java @@ -64,20 +64,28 @@ public class MongoDBAtlasVectorStore implements VectorStore, InitializingBean { private final MongoDBAtlasFilterExpressionConverter filterExpressionConverter = new MongoDBAtlasFilterExpressionConverter(); - public MongoDBAtlasVectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { - this(mongoTemplate, embeddingModel, MongoDBVectorStoreConfig.defaultConfig()); + private final boolean initializeSchema; + + public MongoDBAtlasVectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel, + boolean initializeSchema) { + this(mongoTemplate, embeddingModel, MongoDBVectorStoreConfig.defaultConfig(), initializeSchema); } public MongoDBAtlasVectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel, - MongoDBVectorStoreConfig config) { + MongoDBVectorStoreConfig config, boolean initializeSchema) { this.mongoTemplate = mongoTemplate; this.embeddingModel = embeddingModel; this.config = config; + this.initializeSchema = initializeSchema; } @Override public void afterPropertiesSet() throws Exception { + if (!this.initializeSchema) { + return; + } + // Create the collection if it does not exist if (!mongoTemplate.collectionExists(this.config.collectionName)) { mongoTemplate.createCollection(this.config.collectionName); diff --git a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java index c19963cdd..e804ff4fd 100644 --- a/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java +++ b/vector-stores/spring-ai-mongodb-atlas-store/src/test/java/org/springframework/ai/vectorstore/MongoDBAtlasVectorStoreIT.java @@ -196,7 +196,8 @@ class MongoDBAtlasVectorStoreIT { return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel, MongoDBAtlasVectorStore.MongoDBVectorStoreConfig.builder() .withMetadataFieldsToFilter(List.of("country", "year")) - .build()); + .build(), + true); } @Bean diff --git a/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/Neo4jVectorStore.java b/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/Neo4jVectorStore.java index b84854b43..1ea0a913a 100644 --- a/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/Neo4jVectorStore.java +++ b/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/Neo4jVectorStore.java @@ -273,7 +273,11 @@ public class Neo4jVectorStore implements VectorStore, InitializingBean { private final Neo4jVectorStoreConfig config; - public Neo4jVectorStore(Driver driver, EmbeddingModel embeddingModel, Neo4jVectorStoreConfig config) { + private final boolean initializeSchema; + + public Neo4jVectorStore(Driver driver, EmbeddingModel embeddingModel, Neo4jVectorStoreConfig config, + boolean initializeSchema) { + this.initializeSchema = initializeSchema; Assert.notNull(driver, "Neo4j driver must not be null"); Assert.notNull(embeddingModel, "Embedding client must not be null"); @@ -351,6 +355,10 @@ public class Neo4jVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() { + if (!this.initializeSchema) { + return; + } + try (var session = this.driver.session(this.config.sessionConfig)) { session diff --git a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/Neo4jVectorStoreIT.java b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/Neo4jVectorStoreIT.java index 34433ef3b..451aa1009 100644 --- a/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/Neo4jVectorStoreIT.java +++ b/vector-stores/spring-ai-neo4j-store/src/test/java/org/springframework/ai/vectorstore/Neo4jVectorStoreIT.java @@ -295,8 +295,8 @@ class Neo4jVectorStoreIT { @Bean public VectorStore vectorStore(Driver driver, EmbeddingModel embeddingModel) { - return new Neo4jVectorStore(driver, embeddingModel, - Neo4jVectorStore.Neo4jVectorStoreConfig.defaultConfig()); + return new Neo4jVectorStore(driver, embeddingModel, Neo4jVectorStore.Neo4jVectorStoreConfig.defaultConfig(), + true); } @Bean diff --git a/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java index e95840e71..77038cea6 100644 --- a/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java +++ b/vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/PgVectorStore.java @@ -49,6 +49,7 @@ import org.springframework.util.StringUtils; * vector index will be auto-created if not available. * * @author Christian Tzolov + * @author Josh Long */ public class PgVectorStore implements VectorStore, InitializingBean { @@ -78,6 +79,8 @@ public class PgVectorStore implements VectorStore, InitializingBean { private PgIndexType createIndexMethod; + private final boolean initializeSchema; + /** * By default, pgvector performs exact nearest neighbor search, which provides perfect * recall. You can add an index to use approximate nearest neighbor search, which @@ -199,16 +202,17 @@ public class PgVectorStore implements VectorStore, InitializingBean { public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { this(jdbcTemplate, embeddingModel, INVALID_EMBEDDING_DIMENSION, PgVectorStore.PgDistanceType.COSINE_DISTANCE, - false, PgIndexType.NONE); + false, PgIndexType.NONE, false); } public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, int dimensions) { this(jdbcTemplate, embeddingModel, dimensions, PgVectorStore.PgDistanceType.COSINE_DISTANCE, false, - PgIndexType.NONE); + PgIndexType.NONE, false); } public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel, int dimensions, - PgDistanceType distanceType, boolean removeExistingVectorStoreTable, PgIndexType createIndexMethod) { + PgDistanceType distanceType, boolean removeExistingVectorStoreTable, PgIndexType createIndexMethod, + boolean initializeSchema) { this.jdbcTemplate = jdbcTemplate; this.embeddingModel = embeddingModel; @@ -216,6 +220,7 @@ public class PgVectorStore implements VectorStore, InitializingBean { this.distanceType = distanceType; this.removeExistingVectorStoreTable = removeExistingVectorStoreTable; this.createIndexMethod = createIndexMethod; + this.initializeSchema = initializeSchema; } public PgDistanceType getDistanceType() { @@ -333,6 +338,11 @@ public class PgVectorStore implements VectorStore, InitializingBean { // --------------------------------------------------------------------------------- @Override public void afterPropertiesSet() throws Exception { + + if (!this.initializeSchema) { + return; + } + // Enable the PGVector, JSONB and UUID support. this.jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS vector"); this.jdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS hstore"); diff --git a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java index ca53406ce..8ac1219ff 100644 --- a/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java +++ b/vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/PgVectorStoreIT.java @@ -308,7 +308,7 @@ public class PgVectorStoreIT { @Bean public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) { return new PgVectorStore(jdbcTemplate, embeddingModel, PgVectorStore.INVALID_EMBEDDING_DIMENSION, - distanceType, true, PgIndexType.HNSW); + distanceType, true, PgIndexType.HNSW, true); } @Bean 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 c8001044c..73f0b29b1 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 @@ -15,24 +15,12 @@ */ package org.springframework.ai.vectorstore.qdrant; -import static io.qdrant.client.PointIdFactory.id; -import static io.qdrant.client.ValueFactory.value; -import static io.qdrant.client.VectorsFactory.vectors; -import static io.qdrant.client.WithPayloadSelectorFactory.enable; - import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; -import org.springframework.ai.document.Document; -import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.vectorstore.SearchRequest; -import org.springframework.ai.vectorstore.VectorStore; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - import io.qdrant.client.QdrantClient; import io.qdrant.client.grpc.Collections.Distance; import io.qdrant.client.grpc.Collections.VectorParams; @@ -43,6 +31,17 @@ import io.qdrant.client.grpc.Points.PointStruct; import io.qdrant.client.grpc.Points.ScoredPoint; import io.qdrant.client.grpc.Points.SearchPoints; import io.qdrant.client.grpc.Points.UpdateStatus; +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.EmbeddingModel; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +import static io.qdrant.client.PointIdFactory.id; +import static io.qdrant.client.ValueFactory.value; +import static io.qdrant.client.VectorsFactory.vectors; +import static io.qdrant.client.WithPayloadSelectorFactory.enable; /** * Qdrant vectorStore implementation. This store supports creating, updating, deleting, @@ -51,6 +50,7 @@ import io.qdrant.client.grpc.Points.UpdateStatus; * @author Anush Shetty * @author Christian Tzolov * @author Eddú Meléndez + * @author Josh Long * @since 0.8.1 */ public class QdrantVectorStore implements VectorStore, InitializingBean { @@ -69,6 +69,8 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { private final QdrantFilterExpressionConverter filterExpressionConverter = new QdrantFilterExpressionConverter(); + private final boolean initializeSchema; + /** * Configuration class for the QdrantVectorStore. * @@ -84,6 +86,7 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { * * @param builder The configuration builder. */ + private QdrantVectorStoreConfig(Builder builder) { this.collectionName = builder.collectionName; } @@ -137,8 +140,9 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { * @deprecated since 1.0.0 in favor of {@link QdrantVectorStore}. */ @Deprecated(since = "1.0.0", forRemoval = true) - public QdrantVectorStore(QdrantClient qdrantClient, QdrantVectorStoreConfig config, EmbeddingModel embeddingModel) { - this(qdrantClient, config.collectionName, embeddingModel); + public QdrantVectorStore(QdrantClient qdrantClient, QdrantVectorStoreConfig config, EmbeddingModel embeddingModel, + boolean initializeSchema) { + this(qdrantClient, config.collectionName, embeddingModel, initializeSchema); } /** @@ -147,11 +151,13 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { * @param collectionName The name of the collection to use in Qdrant. * @param embeddingModel The client for embedding operations. */ - public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel) { + public QdrantVectorStore(QdrantClient qdrantClient, String collectionName, EmbeddingModel embeddingModel, + boolean initializeSchema) { Assert.notNull(qdrantClient, "QdrantClient must not be null"); Assert.notNull(collectionName, "collectionName must not be null"); Assert.notNull(embeddingModel, "EmbeddingModel must not be null"); + this.initializeSchema = initializeSchema; this.embeddingModel = embeddingModel; this.collectionName = collectionName; this.qdrantClient = qdrantClient; @@ -285,6 +291,10 @@ public class QdrantVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() throws Exception { + + if (!this.initializeSchema) + return; + // Create the collection if it does not exist. if (!isCollectionExists()) { var vectorParams = VectorParams.newBuilder() 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 bdad3ff84..f01ae82b6 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 @@ -48,6 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Anush Shetty + * @author Josh Long * @since 0.8.1 */ @Testcontainers @@ -251,7 +252,7 @@ public class QdrantVectorStoreIT { @Bean public VectorStore qdrantVectorStore(EmbeddingModel embeddingModel, QdrantClient qdrantClient) { - return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel); + return new QdrantVectorStore(qdrantClient, COLLECTION_NAME, embeddingModel, true); } @Bean diff --git a/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/RedisVectorStore.java b/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/RedisVectorStore.java index 6680070ec..0dd181a73 100644 --- a/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/RedisVectorStore.java +++ b/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/RedisVectorStore.java @@ -34,7 +34,6 @@ import org.springframework.ai.vectorstore.filter.FilterExpressionConverter; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; - import redis.clients.jedis.JedisPooled; import redis.clients.jedis.Pipeline; import redis.clients.jedis.json.Path2; @@ -246,6 +245,8 @@ public class RedisVectorStore implements VectorStore, InitializingBean { } + private final boolean initializeSchema; + public static final String DEFAULT_URI = "redis://localhost:6379"; public static final String DEFAULT_INDEX_NAME = "spring-ai-index"; @@ -286,10 +287,11 @@ public class RedisVectorStore implements VectorStore, InitializingBean { private FilterExpressionConverter filterExpressionConverter; - public RedisVectorStore(RedisVectorStoreConfig config, EmbeddingModel embeddingModel) { + public RedisVectorStore(RedisVectorStoreConfig config, EmbeddingModel embeddingModel, boolean initializeSchema) { Assert.notNull(config, "Config must not be null"); Assert.notNull(embeddingModel, "Embedding client must not be null"); + this.initializeSchema = initializeSchema; this.jedis = new JedisPooled(config.uri); this.embeddingModel = embeddingModel; @@ -405,6 +407,10 @@ public class RedisVectorStore implements VectorStore, InitializingBean { @Override public void afterPropertiesSet() { + if (!this.initializeSchema) { + return; + } + // If index already exists don't do anything if (this.jedis.ftList().contains(this.config.indexName)) { return; diff --git a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/RedisVectorStoreIT.java b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/RedisVectorStoreIT.java index cce1808a0..735a45176 100644 --- a/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/RedisVectorStoreIT.java +++ b/vector-stores/spring-ai-redis-store/src/test/java/org/springframework/ai/vectorstore/RedisVectorStoreIT.java @@ -250,7 +250,7 @@ class RedisVectorStoreIT { .withURI(redisContainer.getRedisURI()) .withMetadataFields(MetadataField.tag("meta1"), MetadataField.tag("meta2"), MetadataField.tag("country"), MetadataField.numeric("year")) - .build(), embeddingModel); + .build(), embeddingModel, true); } @Bean diff --git a/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java b/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java index 0f73fad8f..f9a7b86b7 100644 --- a/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java +++ b/vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/WeaviateVectorStore.java @@ -61,6 +61,7 @@ import org.springframework.util.StringUtils; * * @author Christian Tzolov * @author Eddú Meléndez + * @author Josh Long */ public class WeaviateVectorStore implements VectorStore, InitializingBean { @@ -280,10 +281,11 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { * @param embeddingModel The client for embedding operations. */ public WeaviateVectorStore(WeaviateVectorStoreConfig vectorStoreConfig, EmbeddingModel embeddingModel, - WeaviateClient weaviateClient) { + WeaviateClient weaviateClient, boolean initializeSchema) { Assert.notNull(vectorStoreConfig, "WeaviateVectorStoreConfig must not be null"); Assert.notNull(embeddingModel, "EmbeddingModel must not be null"); + this.initializeSchema = initializeSchema; this.embeddingModel = embeddingModel; this.consistencyLevel = vectorStoreConfig.consistencyLevel; this.weaviateObjectClass = vectorStoreConfig.weaviateObjectClass; @@ -524,9 +526,15 @@ public class WeaviateVectorStore implements VectorStore, InitializingBean { return doubleList.stream().map(Number::floatValue).toList().toArray(new Float[0]); } + private final boolean initializeSchema; + @Override public void afterPropertiesSet() throws Exception { + if (!this.initializeSchema) { + return; + } + Map metadata = new HashMap<>(); if (!CollectionUtils.isEmpty(this.filterMetadataFields)) { for (MetadataField mf : this.filterMetadataFields) { diff --git a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java index 1cd18ae4c..5d26f3671 100644 --- a/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java +++ b/vector-stores/spring-ai-weaviate-store/src/test/java/org/springframework/ai/vectorstore/WeaviateVectorStoreIT.java @@ -25,9 +25,6 @@ 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; - import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.transformers.TransformersEmbeddingModel; @@ -38,8 +35,17 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.core.io.DefaultResourceLoader; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.weaviate.WeaviateContainer; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -252,9 +258,8 @@ public class WeaviateVectorStoreIT { .withConsistencyLevel(WeaviateVectorStoreConfig.ConsistentLevel.ONE) .build(); - WeaviateVectorStore vectorStore = new WeaviateVectorStore(config, embeddingModel, weaviateClient); + return new WeaviateVectorStore(config, embeddingModel, weaviateClient, true); - return vectorStore; } @Bean