Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<module>helidon-examples</module>
<module>payara-micro-example</module>
<module>watsonx-ai-examples</module>
<module>yugabytedb-example</module>
</modules>

</project>
46 changes: 46 additions & 0 deletions yugabytedb-example/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?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>

<groupId>dev.langchain4j</groupId>
<artifactId>yugabytedb-example</artifactId>
<version>1.8.0-beta15-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-yugabytedb</artifactId>
<version>1.8.0-beta15-SNAPSHOT</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please update the version to the non-SNAPSHOT one. If it is not released yet, then this PR will be merged after the release

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I've created yugabyteDB as embedding store in community repo.

Link: yugabyte/langchain4j-community@90c2f0f

Here I've used this version: 1.8.0-beta15-SNAPSHOT

What should I do to progress from this point?

Thanks

</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.19.7</version>
</dependency>

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>1.7.1-beta14</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.12</version>
</dependency>

</dependencies>

</project>

23 changes: 23 additions & 0 deletions yugabytedb-example/run-example.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

# Run YugabyteDB examples as standalone applications
# This avoids exec:java classloader issues with Testcontainers

set -e

EXAMPLE_CLASS=${1:-YugabyteDBEmbeddingStoreExample}

echo "🚀 Building project..."
../mvnw clean compile -q

echo "📦 Running example: $EXAMPLE_CLASS"
echo ""

# Run with proper classpath
../mvnw exec:exec -Dexec.executable="java" \
-Dexec.args="-cp %classpath $EXAMPLE_CLASS" \
-q

echo ""
echo "✅ Example execution completed!"

104 changes: 104 additions & 0 deletions yugabytedb-example/src/main/java/YugabyteDBEmbeddingStoreExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import dev.langchain4j.community.store.embedding.yugabytedb.YugabyteDBEmbeddingStore;
import dev.langchain4j.community.store.embedding.yugabytedb.YugabyteDBEngine;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingStore;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.List;

public class YugabyteDBEmbeddingStoreExample {

public static void main(String[] args) {
GenericContainer<?> yugabyteContainer = null;
YugabyteDBEngine engine = null;

try {
DockerImageName dockerImageName = DockerImageName.parse("yugabytedb/yugabyte:2025.1.0.1-b3");
yugabyteContainer = new GenericContainer<>(dockerImageName)
.withExposedPorts(5433, 7000, 9000, 15433, 9042)
.withCommand("bin/yugabyted", "start", "--background=false")
.waitingFor(Wait.forListeningPorts(5433).withStartupTimeout(Duration.ofMinutes(5)));

yugabyteContainer.start();

EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();

// Create YugabyteDB engine with PostgreSQL driver
engine = YugabyteDBEngine.builder()
.host(yugabyteContainer.getHost())
.port(yugabyteContainer.getMappedPort(5433))
.database("yugabyte")
.username("yugabyte")
.password("yugabyte")
.usePostgreSQLDriver(true) // Use PostgreSQL JDBC driver
.build();

EmbeddingStore<TextSegment> embeddingStore = YugabyteDBEmbeddingStore.builder()
.engine(engine)
.tableName("test_embeddings")
.dimension(embeddingModel.dimension())
.createTableIfNotExists(true)
.build();

TextSegment segment1 = TextSegment.from("I like football.");
Embedding embedding1 = embeddingModel.embed(segment1).content();
embeddingStore.add(embedding1, segment1);

TextSegment segment2 = TextSegment.from("The weather is good today.");
Embedding embedding2 = embeddingModel.embed(segment2).content();
embeddingStore.add(embedding2, segment2);

Embedding queryEmbedding = embeddingModel.embed("What is your favourite sport?").content();

EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(1)
.build();

List<EmbeddingMatch<TextSegment>> relevant = embeddingStore.search(embeddingSearchRequest).matches();

EmbeddingMatch<TextSegment> embeddingMatch = relevant.get(0);

System.out.println(embeddingMatch.score()); // ~0.8144
System.out.println(embeddingMatch.embedded().text()); // I like football.

System.out.println("\n✅ Example completed successfully!");

} catch (Exception e) {
System.err.println("❌ Error running example: " + e.getMessage());
e.printStackTrace();
} finally {
// Give Testcontainers time to cleanup gracefully
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}

// Cleanup resources
System.out.println("🧹 Cleaning up resources...");
if (engine != null) {
try {
engine.close();
} catch (Exception e) {
System.err.println("Error closing engine: " + e.getMessage());
}
}
if (yugabyteContainer != null) {
try {
yugabyteContainer.stop();
} catch (Exception e) {
System.err.println("Error stopping container: " + e.getMessage());
}
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import dev.langchain4j.community.store.embedding.yugabytedb.DefaultMetadataStorageConfig;
import dev.langchain4j.community.store.embedding.yugabytedb.MetadataStorageConfig;
import dev.langchain4j.community.store.embedding.yugabytedb.MetadataStorageMode;
import dev.langchain4j.community.store.embedding.yugabytedb.YugabyteDBEmbeddingStore;
import dev.langchain4j.community.store.embedding.yugabytedb.YugabyteDBEngine;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.filter.Filter;
import dev.langchain4j.store.embedding.filter.comparison.IsEqualTo;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.List;

public class YugabyteDBEmbeddingStoreWithMetadataExample {

public static void main(String[] args) {
GenericContainer<?> yugabyteContainer = null;
YugabyteDBEngine engine = null;

try {
DockerImageName dockerImageName = DockerImageName.parse("yugabytedb/yugabyte:2025.1.0.1-b3");
yugabyteContainer = new GenericContainer<>(dockerImageName)
.withExposedPorts(5433, 7000, 9000, 15433, 9042)
.withCommand("bin/yugabyted", "start", "--background=false")
.waitingFor(Wait.forListeningPorts(5433).withStartupTimeout(Duration.ofMinutes(5)));

yugabyteContainer.start();

EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();

// Create YugabyteDB engine with PostgreSQL driver
engine = YugabyteDBEngine.builder()
.host(yugabyteContainer.getHost())
.port(yugabyteContainer.getMappedPort(5433))
.database("yugabyte")
.username("yugabyte")
.password("yugabyte")
.usePostgreSQLDriver(true)
.build();

// Configure metadata storage (JSONB format)
MetadataStorageConfig metadataConfig = DefaultMetadataStorageConfig.builder()
.storageMode(MetadataStorageMode.COMBINED_JSONB)
.build();

EmbeddingStore<TextSegment> embeddingStore = YugabyteDBEmbeddingStore.builder()
.engine(engine)
.tableName("test_embeddings_with_metadata")
.dimension(embeddingModel.dimension())
.metadataStorageConfig(metadataConfig)
.createTableIfNotExists(true)
.build();

// Add embeddings with metadata
TextSegment segment1 = TextSegment.from("I like football.",
Metadata.from("category", "sports").put("user", "john"));
Embedding embedding1 = embeddingModel.embed(segment1).content();
embeddingStore.add(embedding1, segment1);

TextSegment segment2 = TextSegment.from("The weather is good today.",
Metadata.from("category", "weather").put("user", "alice"));
Embedding embedding2 = embeddingModel.embed(segment2).content();
embeddingStore.add(embedding2, segment2);

TextSegment segment3 = TextSegment.from("I love basketball.",
Metadata.from("category", "sports").put("user", "bob"));
Embedding embedding3 = embeddingModel.embed(segment3).content();
embeddingStore.add(embedding3, segment3);

// Search with metadata filter
Embedding queryEmbedding = embeddingModel.embed("What sport do you like?").content();

Filter categoryFilter = new IsEqualTo("category", "sports");

EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(5)
.filter(categoryFilter)
.build();

List<EmbeddingMatch<TextSegment>> relevant = embeddingStore.search(searchRequest).matches();

System.out.println("Found " + relevant.size() + " sports-related results:");
for (EmbeddingMatch<TextSegment> match : relevant) {
System.out.println("Score: " + match.score());
System.out.println("Text: " + match.embedded().text());
System.out.println("Metadata: " + match.embedded().metadata());
System.out.println("---");
}

System.out.println("\n✅ Example completed successfully!");

} catch (Exception e) {
System.err.println("❌ Error running example: " + e.getMessage());
e.printStackTrace();
} finally {
// Give Testcontainers time to cleanup gracefully
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}

// Cleanup resources
System.out.println("🧹 Cleaning up resources...");
if (engine != null) {
try {
engine.close();
} catch (Exception e) {
System.err.println("Error closing engine: " + e.getMessage());
}
}
if (yugabyteContainer != null) {
try {
yugabyteContainer.stop();
} catch (Exception e) {
System.err.println("Error stopping container: " + e.getMessage());
}
}
}
}
}

Loading