diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java index 6bc5f793551..3f7edb778c2 100644 --- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java +++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java @@ -74,8 +74,7 @@ public CassandraVectorStore vectorStore(EmbeddingModel embeddingModel, Cassandra .embeddingColumnName(properties.getEmbeddingColumnName()) .indexName(properties.getIndexName()) .fixedThreadPoolExecutorSize(properties.getFixedThreadPoolExecutorSize()) - .disallowSchemaChanges(!properties.isInitializeSchema()) - .returnEmbeddings(properties.getReturnEmbeddings()) + .initializeSchema(properties.isInitializeSchema()) .observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)) .customObservationConvention(customObservationConvention.getIfAvailable(() -> null)) .batchingStrategy(batchingStrategy) diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreProperties.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreProperties.java index a9c960f07ac..a76d939d19d 100644 --- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreProperties.java +++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreProperties.java @@ -16,9 +16,6 @@ package org.springframework.ai.vectorstore.cassandra.autoconfigure; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.springframework.ai.vectorstore.cassandra.CassandraVectorStore; import org.springframework.ai.vectorstore.properties.CommonVectorStoreProperties; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -35,8 +32,6 @@ public class CassandraVectorStoreProperties extends CommonVectorStoreProperties public static final String CONFIG_PREFIX = "spring.ai.vectorstore.cassandra"; - private static final Logger logger = LoggerFactory.getLogger(CassandraVectorStoreProperties.class); - private String keyspace = CassandraVectorStore.DEFAULT_KEYSPACE_NAME; private String table = CassandraVectorStore.DEFAULT_TABLE_NAME; @@ -47,8 +42,6 @@ public class CassandraVectorStoreProperties extends CommonVectorStoreProperties private String embeddingColumnName = CassandraVectorStore.DEFAULT_EMBEDDING_COLUMN_NAME; - private boolean returnEmbeddings = false; - private int fixedThreadPoolExecutorSize = CassandraVectorStore.DEFAULT_ADD_CONCURRENCY; public String getKeyspace() { @@ -91,14 +84,6 @@ public void setEmbeddingColumnName(String embeddingColumnName) { this.embeddingColumnName = embeddingColumnName; } - public boolean getReturnEmbeddings() { - return this.returnEmbeddings; - } - - public void setReturnEmbeddings(boolean returnEmbeddings) { - this.returnEmbeddings = returnEmbeddings; - } - public int getFixedThreadPoolExecutorSize() { return this.fixedThreadPoolExecutorSize; } 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 1a1c8f3196a..19511f82e2f 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 @@ -20,9 +20,9 @@ This Spring AI Vector Store is designed to work for both brand-new RAG applicati The store can also be used for non-RAG use-cases in an existing database, e.g. semantic searches, geo-proximity searches, etc. -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`. +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 `initializeSchema`. -When using spring-boot-autoconfigure `disallowSchemaChanges` defaults to true, per Spring Boot standards, and you must opt-in to schema creation/modifications by setting `...initialize-schema=true` in the `application.properties` file. +When using spring-boot-autoconfigure `initializeSchema` defaults to `false`, per Spring Boot standards, and you must opt-in to schema creation/modifications by setting `...initialize-schema=true` in the `application.properties` file. == What is JVector? @@ -167,7 +167,7 @@ public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel // Performance tuning .fixedThreadPoolExecutorSize(32) // Schema management - .disallowSchemaChanges(false) + .initializeSchema(true) // Custom batching strategy .batchingStrategy(new TokenCountBatchingStrategy()) .build(); @@ -282,7 +282,7 @@ public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel .contentColumnName("body") .embeddingColumnName("all_minilm_l6_v2_embedding") .indexName("all_minilm_l6_v2_ann") - .disallowSchemaChanges(true) + .initializeSchema(false) .addMetadataColumns(extraColumns) .primaryKeyTranslator((List primaryKeys) -> { if (primaryKeys.isEmpty()) { diff --git a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java index d5425247b5c..f6d8ad47561 100644 --- a/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java +++ b/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java @@ -95,7 +95,7 @@ * * A schema matching the configuration is automatically created if it doesn't exist. * Missing columns and indexes in existing tables will also be automatically created. - * Disable this with the CassandraBuilder#disallowSchemaChanges(). + * Disable this with the CassandraBuilder#initializeSchema(boolean) method(). * *

* Basic usage example: @@ -139,7 +139,7 @@ * .contentColumnName("text") * .embeddingColumnName("vector") * .fixedThreadPoolExecutorSize(32) - * .disallowSchemaChanges(false) + * .initializeSchema(true) * .batchingStrategy(new TokenCountBatchingStrategy()) * .build(); * } @@ -202,7 +202,7 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme private final Schema schema; - private final boolean disallowSchemaChanges; + private final boolean initializeSchema; private final FilterExpressionConverter filterExpressionConverter; @@ -229,7 +229,7 @@ protected CassandraVectorStore(Builder builder) { this.session = builder.session; this.schema = builder.buildSchema(); - this.disallowSchemaChanges = builder.disallowSchemaChanges; + this.initializeSchema = builder.initializeSchema; this.documentIdTranslator = builder.documentIdTranslator; this.primaryKeyTranslator = builder.primaryKeyTranslator; this.executor = Executors.newFixedThreadPool(builder.fixedThreadPoolExecutorSize); @@ -525,7 +525,7 @@ static void dropKeyspace(Builder builder) { } void ensureSchemaExists(int vectorDimension) { - if (!this.disallowSchemaChanges) { + if (this.initializeSchema) { SchemaUtil.ensureKeyspaceExists(this.session, this.schema.keyspace); ensureTableExists(vectorDimension); ensureTableColumnsExist(vectorDimension); @@ -805,7 +805,7 @@ public static class Builder extends AbstractVectorStoreBuilder { private Set metadataColumns = new HashSet<>(); - private boolean disallowSchemaChanges = false; + private boolean initializeSchema = true; private int fixedThreadPoolExecutorSize = DEFAULT_ADD_CONCURRENCY; @@ -821,8 +821,6 @@ public static class Builder extends AbstractVectorStoreBuilder { return (String) primaryKeyColumns.get(0); }; - private boolean returnEmbeddings = false; - private Builder(EmbeddingModel embeddingModel) { super(embeddingModel); } @@ -938,12 +936,12 @@ public Builder indexName(String indexName) { } /** - * Sets whether to disallow schema changes. - * @param disallowSchemaChanges true to disallow schema changes + * Sets whether to initialize the schema. + * @param initializeSchema true to initialize schema, false otherwise * @return the builder instance */ - public Builder disallowSchemaChanges(boolean disallowSchemaChanges) { - this.disallowSchemaChanges = disallowSchemaChanges; + public Builder initializeSchema(boolean initializeSchema) { + this.initializeSchema = initializeSchema; return this; } @@ -1016,11 +1014,6 @@ public Builder primaryKeyTranslator(PrimaryKeyTranslator translator) { return this; } - public Builder returnEmbeddings(boolean returnEmbeddings) { - this.returnEmbeddings = true; - return this; - } - Schema buildSchema() { if (this.indexName == null) { this.indexName = String.format("%s_%s_%s", this.table, this.embeddingColumnName, DEFAULT_INDEX_SUFFIX); diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java index cf48d57dec3..34e89227142 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java @@ -150,7 +150,7 @@ static CassandraVectorStore.Builder storeBuilder(ApplicationContext context, @Test void ensureSchemaCreation() { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { Assertions.assertNotNull(store); store.checkSchemaValid(); store.similaritySearch(SearchRequest.builder().query("1843").topK(1).build()); @@ -162,7 +162,7 @@ void ensureSchemaCreation() { void ensureSchemaNoCreation() { this.contextRunner.run(context -> { executeCqlFile(context, "test_wiki_full_schema.cql"); - var builder = createBuilder(context, List.of(), true, false); + var builder = createBuilder(context, List.of(), false, false); Assertions.assertNotNull(builder); var store = new CassandraVectorStore(builder); try { @@ -176,7 +176,7 @@ void ensureSchemaNoCreation() { // IllegalStateException: column all_minilm_l6_v2_embedding does not exist IllegalStateException ise = Assertions.assertThrows(IllegalStateException.class, - () -> createStore(context, List.of(), true, false)); + () -> createStore(context, List.of(), false, false)); Assertions.assertEquals("column all_minilm_l6_v2_embedding does not exist", ise.getMessage()); } @@ -193,7 +193,7 @@ void ensureSchemaPartialCreation() { int PARTIAL_FILES = 5; for (int i = 0; i < PARTIAL_FILES; ++i) { executeCqlFile(context, java.lang.String.format("test_wiki_partial_%d_schema.cql", i)); - var builder = createBuilder(context, List.of(), false, false); + var builder = createBuilder(context, List.of(), true, false); Assertions.assertNotNull(builder); CassandraVectorStore.dropKeyspace(builder); var store = builder.build(); @@ -216,7 +216,7 @@ void ensureSchemaPartialCreation() { @Test void addAndSearch() { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List results = store.similaritySearch( @@ -290,7 +290,7 @@ void addAndSearchPoormansBench() { @Test void searchWithPartitionFilter() throws InterruptedException { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List results = store @@ -346,7 +346,7 @@ void searchWithPartitionFilter() throws InterruptedException { @Test void unsearchableFilters() throws InterruptedException { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List results = store @@ -367,7 +367,7 @@ void unsearchableFilters() throws InterruptedException { @Test void searchWithFilters() throws InterruptedException { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List results = store @@ -447,7 +447,7 @@ void searchWithFilterOnPrimaryKeys() throws InterruptedException { new SchemaColumn("title", DataTypes.TEXT, CassandraVectorStore.SchemaColumnTags.INDEXED), new SchemaColumn("chunk_no", DataTypes.INT, CassandraVectorStore.SchemaColumnTags.INDEXED)); - try (CassandraVectorStore store = createStore(context, overrides, false, true)) { + try (CassandraVectorStore store = createStore(context, overrides, true, true)) { store.add(documents); @@ -481,7 +481,7 @@ void searchWithFilterOnPrimaryKeys() throws InterruptedException { @Test void documentUpdate() { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List results = store @@ -532,7 +532,7 @@ void documentUpdate() { @Test void searchWithThreshold() { this.contextRunner.run(context -> { - try (CassandraVectorStore store = createStore(context, false)) { + try (CassandraVectorStore store = createStore(context, true)) { store.add(documents); List fullResult = store.similaritySearch( @@ -562,19 +562,16 @@ void searchWithThreshold() { }); } - private CassandraVectorStore createStore(ApplicationContext context, boolean disallowSchemaCreation) - throws IOException { + private CassandraVectorStore createStore(ApplicationContext context, boolean initializeSchema) throws IOException { - return createStore(context, List.of(), disallowSchemaCreation, true); + return createStore(context, List.of(), initializeSchema, true); } private CassandraVectorStore createStore(ApplicationContext context, List columnOverrides, - boolean disallowSchemaCreation, boolean dropKeyspaceFirst) throws IOException { + boolean initializeSchema, boolean dropKeyspaceFirst) throws IOException { CassandraVectorStore.Builder builder = storeBuilder(context, columnOverrides); - if (disallowSchemaCreation) { - builder = builder.disallowSchemaChanges(true); - } + builder.initializeSchema(initializeSchema); if (dropKeyspaceFirst) { CassandraVectorStore.dropKeyspace(builder); @@ -584,12 +581,10 @@ private CassandraVectorStore createStore(ApplicationContext context, List columnOverrides, - boolean disallowSchemaCreation, boolean dropKeyspaceFirst) throws IOException { + boolean initailzeSchema, boolean dropKeyspaceFirst) throws IOException { CassandraVectorStore.Builder builder = storeBuilder(context, columnOverrides); - if (disallowSchemaCreation) { - builder = builder.disallowSchemaChanges(true); - } + builder.initializeSchema(initailzeSchema); if (dropKeyspaceFirst) { CassandraVectorStore.dropKeyspace(builder); diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java index 6070a6b1590..26327e81d7f 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java @@ -172,39 +172,6 @@ void addAndSearch() { }); } - @Test - void addAndSearchReturnEmbeddings() { - this.contextRunner.run(context -> { - CassandraVectorStore.Builder builder = storeBuilder(context.getBean(CqlSession.class), - context.getBean(EmbeddingModel.class)) - .returnEmbeddings(true); - - try (CassandraVectorStore store = createTestStore(context, builder)) { - List documents = documents(); - store.add(documents); - - List results = store - .similaritySearch(SearchRequest.builder().query("Spring").topK(1).build()); - - assertThat(results).hasSize(1); - Document resultDoc = results.get(0); - assertThat(resultDoc.getId()).isEqualTo(documents().get(0).getId()); - - assertThat(resultDoc.getText()).contains( - "Spring AI provides abstractions that serve as the foundation for developing AI applications."); - - assertThat(resultDoc.getMetadata()).hasSize(1); - assertThat(resultDoc.getMetadata()).containsKey(DocumentMetadata.DISTANCE.value()); - - // Remove all documents from the store - store.delete(documents().stream().map(doc -> doc.getId()).toList()); - - results = store.similaritySearch(SearchRequest.builder().query("Spring").topK(1).build()); - assertThat(results).isEmpty(); - } - }); - } - @Test void searchWithPartitionFilter() throws InterruptedException { this.contextRunner.run(context -> { diff --git a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java index a3e8fdab149..415b95b7e97 100644 --- a/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java +++ b/vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java @@ -102,7 +102,7 @@ public CassandraVectorStore store(CqlSession cqlSession, EmbeddingModel embeddin .contentColumnName("body") .embeddingColumnName("all_minilm_l6_v2_embedding") .indexName("all_minilm_l6_v2_ann") - .disallowSchemaChanges(true) + .initializeSchema(false) .addMetadataColumns(extraColumns) .primaryKeyTranslator((List primaryKeys) -> { // the deliminator used to join fields together into the document's id