Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Example for AstraDB and Cassandra #79

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 63 additions & 0 deletions astradb-examples/pom.xml
@@ -0,0 +1,63 @@
<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>dev.langchain4j</groupId>
<artifactId>langchain4j-examples</artifactId>
<version>0.30.0</version>
</parent>

<artifactId>astradb-examples</artifactId>
<packaging>jar</packaging>
<name>astradb-examples</name>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<langchain.version>0.29.1</langchain.version>

</properties>

<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-astradb</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>

</dependencies>
</project>
3 changes: 3 additions & 0 deletions astradb-examples/src/test/java/AstraDbAssistant.java
@@ -0,0 +1,3 @@
interface AstraDbAssistant {
String answer(String query);
}
113 changes: 113 additions & 0 deletions astradb-examples/src/test/java/AstraDbNaiveRagTestIT.java
@@ -0,0 +1,113 @@
import com.datastax.astra.client.DataAPIClient;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiTokenizer;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.astradb.AstraDbEmbeddingStore;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;

import java.io.File;
import java.nio.file.Path;
import java.util.Objects;

import static com.datastax.astra.client.model.SimilarityMetric.COSINE;
import static com.dtsx.astra.sdk.utils.TestUtils.getAstraToken;
import static dev.langchain4j.data.document.loader.FileSystemDocumentLoader.loadDocument;
import static dev.langchain4j.data.document.splitter.DocumentSplitters.recursive;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_3_5_TURBO;
import static dev.langchain4j.model.openai.OpenAiEmbeddingModelName.TEXT_EMBEDDING_ADA_002;
import static java.time.Duration.ofSeconds;

@Disabled("AstraDB is not available in the CI")
class AstraDbNaiveRagTestIT {

static final String VAR_OPENAI_API_KEY = "OPENAI_API_KEY";
static final String VAR_ASTRA_TOKEN = "ASTRA_DB_APPLICATION_TOKEN";

@Test
@EnabledIfEnvironmentVariable(named = VAR_ASTRA_TOKEN, matches = "Astra.*")
@EnabledIfEnvironmentVariable(named = VAR_OPENAI_API_KEY, matches = "sk.*")
void shouldNaiveRagWithOpenAiAndAstraDbTest() {

// Parsing input file
Path textFile = new File(Objects.requireNonNull(getClass()
.getResource("/story-about-happy-carrot.txt"))
.getFile())
.toPath();

// === INGESTION ===

EmbeddingModel embeddingModel = initEmbeddingModelOpenAi();
EmbeddingStore<TextSegment> embeddingStore = initEmbeddingStoreAstraDb();
EmbeddingStoreIngestor.builder()
.documentSplitter(recursive(100, 10, new OpenAiTokenizer(GPT_3_5_TURBO)))
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build()
.ingest(loadDocument(textFile, new TextDocumentParser()));

// === NAIVE RETRIEVER ===

ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(2)
.minScore(0.5)
.build();

AstraDbAssistant ai = AiServices.builder(AstraDbAssistant.class)
.contentRetriever(contentRetriever)
.chatLanguageModel(initChatLanguageModelOpenAi())
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.build();

String response = ai.answer("What vegetable is Happy?");
Assertions.assertNotNull(response);
}

private ChatLanguageModel initChatLanguageModelOpenAi() {
return OpenAiChatModel.builder()
.apiKey(System.getenv(VAR_OPENAI_API_KEY))
.modelName(GPT_3_5_TURBO)
.temperature(0.7)
.timeout(ofSeconds(15))
.maxRetries(3)
.logResponses(true)
.logRequests(true)
.build();
}

private EmbeddingModel initEmbeddingModelOpenAi() {
return OpenAiEmbeddingModel.builder()
.apiKey(System.getenv(VAR_OPENAI_API_KEY))
.modelName(TEXT_EMBEDDING_ADA_002)
.build();
}

private EmbeddingStore<TextSegment> initEmbeddingStoreAstraDb() {
return new AstraDbEmbeddingStore(
// Astra Db Client
new DataAPIClient(getAstraToken())
// Access the 'admin' part
.getAdmin()
// To create a database if it does not exist
.createDatabase("test_langchain4j")
// Select the created db
.getDatabase()
// And create a collection if it does not exist
.createCollection("story_collection", 1536, COSINE));
}

}
17 changes: 17 additions & 0 deletions astradb-examples/src/test/resources/logback-test.xml
@@ -0,0 +1,17 @@
<configuration scan="true">

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %magenta(%-5level) %cyan(%-20logger) : %msg%n</pattern>
</encoder>
</appender>

<logger name="dev.langchain4j.store.embedding.astradb" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>

<root level="INFO">
<appender-ref ref="STDOUT" />
</root>

</configuration>
28 changes: 28 additions & 0 deletions astradb-examples/src/test/resources/story-about-happy-carrot.txt
@@ -0,0 +1,28 @@
Once upon a time in the town of VeggieVille, there lived a cheerful carrot named Charlie.
Charlie was a radiant carrot, always beaming with joy and positivity.
His vibrant orange skin and lush green top were a sight to behold, but it was his infectious laughter and warm personality that really set him apart.

Charlie had a diverse group of friends, each a vegetable with their own unique characteristics.
There was Bella the blushing beetroot, always ready with a riddle or two; Timmy the timid tomato, a gentle soul with a heart of gold; and Percy the prankster potato, whose jokes always brought a smile to everyone's faces.
Despite their differences, they shared a close bond, their friendship as robust as their natural goodness.

Their lives were filled with delightful adventures, from playing hide-and-seek amidst the leafy lettuce to swimming in the dewy droplets that pooled on the cabbage leaves.
Their favorite place, though, was the sunlit corner of the vegetable patch, where they would bask in the warmth of the sun, share stories, and have hearty laughs.

One day, a bunch of pesky caterpillars invaded VeggieVille.
The vegetables were terrified, fearing they would be nibbled to nothingness.
But Charlie, with his usual sunny disposition, had an idea.
He proposed they host a grand feast for the caterpillars, with the juiciest leaves from the outskirts of the town.
Charlie's optimism was contagious, and his friends eagerly joined in to prepare the feast.

When the caterpillars arrived, they were pleasantly surprised.
They enjoyed the feast and were so impressed with the vegetables' hospitality that they promised not to trouble VeggieVille again.
In return, they agreed to help pollinate the flowers, contributing to a more lush and vibrant VeggieVille.

Charlie's idea had saved the day, but he humbly attributed the success to their teamwork and friendship.
They celebrated their victory with a grand party, filled with laughter, dance, and merry games.
That night, under the twinkling stars, they made a pact to always stand by each other, come what may.

From then on, the story of the happy carrot and his friends spread far and wide, a tale of friendship, unity, and positivity.
Charlie, Bella, Timmy, and Percy continued to live their joyful lives, their laughter echoing through VeggieVille.
And so, the tale of the happy carrot and his friends serves as a reminder that no matter the challenge, with optimism, teamwork, and a bit of creativity, anything is possible.
80 changes: 80 additions & 0 deletions cassandra-examples/pom.xml
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<artifactId>cassandra-example</artifactId>

<parent>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-examples</artifactId>
<version>0.30.0</version>
</parent>


<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<langchain.version>0.29.1</langchain.version>
<testcontainers.version>1.19.7</testcontainers.version>
</properties>

<dependencies>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-cassandra</artifactId>
<version>${langchain.version}</version>
</dependency>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>cassandra</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>

</dependencies>

</project>
3 changes: 3 additions & 0 deletions cassandra-examples/src/test/java/CassandraAssistant.java
@@ -0,0 +1,3 @@
interface CassandraAssistant {
String answer(String query);
}