Migrate Cassandra chat memory implementation to its own module

Signed-off-by: Soby Chacko <soby.chacko@broadcom.com>
This commit is contained in:
Soby Chacko
2025-04-01 15:59:22 -04:00
committed by Mark Pollack
parent d45ff8e984
commit f7f00328a1
14 changed files with 185 additions and 12 deletions

View File

@@ -32,7 +32,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-cassandra-store</artifactId>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<version>${project.parent.version}</version>
</dependency>

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2023-2024 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<name>Spring AI Cassandra Chat Memory</name>
<description>Spring AI Cassandra Chat Memory implementation</description>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>java-driver-query-builder</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-test</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>cassandra</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -43,8 +43,6 @@ import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.cassandra.SchemaUtil;
/**
* Configuration for the Cassandra Chat Memory store.
*

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2025-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
import java.time.Duration;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.querybuilder.SchemaBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for working with Cassandra schema.
*
* @author Mick Semb Wever
* @since 1.0.0
*/
public final class SchemaUtil {
private static final Logger logger = LoggerFactory.getLogger(SchemaUtil.class);
private SchemaUtil() {
}
public static void checkSchemaAgreement(CqlSession session) throws IllegalStateException {
if (!session.checkSchemaAgreement()) {
logger.warn("Waiting for cluster schema agreement, sleeping 10s…");
try {
Thread.sleep(Duration.ofSeconds(10).toMillis());
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new IllegalStateException(ex);
}
if (!session.checkSchemaAgreement()) {
logger.error("no cluster schema agreement still, continuing, let's hope this works…");
}
}
}
public static void ensureKeyspaceExists(CqlSession session, String keyspaceName) {
if (session.getMetadata().getKeyspace(keyspaceName).isEmpty()) {
SimpleStatement keyspaceStmt = SchemaBuilder.createKeyspace(keyspaceName)
.ifNotExists()
.withSimpleStrategy(1)
.build();
logger.debug("Executing {}", keyspaceStmt.getQuery());
session.execute(keyspaceStmt);
}
}
}

View File

@@ -26,7 +26,6 @@ import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.ai.cassandra.CassandraImage;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.cassandra;
package org.springframework.ai.chat.memory.cassandra;
import org.testcontainers.utility.DockerImageName;

View File

@@ -40,6 +40,9 @@
<module>spring-ai-rag</module>
<module>advisors/spring-ai-advisors-vector-store</module>
<module>memory/spring-ai-model-chat-memory-neo4j</module>
<module>memory/spring-ai-model-chat-memory-cassandra</module>
<module>auto-configurations/common/spring-ai-autoconfigure-retry</module>
<module>auto-configurations/models/tool/spring-ai-autoconfigure-model-tool</module>
@@ -49,8 +52,6 @@
<module>auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-cassandra</module>
<module>auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-neo4j</module>
<module>memory/spring-ai-model-chat-memory-neo4j</module>
<module>auto-configurations/models/chat/observation/spring-ai-autoconfigure-model-chat-observation</module>
<module>auto-configurations/models/embedding/observation/spring-ai-autoconfigure-model-embedding-observation</module>

View File

@@ -64,7 +64,6 @@ import com.datastax.oss.driver.shaded.guava.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.cassandra.SchemaUtil;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentMetadata;
import org.springframework.ai.embedding.EmbeddingModel;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.cassandra;
package org.springframework.ai.vectorstore.cassandra;
import java.time.Duration;

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ai.vectorstore.cassandra;
import org.testcontainers.utility.DockerImageName;
/**
* @author Thomas Vitale
*/
public final class CassandraImage {
public static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("cassandra:5.0");
private CassandraImage() {
}
}

View File

@@ -42,7 +42,6 @@ import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import org.springframework.ai.cassandra.CassandraImage;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentMetadata;
import org.springframework.ai.embedding.EmbeddingModel;

View File

@@ -38,7 +38,6 @@ import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.ai.cassandra.CassandraImage;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentMetadata;
import org.springframework.ai.embedding.EmbeddingModel;

View File

@@ -32,7 +32,6 @@ import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.ai.cassandra.CassandraImage;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;