diff --git a/build.sh b/build.sh
new file mode 100644
index 00000000..264cdabf
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+export JDK21_HOME=/usr/local/opt/openjdk/libexec/openjdk.jdk/Contents/Home
+#export JDK17_HOME=/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
+#export JDK11_HOME=/usr/local/opt/openjdk@11/libexec/openjdk.jdk/Contents/Home
+#export JDK8_HOME=/usr/local/opt/openjdk@8/libexec/openjdk.jdk/Contents/Home
+
+export JAVA_HOME=$JDK21_HOME
+mvn install -DskipTests -Denforcer.skip=true
diff --git a/elasticsearch-example/pom.xml b/elasticsearch-example/pom.xml
index d293ae5f..011de589 100644
--- a/elasticsearch-example/pom.xml
+++ b/elasticsearch-example/pom.xml
@@ -12,6 +12,7 @@
8
8
UTF-8
+ 2.22.1
@@ -34,6 +35,23 @@
1.19.6
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j.version}
+
+
+
+ org.testcontainers
+ elasticsearch
+ 1.19.4
+
\ No newline at end of file
diff --git a/elasticsearch-example/src/main/java/ElasticsearchEmbeddingStoreExample.java b/elasticsearch-example/src/main/java/ElasticsearchEmbeddingStoreExample.java
index 822e933f..ed695b65 100644
--- a/elasticsearch-example/src/main/java/ElasticsearchEmbeddingStoreExample.java
+++ b/elasticsearch-example/src/main/java/ElasticsearchEmbeddingStoreExample.java
@@ -5,20 +5,37 @@
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.elasticsearch.ElasticsearchEmbeddingStore;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
-
+import org.testcontainers.utility.DockerImageName;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
public class ElasticsearchEmbeddingStoreExample {
+ private static final Logger LOGGER = LogManager.getLogger(ElasticsearchEmbeddingStoreExample.class);
+
+ /**
+ * To run this example, ensure you have Elasticsearch running locally. If not, then:
+ * - Execute "docker pull docker.elastic.co/elasticsearch/elasticsearch:8.9.0"
+ * - Execute "docker run -d -p 9200:9200 -p 9300:9300 -e discovery.type=single-node -e xpack.security.enabled=false docker.elastic.co/elasticsearch/elasticsearch:8.9.0"
+ * - Wait until Elasticsearch is ready to serve (may take a few minutes)
+ */
+
public static void main(String[] args) throws InterruptedException {
+ DockerImageName imageName = DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch:8.9.0");
+ Map env = new HashMap<>();
+ env.put("xpack.security.enabled", "false");
+ env.put("discovery.type", "single-node");
- try (ElasticsearchContainer elastic = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.9.0")
- .withEnv("xpack.security.enabled", "false")) {
+ try (ElasticsearchContainer elastic = new ElasticsearchContainer(imageName).withCertPath(null).withEnv(env)) {
elastic.start();
EmbeddingStore embeddingStore = ElasticsearchEmbeddingStore.builder()
- .serverUrl("http://" + elastic.getHttpHostAddress())
+ .serverUrl(elastic.getHttpHostAddress())
.dimension(384)
.build();
@@ -32,14 +49,19 @@ public static void main(String[] args) throws InterruptedException {
Embedding embedding2 = embeddingModel.embed(segment2).content();
embeddingStore.add(embedding2, segment2);
- Thread.sleep(1000); // to be sure that embeddings were persisted
+ // to be sure that embeddings were persisted
+ TimeUnit.MILLISECONDS.sleep(1000);
Embedding queryEmbedding = embeddingModel.embed("What is your favourite sport?").content();
List> relevant = embeddingStore.findRelevant(queryEmbedding, 1);
EmbeddingMatch embeddingMatch = relevant.get(0);
- System.out.println(embeddingMatch.score()); // 0.81442887
- System.out.println(embeddingMatch.embedded().text()); // I like football.
+ // expected 0.8144288659095
+ LOGGER.info("Score: {}", embeddingMatch.score());
+ // expected "I like football."
+ LOGGER.info("Embedded: {}", embeddingMatch.embedded().text());
+ } catch (Exception e) {
+ LOGGER.error("Error: {}", e.getMessage());
}
}
}
diff --git a/elasticsearch-example/src/main/resources/log4j2.xml b/elasticsearch-example/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..345ffd41
--- /dev/null
+++ b/elasticsearch-example/src/main/resources/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/neo4j-example/pom.xml b/neo4j-example/pom.xml
index f81fd3a7..815d50e9 100644
--- a/neo4j-example/pom.xml
+++ b/neo4j-example/pom.xml
@@ -12,6 +12,7 @@
17
17
UTF-8
+ 2.22.1
@@ -34,6 +35,23 @@
1.19.6
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j.version}
+
+
+
+ org.testcontainers
+ neo4j
+ 1.19.4
+
\ No newline at end of file
diff --git a/neo4j-example/src/main/java/Neo4jEmbeddingStoreExample.java b/neo4j-example/src/main/java/Neo4jEmbeddingStoreExample.java
index b428ad9a..e7105375 100644
--- a/neo4j-example/src/main/java/Neo4jEmbeddingStoreExample.java
+++ b/neo4j-example/src/main/java/Neo4jEmbeddingStoreExample.java
@@ -5,17 +5,35 @@
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.neo4j.Neo4jEmbeddingStore;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.neo4j.driver.AuthTokens;
+import org.neo4j.driver.GraphDatabase;
import org.testcontainers.containers.Neo4jContainer;
-
+import org.testcontainers.utility.DockerImageName;
import java.util.List;
public class Neo4jEmbeddingStoreExample {
+ private static final Logger LOGGER = LogManager.getLogger(Neo4jEmbeddingStoreExample.class);
+
+ /**
+ * To run this example, ensure you have Neo4j running locally,
+ * and change uri, username and password strings consistently.
+ * If not, then:
+ * - Execute "docker pull neo4j:latest"
+ * - Execute "docker run -d -p 7687:7687 --env NEO4J_AUTH=neo4j/password1234 neo4j:latest"
+ * - Wait until Neo4j is ready to serve (may take a few minutes)
+ */
+
public static void main(String[] args) {
- try (Neo4jContainer> neo4j = new Neo4jContainer<>("neo4j:5")) {
- neo4j.start();
+ String username = "neo4j";
+ String password = "password1234";
+
+ try (Neo4jContainer> neo4jContainer = new Neo4jContainer<>(DockerImageName.parse("neo4j:latest"))) {
+ neo4jContainer.withEnv("NEO4J_AUTH", username + "/" + password).start();
EmbeddingStore embeddingStore = Neo4jEmbeddingStore.builder()
- .withBasicAuth(neo4j.getBoltUrl(), "neo4j", neo4j.getAdminPassword())
+ .driver(GraphDatabase.driver(neo4jContainer.getBoltUrl(), AuthTokens.basic(username, password)))
.dimension(384)
.build();
@@ -33,8 +51,11 @@ public static void main(String[] args) {
List> relevant = embeddingStore.findRelevant(queryEmbedding, 1);
EmbeddingMatch embeddingMatch = relevant.get(0);
- System.out.println(embeddingMatch.score()); // 0.8144289255142212
- System.out.println(embeddingMatch.embedded().text()); // I like football.
+ LOGGER.info("Score: {}", embeddingMatch.score());
+ // expected "I like football."
+ LOGGER.info("Embedded: {}", embeddingMatch.embedded().text());
+ } catch (Exception e) {
+ LOGGER.error("Error: {}", e.getMessage());
}
}
}
diff --git a/neo4j-example/src/main/resources/log4j2.xml b/neo4j-example/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..345ffd41
--- /dev/null
+++ b/neo4j-example/src/main/resources/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ollama-examples/pom.xml b/ollama-examples/pom.xml
index a47066a3..eb9c40e1 100644
--- a/ollama-examples/pom.xml
+++ b/ollama-examples/pom.xml
@@ -40,6 +40,7 @@
5.10.0
+
org.tinylog
tinylog-impl
diff --git a/ollama-examples/src/main/java/OllamaChatModelTest.java b/ollama-examples/src/main/java/OllamaChatModelTest.java
index a179b6ac..20bce561 100644
--- a/ollama-examples/src/main/java/OllamaChatModelTest.java
+++ b/ollama-examples/src/main/java/OllamaChatModelTest.java
@@ -4,6 +4,7 @@
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
+import org.tinylog.Logger;
@Testcontainers
class OllamaChatModelTest {
@@ -21,40 +22,30 @@ class OllamaChatModelTest {
* 2. Run "docker exec -it ollama ollama run mistral" <- specify the desired model here
*/
- static String MODEL_NAME = "orca-mini"; // try "mistral", "llama2", "codellama", "phi" or "tinyllama"
-
@Container
- static GenericContainer> ollama = new GenericContainer<>("langchain4j/ollama-" + MODEL_NAME + ":latest")
- .withExposedPorts(11434);
+ private static GenericContainer> ollama = new GenericContainer<>(OllamaContants.OLLAMA_IMAGE_NAME).withExposedPorts(OllamaContants.OLLAMA_PORT);
@Test
- void simple_example() {
-
+ void example() {
ChatLanguageModel model = OllamaChatModel.builder()
- .baseUrl(baseUrl())
- .modelName(MODEL_NAME)
+ .baseUrl(baseUrl(ollama))
+ .modelName(OllamaContants.MODEL_NAME)
.build();
+ simpleExample(model);
+ jsonOutputExample(model);
+ }
+ void simpleExample(ChatLanguageModel model) {
String answer = model.generate("Provide 3 short bullet points explaining why Java is awesome");
-
- System.out.println(answer);
+ Logger.info("Answer: {}", answer);
}
- @Test
- void json_output_example() {
-
- ChatLanguageModel model = OllamaChatModel.builder()
- .baseUrl(baseUrl())
- .modelName(MODEL_NAME)
- .format("json")
- .build();
-
+ void jsonOutputExample(ChatLanguageModel model) {
String json = model.generate("Give me a JSON with 2 fields: name and age of a John Doe, 42");
-
- System.out.println(json);
+ Logger.info("JSON: {}", json);
}
- static String baseUrl() {
+ static String baseUrl(GenericContainer> ollama) {
return String.format("http://%s:%d", ollama.getHost(), ollama.getFirstMappedPort());
}
}
diff --git a/ollama-examples/src/main/java/OllamaContants.java b/ollama-examples/src/main/java/OllamaContants.java
new file mode 100644
index 00000000..7fd08ff8
--- /dev/null
+++ b/ollama-examples/src/main/java/OllamaContants.java
@@ -0,0 +1,14 @@
+public class OllamaContants {
+
+ static final String MODEL_ORCA_MINI = "orca-mini";
+ static final String MODEL_MISTRAL = "mistral";
+ static final String MODEL_LLAMA2 = "llama2";
+ static final String MODEL_CODE_LLAMA = "codellama";
+ static final String MODEL_PHI = "phi";
+ static final String MODEL_TINY_LLAMA = "tinyllama";
+
+ // try "mistral", "llama2", "codellama", "phi" or "tinyllama"
+ static final String MODEL_NAME = MODEL_ORCA_MINI;
+ public static final String OLLAMA_IMAGE_NAME = "langchain4j/ollama-" + MODEL_NAME + ":latest";
+ public static final Integer OLLAMA_PORT = 11434;
+}
diff --git a/ollama-examples/src/main/java/OllamaStreamingChatModelTest.java b/ollama-examples/src/main/java/OllamaStreamingChatModelTest.java
index 56a7f672..f3a2b19a 100644
--- a/ollama-examples/src/main/java/OllamaStreamingChatModelTest.java
+++ b/ollama-examples/src/main/java/OllamaStreamingChatModelTest.java
@@ -7,6 +7,7 @@
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
+import org.tinylog.Logger;
import java.util.concurrent.CompletableFuture;
@@ -26,20 +27,15 @@ class OllamaStreamingChatModelTest {
* 2. Run "docker exec -it ollama ollama run llama2" <- specify the desired model here
*/
- static String MODEL_NAME = "orca-mini"; // try "mistral", "llama2", "codellama" or "phi"
- static String DOCKER_IMAGE_NAME = "langchain4j/ollama-" + MODEL_NAME + ":latest";
- static Integer PORT = 11434;
-
@Container
- static GenericContainer> ollama = new GenericContainer<>(DOCKER_IMAGE_NAME)
- .withExposedPorts(PORT);
+ private static GenericContainer> ollama = new GenericContainer<>(OllamaContants.OLLAMA_IMAGE_NAME).withExposedPorts(OllamaContants.OLLAMA_PORT);
@Test
- void streaming_example() {
+ void streamingExample() {
StreamingChatLanguageModel model = OllamaStreamingChatModel.builder()
- .baseUrl(String.format("http://%s:%d", ollama.getHost(), ollama.getMappedPort(PORT)))
- .modelName(MODEL_NAME)
+ .baseUrl(String.format("http://%s:%d", ollama.getHost(), ollama.getMappedPort(OllamaContants.OLLAMA_PORT)))
+ .modelName(OllamaContants.MODEL_NAME)
.temperature(0.0)
.build();
@@ -50,7 +46,7 @@ void streaming_example() {
@Override
public void onNext(String token) {
- System.out.print(token);
+ Logger.info("Token: {}", token);
}
@Override
diff --git a/ollama-examples/src/main/resources/tinylog.properties b/ollama-examples/src/main/resources/tinylog.properties
new file mode 100644
index 00000000..cc12392d
--- /dev/null
+++ b/ollama-examples/src/main/resources/tinylog.properties
@@ -0,0 +1,4 @@
+#https://tinylog.org/v2/configuration/
+writer = console
+writer.level = info
+writer.format = {date: HH:mm:ss.SSS} {{level}:|min-size=8} {message}
\ No newline at end of file
diff --git a/open-ai-examples/src/main/java/OpenAiImageModelExamples.java b/open-ai-examples/src/main/java/OpenAiImageModelExamples.java
index 6c1036cd..a5492594 100644
--- a/open-ai-examples/src/main/java/OpenAiImageModelExamples.java
+++ b/open-ai-examples/src/main/java/OpenAiImageModelExamples.java
@@ -11,7 +11,7 @@
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiImageModel;
import dev.langchain4j.model.output.Response;
-import dev.langchain4j.retriever.EmbeddingStoreRetriever;
+import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
@@ -76,7 +76,7 @@ public static void main(String[] args) throws URISyntaxException {
ConversationalRetrievalChain chain = ConversationalRetrievalChain
.builder()
.chatLanguageModel(OpenAiChatModel.builder().apiKey(System.getenv("OPENAI_API_KEY")).build())
- .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel))
+ .contentRetriever(new EmbeddingStoreContentRetriever(embeddingStore, embeddingModel))
.build();
PromptTemplate drawPromptTemplate = PromptTemplate.from(
diff --git a/pom.xml b/pom.xml
index 869f13a4..a60c8cbc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,5 +36,4 @@
javafx-example
quarkus-example
-
\ No newline at end of file
diff --git a/redis-example/pom.xml b/redis-example/pom.xml
index e16dd4d3..40531d52 100644
--- a/redis-example/pom.xml
+++ b/redis-example/pom.xml
@@ -12,10 +12,10 @@
8
8
UTF-8
+ 2.22.1
-
dev.langchain4j
langchain4j-redis
@@ -28,16 +28,22 @@
0.30.0
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
- org.slf4j
- slf4j-simple
- 2.0.7
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j.version}
- com.redis.testcontainers
+ com.redis
testcontainers-redis
- 1.6.4
+ 2.0.1
@@ -47,5 +53,4 @@
-
\ No newline at end of file
diff --git a/redis-example/src/main/java/RedisEmbeddingStoreExample.java b/redis-example/src/main/java/RedisEmbeddingStoreExample.java
index c3c8b2a8..d183081e 100644
--- a/redis-example/src/main/java/RedisEmbeddingStoreExample.java
+++ b/redis-example/src/main/java/RedisEmbeddingStoreExample.java
@@ -1,4 +1,5 @@
-import com.redis.testcontainers.RedisStackContainer;
+
+import com.redis.testcontainers.RedisContainer;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel;
@@ -6,42 +7,45 @@
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.testcontainers.utility.DockerImageName;
import java.util.List;
-import static com.redis.testcontainers.RedisStackContainer.DEFAULT_IMAGE_NAME;
-import static com.redis.testcontainers.RedisStackContainer.DEFAULT_TAG;
public class RedisEmbeddingStoreExample {
+ private static final Logger LOGGER = LogManager.getLogger(RedisEmbeddingStoreExample.class);
public static void main(String[] args) {
-
- RedisStackContainer redis = new RedisStackContainer(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG));
- redis.start();
-
- EmbeddingStore embeddingStore = RedisEmbeddingStore.builder()
- .host(redis.getHost())
- .port(redis.getFirstMappedPort())
- .dimension(384)
- .build();
-
- EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
-
- 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();
- List> relevant = embeddingStore.findRelevant(queryEmbedding, 1);
- EmbeddingMatch embeddingMatch = relevant.get(0);
-
- System.out.println(embeddingMatch.score()); // 0.8144288659095
- System.out.println(embeddingMatch.embedded().text()); // I like football.
-
- redis.stop();
+ try (RedisContainer redis = new RedisContainer(DockerImageName.parse("redis/redis-stack-server:latest"))) {
+ redis.start();
+
+ EmbeddingStore embeddingStore = RedisEmbeddingStore.builder()
+ .host(redis.getHost())
+ .port(redis.getFirstMappedPort())
+ .dimension(384)
+ .build();
+
+ EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
+
+ 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();
+ List> relevant = embeddingStore.findRelevant(queryEmbedding, 1);
+ EmbeddingMatch embeddingMatch = relevant.get(0);
+ // expected 0.8144288659095
+ LOGGER.info("Score: {}", embeddingMatch.score());
+ // expected "I like football."
+ LOGGER.info("Embedded: {}", embeddingMatch.embedded().text());
+ } catch (Exception e) {
+ LOGGER.error("Error: {}", e.getMessage());
+ }
}
}
diff --git a/redis-example/src/main/resources/log4j2.xml b/redis-example/src/main/resources/log4j2.xml
new file mode 100644
index 00000000..345ffd41
--- /dev/null
+++ b/redis-example/src/main/resources/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file