Add property to initialize schema for vector stores
* Default is fale * Update docs
This commit is contained in:
21
README.md
21
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.
|
||||
|
||||
@@ -105,13 +105,13 @@ public class OllamaEmbeddingModel extends AbstractEmbeddingModel {
|
||||
List<List<Double>> 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<Embedding> embeddings = embeddingList.stream()
|
||||
.map(e -> new Embedding(e, indexCounter.getAndIncrement()))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -83,6 +83,13 @@ The `similaritySearch` methods in the interface allow for retrieving documents s
|
||||
|
||||
Find more information on the `Filter.Expression` in the <<metadata-filters>> 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:
|
||||
|
||||
@@ -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 ?
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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=<true or false>
|
||||
spring.ai.vectorstore.chroma.client.host=<your Chroma instance host>
|
||||
spring.ai.vectorstore.chroma.client.port=<your Chroma instance port>
|
||||
spring.ai.vectorstore.chroma.client.key-token=<your access token (if configure)>
|
||||
@@ -75,7 +84,7 @@ spring.ai.openai.api.key=<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]
|
||||
----
|
||||
|
||||
@@ -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 <<elasticsearchvector-properties,configuration parameters>> 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
|
||||
|
||||
@@ -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`
|
||||
|
||||
|===
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|===
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|===
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:`
|
||||
|
||||
|===
|
||||
|
||||
@@ -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.<field-name>=<field-type> | -
|
||||
|`spring.ai.vectorstore.weaviate.headers`| | -
|
||||
|`spring.ai.vectorstore.weaviate.initialize-schema`| Whether to initialize the required schema | `false`
|
||||
|===
|
||||
|
||||
== Metadata filtering
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -151,6 +151,12 @@
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.vaadin.external.google</groupId>
|
||||
<artifactId>android-json</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>
|
||||
* 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<MetadataField> filterMetadataFields) {
|
||||
boolean initializeSchema, List<MetadataField> 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<SearchField> fields = new ArrayList<>();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -196,7 +196,8 @@ class MongoDBAtlasVectorStoreIT {
|
||||
return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel,
|
||||
MongoDBAtlasVectorStore.MongoDBVectorStoreConfig.builder()
|
||||
.withMetadataFieldsToFilter(List.of("country", "year"))
|
||||
.build());
|
||||
.build(),
|
||||
true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<String, Object> metadata = new HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(this.filterMetadataFields)) {
|
||||
for (MetadataField mf : this.filterMetadataFields) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user