From 7392b003f1cee2c312f29a17d1f46cb86aa0bcd9 Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Mon, 23 Oct 2023 14:33:05 +0530 Subject: [PATCH 1/7] Adding sourcecode for reference in the article tracked under BAEL-6970. --- libraries-llms/README.md | 6 ++ libraries-llms/pom.xml | 43 ++++++++ libraries-llms/src/main/resources/logback.xml | 17 ++++ .../langchain/ChainWithDocumentLiveTests.java | 98 +++++++++++++++++++ .../langchain/ChatWithDocumentLiveTests.java | 80 +++++++++++++++ .../langchain/ChatWithMemoryLiveTests.java | 45 +++++++++ .../com/baeldung/langchain/Constants.java | 7 ++ .../langchain/PromptTemplatesLiveTests.java | 42 ++++++++ .../langchain/ServiceWithToolsLiveTests.java | 52 ++++++++++ .../example-files/simpson's_adventures.txt | 28 ++++++ pom.xml | 2 + 11 files changed, 420 insertions(+) create mode 100644 libraries-llms/README.md create mode 100644 libraries-llms/pom.xml create mode 100644 libraries-llms/src/main/resources/logback.xml create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/Constants.java create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java create mode 100644 libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java create mode 100644 libraries-llms/src/test/resources/example-files/simpson's_adventures.txt diff --git a/libraries-llms/README.md b/libraries-llms/README.md new file mode 100644 index 0000000000..2e250d42d6 --- /dev/null +++ b/libraries-llms/README.md @@ -0,0 +1,6 @@ +## Language Model Integration Libraries + +This module contains articles about libraries for language model integration in Java. + +### Relevant articles +- [Introduction to LangChain](https://www.baeldung.com/langchain) \ No newline at end of file diff --git a/libraries-llms/pom.xml b/libraries-llms/pom.xml new file mode 100644 index 0000000000..3d5ed6830e --- /dev/null +++ b/libraries-llms/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + libraries-llms + libraries-llms + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + dev.langchain4j + langchain4j + ${langchain4j.version} + + + dev.langchain4j + langchain4j-embeddings + ${langchain4j.version} + + + dev.langchain4j + langchain4j-open-ai + ${langchain4j.version} + + + dev.langchain4j + langchain4j-embeddings-all-minilm-l6-v2 + ${langchain4j.version} + + + + + 0.23.0 + + + \ No newline at end of file diff --git a/libraries-llms/src/main/resources/logback.xml b/libraries-llms/src/main/resources/logback.xml new file mode 100644 index 0000000000..23c5605a05 --- /dev/null +++ b/libraries-llms/src/main/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - + %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java new file mode 100644 index 0000000000..4ab5eaa68d --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java @@ -0,0 +1,98 @@ +package com.baeldung.langchain; + +import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocument; +import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; +import static java.time.Duration.ofSeconds; +import static java.util.stream.Collectors.joining; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.junit.Assert; +import org.junit.Test; + +import dev.langchain4j.data.document.Document; +import dev.langchain4j.data.document.DocumentSplitter; +import dev.langchain4j.data.document.splitter.DocumentSplitters; +import dev.langchain4j.data.embedding.Embedding; +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.input.Prompt; +import dev.langchain4j.model.input.PromptTemplate; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.model.openai.OpenAiTokenizer; +import dev.langchain4j.store.embedding.EmbeddingMatch; +import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; + +public class ChainWithDocumentLiveTests { + + @Test + public void givenChainWithDocument_whenPrompted_thenValidResponse() { + + Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); + DocumentSplitter splitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO)); + List segments = splitter.split(document); + + EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); + List embeddings = embeddingModel.embedAll(segments) + .content(); + EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); + embeddingStore.addAll(embeddings, segments); + + String question = "Who is Simpson?"; + Embedding questionEmbedding = embeddingModel.embed(question) + .content(); + int maxResults = 3; + double minScore = 0.7; + List> relevantEmbeddings = embeddingStore.findRelevant(questionEmbedding, maxResults, minScore); + + PromptTemplate promptTemplate = PromptTemplate.from("Answer the following question to the best of your ability:\n" + "\n" + "Question:\n" + "{{question}}\n" + "\n" + "Base your answer on the following information:\n" + "{{information}}"); + + String information = relevantEmbeddings.stream() + .map(match -> match.embedded() + .text()) + .collect(joining("\n\n")); + + Map variables = new HashMap<>(); + variables.put("question", question); + variables.put("information", information); + + Prompt prompt = promptTemplate.apply(variables); + ChatLanguageModel chatModel = OpenAiChatModel.builder() + .apiKey(Constants.OPEN_API_KEY) + .timeout(ofSeconds(60)) + .build(); + AiMessage aiMessage = chatModel.generate(prompt.toUserMessage()) + .content(); + + Logger.getGlobal() + .info(aiMessage.text()); + Assert.assertNotNull(aiMessage.text()); + + } + + private static Path toPath(String fileName) { + try { + URL fileUrl = new File(fileName).toURI() + .toURL(); + System.out.println(new File(fileName).toURI() + .toURL()); + return Paths.get(fileUrl.toURI()); + } catch (URISyntaxException | MalformedURLException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java new file mode 100644 index 0000000000..e75465e5b7 --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java @@ -0,0 +1,80 @@ +package com.baeldung.langchain; + +import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocument; +import static java.time.Duration.ofSeconds; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.logging.Logger; + +import org.junit.Assert; +import org.junit.Test; + +import dev.langchain4j.chain.ConversationalRetrievalChain; +import dev.langchain4j.data.document.Document; +import dev.langchain4j.data.document.splitter.DocumentSplitters; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.retriever.EmbeddingStoreRetriever; +import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; +import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; + +public class ChatWithDocumentLiveTests { + + @Test + public void givenDocument_whenPrompted_thenValidResponse() { + + EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); + + EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); + + EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() + .documentSplitter(DocumentSplitters.recursive(500, 0)) + .embeddingModel(embeddingModel) + .embeddingStore(embeddingStore) + .build(); + + Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); + ingestor.ingest(document); + + ChatLanguageModel chatModel = OpenAiChatModel.builder() + .apiKey(Constants.OPEN_API_KEY) + .timeout(ofSeconds(60)) + .build(); + + ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder() + .chatLanguageModel(chatModel) + .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel)) + // .chatMemory() // you can override default chat memory + // .promptTemplate() // you can override default prompt template + .build(); + + String answer = chain.execute("Who is Simpson?"); + + Logger.getGlobal() + .info(answer); + Assert.assertNotNull(answer); + + } + + private static Path toPath(String fileName) { + try { + URL fileUrl = new File(fileName).toURI() + .toURL(); + System.out.println(new File(fileName).toURI() + .toURL()); + return Paths.get(fileUrl.toURI()); + } catch (URISyntaxException | MalformedURLException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java new file mode 100644 index 0000000000..4395c52274 --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java @@ -0,0 +1,45 @@ +package com.baeldung.langchain; + +import dev.langchain4j.data.message.AiMessage; +import dev.langchain4j.memory.ChatMemory; +import dev.langchain4j.memory.chat.TokenWindowChatMemory; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.model.openai.OpenAiTokenizer; + +import static dev.langchain4j.data.message.UserMessage.userMessage; +import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; + +import java.util.logging.Logger; + +import org.junit.Assert; +import org.junit.Test; + +public class ChatWithMemoryLiveTests { + + @Test + public void givenMemory_whenPrompted_thenValidResponse() { + + ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPEN_API_KEY); + ChatMemory chatMemory = TokenWindowChatMemory.withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO)); + + chatMemory.add(userMessage("Hello, my name is Kumar")); + AiMessage answer = model.generate(chatMemory.messages()) + .content(); + Logger.getGlobal() + .info(answer.text()); + Assert.assertNotNull(answer.text()); + chatMemory.add(answer); + + chatMemory.add(userMessage("What is my name?")); + AiMessage answerWithName = model.generate(chatMemory.messages()) + .content(); + Logger.getGlobal() + .info(answerWithName.text()); + Assert.assertTrue(answerWithName.text() + .contains("Kumar")); + chatMemory.add(answerWithName); + + } + +} diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java new file mode 100644 index 0000000000..15645ce68e --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java @@ -0,0 +1,7 @@ +package com.baeldung.langchain; + +public class Constants { + + public static String OPEN_API_KEY = "demo"; + +} diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java new file mode 100644 index 0000000000..c485b9cdf6 --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java @@ -0,0 +1,42 @@ +package com.baeldung.langchain; + +import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import org.junit.Test; + +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.input.Prompt; +import dev.langchain4j.model.input.PromptTemplate; +import dev.langchain4j.model.openai.OpenAiChatModel; + +import org.junit.Assert; + +public class PromptTemplatesLiveTests { + + @Test + public void givenPromptTemplate_whenSuppliedInput_thenValidResponse() { + + PromptTemplate promptTemplate = PromptTemplate.from("Tell me a {{adjective}} joke about {{content}}.."); + Map variables = new HashMap<>(); + variables.put("adjective", "funny"); + variables.put("content", "humans"); + Prompt prompt = promptTemplate.apply(variables); + + ChatLanguageModel model = OpenAiChatModel.builder() + .apiKey(Constants.OPEN_API_KEY) + .modelName(GPT_3_5_TURBO) + .temperature(0.3) + .build(); + + String response = model.generate(prompt.text()); + Logger.getGlobal() + .info(response); + Assert.assertNotNull(response); + + } + +} diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java new file mode 100644 index 0000000000..1e4b356334 --- /dev/null +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java @@ -0,0 +1,52 @@ +package com.baeldung.langchain; + +import java.util.logging.Logger; + +import org.junit.Assert; +import org.junit.Test; + +import dev.langchain4j.agent.tool.Tool; +import dev.langchain4j.memory.chat.MessageWindowChatMemory; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.service.AiServices; + +public class ServiceWithToolsLiveTests { + + static class Calculator { + + @Tool("Calculates the length of a string") + int stringLength(String s) { + return s.length(); + } + + @Tool("Calculates the sum of two numbers") + int add(int a, int b) { + return a + b; + } + + } + + interface Assistant { + + String chat(String userMessage); + } + + @Test + public void givenServiceWithTools_whenPrompted_thenValidResponse() { + + Assistant assistant = AiServices.builder(Assistant.class) + .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPEN_API_KEY)) + .tools(new Calculator()) + .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) + .build(); + + String question = "What is the sum of the numbers of letters in the words \"language\" and \"model\"?"; + String answer = assistant.chat(question); + + Logger.getGlobal() + .info(answer); + Assert.assertNotNull(answer); + + } + +} diff --git a/libraries-llms/src/test/resources/example-files/simpson's_adventures.txt b/libraries-llms/src/test/resources/example-files/simpson's_adventures.txt new file mode 100644 index 0000000000..ae6de80be0 --- /dev/null +++ b/libraries-llms/src/test/resources/example-files/simpson's_adventures.txt @@ -0,0 +1,28 @@ +Once upon a time in the town of VeggieVille, there lived a cheerful carrot named Simpson. +Simpson 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. + +Simpson 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 Simpson, 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. +Simpson'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. + +Simpson'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. +Simpson, 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. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3f4da4bdb0..a391a1c774 100644 --- a/pom.xml +++ b/pom.xml @@ -936,6 +936,7 @@ spring-di-4 spring-kafka-2 + libraries-llms @@ -1223,6 +1224,7 @@ spring-di-4 spring-kafka-2 + libraries-llms From 9796fd51979d6f002451db45d36941b42dd988a2 Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Mon, 23 Oct 2023 16:04:27 +0530 Subject: [PATCH 2/7] Adding sourcecode for reference in the article tracked under BAEL-6970. --- ...nWithDocumentLiveTests.java => ChainWithDocumentLiveTest.java} | 0 ...atWithDocumentLiveTests.java => ChatWithDocumentLiveTest.java} | 0 .../{ChatWithMemoryLiveTests.java => ChatWithMemoryLiveTest.java} | 0 ...PromptTemplatesLiveTests.java => PromptTemplatesLiveTest.java} | 0 ...rviceWithToolsLiveTests.java => ServiceWithToolsLiveTest.java} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename libraries-llms/src/test/java/com/baeldung/langchain/{ChainWithDocumentLiveTests.java => ChainWithDocumentLiveTest.java} (100%) rename libraries-llms/src/test/java/com/baeldung/langchain/{ChatWithDocumentLiveTests.java => ChatWithDocumentLiveTest.java} (100%) rename libraries-llms/src/test/java/com/baeldung/langchain/{ChatWithMemoryLiveTests.java => ChatWithMemoryLiveTest.java} (100%) rename libraries-llms/src/test/java/com/baeldung/langchain/{PromptTemplatesLiveTests.java => PromptTemplatesLiveTest.java} (100%) rename libraries-llms/src/test/java/com/baeldung/langchain/{ServiceWithToolsLiveTests.java => ServiceWithToolsLiveTest.java} (100%) diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java similarity index 100% rename from libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTests.java rename to libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java similarity index 100% rename from libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTests.java rename to libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java similarity index 100% rename from libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTests.java rename to libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java similarity index 100% rename from libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTests.java rename to libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java similarity index 100% rename from libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTests.java rename to libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java From c36a6cc5a4f70ca32cd6397f45ad83a890248deb Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Mon, 23 Oct 2023 16:05:03 +0530 Subject: [PATCH 3/7] Changed the name of tests from LiveTests to LiveTest --- .../java/com/baeldung/langchain/ChainWithDocumentLiveTest.java | 2 +- .../java/com/baeldung/langchain/ChatWithDocumentLiveTest.java | 2 +- .../java/com/baeldung/langchain/ChatWithMemoryLiveTest.java | 2 +- .../java/com/baeldung/langchain/PromptTemplatesLiveTest.java | 2 +- .../java/com/baeldung/langchain/ServiceWithToolsLiveTest.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java index 4ab5eaa68d..b1db486d84 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java @@ -36,7 +36,7 @@ import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; -public class ChainWithDocumentLiveTests { +public class ChainWithDocumentLiveTest { @Test public void givenChainWithDocument_whenPrompted_thenValidResponse() { diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java index e75465e5b7..643c56520e 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java @@ -27,7 +27,7 @@ import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; -public class ChatWithDocumentLiveTests { +public class ChatWithDocumentLiveTest { @Test public void givenDocument_whenPrompted_thenValidResponse() { diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java index 4395c52274..5e0057d23c 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java @@ -15,7 +15,7 @@ import java.util.logging.Logger; import org.junit.Assert; import org.junit.Test; -public class ChatWithMemoryLiveTests { +public class ChatWithMemoryLiveTest { @Test public void givenMemory_whenPrompted_thenValidResponse() { diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java index c485b9cdf6..5f155d3dba 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java @@ -15,7 +15,7 @@ import dev.langchain4j.model.openai.OpenAiChatModel; import org.junit.Assert; -public class PromptTemplatesLiveTests { +public class PromptTemplatesLiveTest { @Test public void givenPromptTemplate_whenSuppliedInput_thenValidResponse() { diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java index 1e4b356334..024c1523e8 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java @@ -10,7 +10,7 @@ import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; -public class ServiceWithToolsLiveTests { +public class ServiceWithToolsLiveTest { static class Calculator { From 03c9dce8cf0a141e8dfd705d03aaaef06579dd30 Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Wed, 25 Oct 2023 10:40:32 +0530 Subject: [PATCH 4/7] Incorporated some review comments on the code. --- libraries-llms/src/main/resources/logback.xml | 17 ---- .../langchain/ChainWithDocumentLiveTest.java | 73 +++++++---------- .../langchain/ChatWithDocumentLiveTest.java | 78 ++++++++++++------- .../langchain/ChatWithMemoryLiveTest.java | 18 ++--- .../com/baeldung/langchain/Constants.java | 7 +- .../langchain/PromptTemplatesLiveTest.java | 10 ++- .../langchain/ServiceWithToolsLiveTest.java | 13 ++-- pom.xml | 4 +- 8 files changed, 110 insertions(+), 110 deletions(-) delete mode 100644 libraries-llms/src/main/resources/logback.xml diff --git a/libraries-llms/src/main/resources/logback.xml b/libraries-llms/src/main/resources/logback.xml deleted file mode 100644 index 23c5605a05..0000000000 --- a/libraries-llms/src/main/resources/logback.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - - %msg%n - - - - - - - - - - \ No newline at end of file diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java index b1db486d84..556f394866 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java @@ -1,9 +1,7 @@ package com.baeldung.langchain; import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocument; -import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; import static java.time.Duration.ofSeconds; -import static java.util.stream.Collectors.joining; import java.io.File; import java.net.MalformedURLException; @@ -11,75 +9,64 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import dev.langchain4j.chain.ConversationalRetrievalChain; import dev.langchain4j.data.document.Document; -import dev.langchain4j.data.document.DocumentSplitter; import dev.langchain4j.data.document.splitter.DocumentSplitters; -import dev.langchain4j.data.embedding.Embedding; -import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel; -import dev.langchain4j.model.input.Prompt; import dev.langchain4j.model.input.PromptTemplate; import dev.langchain4j.model.openai.OpenAiChatModel; -import dev.langchain4j.model.openai.OpenAiTokenizer; -import dev.langchain4j.store.embedding.EmbeddingMatch; +import dev.langchain4j.retriever.EmbeddingStoreRetriever; import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; public class ChainWithDocumentLiveTest { + + Logger logger = LoggerFactory.getLogger(ChainWithDocumentLiveTest.class); @Test - public void givenChainWithDocument_whenPrompted_thenValidResponse() { - - Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); - DocumentSplitter splitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO)); - List segments = splitter.split(document); + public void givenDocument_whenPrompted_thenValidResponse() { EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); - List embeddings = embeddingModel.embedAll(segments) - .content(); + EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); - embeddingStore.addAll(embeddings, segments); - String question = "Who is Simpson?"; - Embedding questionEmbedding = embeddingModel.embed(question) - .content(); - int maxResults = 3; - double minScore = 0.7; - List> relevantEmbeddings = embeddingStore.findRelevant(questionEmbedding, maxResults, minScore); + EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() + .documentSplitter(DocumentSplitters.recursive(500, 0)) + .embeddingModel(embeddingModel) + .embeddingStore(embeddingStore) + .build(); - PromptTemplate promptTemplate = PromptTemplate.from("Answer the following question to the best of your ability:\n" + "\n" + "Question:\n" + "{{question}}\n" + "\n" + "Base your answer on the following information:\n" + "{{information}}"); + Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); + ingestor.ingest(document); - String information = relevantEmbeddings.stream() - .map(match -> match.embedded() - .text()) - .collect(joining("\n\n")); - - Map variables = new HashMap<>(); - variables.put("question", question); - variables.put("information", information); - - Prompt prompt = promptTemplate.apply(variables); ChatLanguageModel chatModel = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_API_KEY) + .apiKey(Constants.OPEN_AI_KEY) .timeout(ofSeconds(60)) .build(); - AiMessage aiMessage = chatModel.generate(prompt.toUserMessage()) - .content(); - Logger.getGlobal() - .info(aiMessage.text()); - Assert.assertNotNull(aiMessage.text()); + ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder() + .chatLanguageModel(chatModel) + .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel)) + .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) + .promptTemplate(PromptTemplate + .from("Answer the following question to the best of your ability: {{question}}\n\nBase your answer on the following information:\n{{information}}")) + .build(); + + String answer = chain.execute("Who is Simpson?"); + + logger.info(answer); + Assert.assertNotNull(answer); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java index 643c56520e..a7dc89afde 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java @@ -1,7 +1,9 @@ package com.baeldung.langchain; import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocument; +import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; import static java.time.Duration.ofSeconds; +import static java.util.stream.Collectors.joining; import java.io.File; import java.net.MalformedURLException; @@ -9,59 +11,77 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.logging.Logger; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import dev.langchain4j.chain.ConversationalRetrievalChain; import dev.langchain4j.data.document.Document; +import dev.langchain4j.data.document.DocumentSplitter; import dev.langchain4j.data.document.splitter.DocumentSplitters; +import dev.langchain4j.data.embedding.Embedding; +import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.embedding.AllMiniLmL6V2EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.input.Prompt; +import dev.langchain4j.model.input.PromptTemplate; import dev.langchain4j.model.openai.OpenAiChatModel; -import dev.langchain4j.retriever.EmbeddingStoreRetriever; +import dev.langchain4j.model.openai.OpenAiTokenizer; +import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingStore; -import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; public class ChatWithDocumentLiveTest { + + Logger logger = LoggerFactory.getLogger(ChatWithDocumentLiveTest.class); @Test - public void givenDocument_whenPrompted_thenValidResponse() { - - EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); - - EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); - - EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() - .documentSplitter(DocumentSplitters.recursive(500, 0)) - .embeddingModel(embeddingModel) - .embeddingStore(embeddingStore) - .build(); + public void givenChainWithDocument_whenPrompted_thenValidResponse() { Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); - ingestor.ingest(document); + DocumentSplitter splitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO)); + List segments = splitter.split(document); + EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); + List embeddings = embeddingModel.embedAll(segments) + .content(); + EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); + embeddingStore.addAll(embeddings, segments); + + String question = "Who is Simpson?"; + Embedding questionEmbedding = embeddingModel.embed(question) + .content(); + int maxResults = 3; + double minScore = 0.7; + List> relevantEmbeddings = embeddingStore.findRelevant(questionEmbedding, maxResults, minScore); + + PromptTemplate promptTemplate = PromptTemplate.from("Answer the following question to the best of your ability:\n" + "\n" + "Question:\n" + "{{question}}\n" + "\n" + "Base your answer on the following information:\n" + "{{information}}"); + + String information = relevantEmbeddings.stream() + .map(match -> match.embedded() + .text()) + .collect(joining("\n\n")); + + Map variables = new HashMap<>(); + variables.put("question", question); + variables.put("information", information); + + Prompt prompt = promptTemplate.apply(variables); ChatLanguageModel chatModel = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_API_KEY) + .apiKey(Constants.OPEN_AI_KEY) .timeout(ofSeconds(60)) .build(); + AiMessage aiMessage = chatModel.generate(prompt.toUserMessage()) + .content(); - ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder() - .chatLanguageModel(chatModel) - .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel)) - // .chatMemory() // you can override default chat memory - // .promptTemplate() // you can override default prompt template - .build(); - - String answer = chain.execute("Who is Simpson?"); - - Logger.getGlobal() - .info(answer); - Assert.assertNotNull(answer); + logger.info(aiMessage.text()); + Assert.assertNotNull(aiMessage.text()); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java index 5e0057d23c..8f7dcca1cb 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java @@ -9,35 +9,35 @@ import dev.langchain4j.model.openai.OpenAiTokenizer; import static dev.langchain4j.data.message.UserMessage.userMessage; import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; - -import java.util.logging.Logger; +import static org.assertj.core.api.Assertions.assertThat; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ChatWithMemoryLiveTest { + + Logger logger = LoggerFactory.getLogger(ChatWithMemoryLiveTest.class); @Test public void givenMemory_whenPrompted_thenValidResponse() { - ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPEN_API_KEY); + ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY); ChatMemory chatMemory = TokenWindowChatMemory.withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO)); chatMemory.add(userMessage("Hello, my name is Kumar")); AiMessage answer = model.generate(chatMemory.messages()) .content(); - Logger.getGlobal() - .info(answer.text()); + logger.info(answer.text()); Assert.assertNotNull(answer.text()); chatMemory.add(answer); chatMemory.add(userMessage("What is my name?")); AiMessage answerWithName = model.generate(chatMemory.messages()) .content(); - Logger.getGlobal() - .info(answerWithName.text()); - Assert.assertTrue(answerWithName.text() - .contains("Kumar")); + logger.info(answerWithName.text()); + assertThat(answerWithName.text().contains("Kumar")); chatMemory.add(answerWithName); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java index 15645ce68e..149858f351 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java @@ -2,6 +2,11 @@ package com.baeldung.langchain; public class Constants { - public static String OPEN_API_KEY = "demo"; + /** + * A limited access key for access to OpenAI language models can be generated by first + * registering for free at (https://platform.openai.com/signup) and then by navigating + * to "Create new secret key" page at (https://platform.openai.com/account/api-keys). + */ + public static String OPEN_AI_KEY = ""; } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java index 5f155d3dba..31698ee0c7 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java @@ -4,9 +4,10 @@ import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; import java.util.HashMap; import java.util.Map; -import java.util.logging.Logger; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.input.Prompt; @@ -16,6 +17,8 @@ import dev.langchain4j.model.openai.OpenAiChatModel; import org.junit.Assert; public class PromptTemplatesLiveTest { + + Logger logger = LoggerFactory.getLogger(PromptTemplatesLiveTest.class); @Test public void givenPromptTemplate_whenSuppliedInput_thenValidResponse() { @@ -27,14 +30,13 @@ public class PromptTemplatesLiveTest { Prompt prompt = promptTemplate.apply(variables); ChatLanguageModel model = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_API_KEY) + .apiKey(Constants.OPEN_AI_KEY) .modelName(GPT_3_5_TURBO) .temperature(0.3) .build(); String response = model.generate(prompt.text()); - Logger.getGlobal() - .info(response); + logger.info(response); Assert.assertNotNull(response); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java index 024c1523e8..6a6144aa21 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java @@ -1,9 +1,11 @@ package com.baeldung.langchain; -import java.util.logging.Logger; +import static org.assertj.core.api.Assertions.assertThat; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import dev.langchain4j.agent.tool.Tool; import dev.langchain4j.memory.chat.MessageWindowChatMemory; @@ -11,6 +13,8 @@ import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; public class ServiceWithToolsLiveTest { + + Logger logger = LoggerFactory.getLogger(ServiceWithToolsLiveTest.class); static class Calculator { @@ -35,7 +39,7 @@ public class ServiceWithToolsLiveTest { public void givenServiceWithTools_whenPrompted_thenValidResponse() { Assistant assistant = AiServices.builder(Assistant.class) - .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPEN_API_KEY)) + .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY)) .tools(new Calculator()) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build(); @@ -43,9 +47,8 @@ public class ServiceWithToolsLiveTest { String question = "What is the sum of the numbers of letters in the words \"language\" and \"model\"?"; String answer = assistant.chat(question); - Logger.getGlobal() - .info(answer); - Assert.assertNotNull(answer); + logger.info(answer); + assertThat(answer).contains("13"); } diff --git a/pom.xml b/pom.xml index a391a1c774..cc433f0946 100644 --- a/pom.xml +++ b/pom.xml @@ -936,7 +936,7 @@ spring-di-4 spring-kafka-2 - libraries-llms + libraries-llms @@ -1224,7 +1224,7 @@ spring-di-4 spring-kafka-2 - libraries-llms + libraries-llms From ed75b80958f0ce23157017a2dde51baa2d7471f9 Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Thu, 26 Oct 2023 23:15:14 +0530 Subject: [PATCH 5/7] Added few more changes to accommodate review comments. --- .../langchain/ChainWithDocumentLiveTest.java | 32 ++++--------------- .../langchain/ChatWithDocumentLiveTest.java | 29 ++++------------- .../langchain/ChatWithMemoryLiveTest.java | 27 ++++++++-------- .../com/baeldung/langchain/Constants.java | 2 +- .../langchain/PromptTemplatesLiveTest.java | 7 ++-- .../langchain/ServiceWithToolsLiveTest.java | 3 +- 6 files changed, 32 insertions(+), 68 deletions(-) diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java index 556f394866..804a052990 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java @@ -2,15 +2,10 @@ package com.baeldung.langchain; import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocument; import static java.time.Duration.ofSeconds; +import static org.junit.Assert.assertNotNull; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; import java.nio.file.Paths; -import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,11 +26,11 @@ import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; public class ChainWithDocumentLiveTest { - - Logger logger = LoggerFactory.getLogger(ChainWithDocumentLiveTest.class); + + private static final Logger logger = LoggerFactory.getLogger(ChainWithDocumentLiveTest.class); @Test - public void givenDocument_whenPrompted_thenValidResponse() { + public void givenChainWithDocument_whenPrompted_thenValidResponse() { EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); @@ -47,7 +42,7 @@ public class ChainWithDocumentLiveTest { .embeddingStore(embeddingStore) .build(); - Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); + Document document = loadDocument(Paths.get("src/test/resources/example-files/simpson's_adventures.txt")); ingestor.ingest(document); ChatLanguageModel chatModel = OpenAiChatModel.builder() @@ -59,27 +54,14 @@ public class ChainWithDocumentLiveTest { .chatLanguageModel(chatModel) .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel)) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) - .promptTemplate(PromptTemplate - .from("Answer the following question to the best of your ability: {{question}}\n\nBase your answer on the following information:\n{{information}}")) + .promptTemplate(PromptTemplate.from("Answer the following question to the best of your ability: {{question}}\n\nBase your answer on the following information:\n{{information}}")) .build(); String answer = chain.execute("Who is Simpson?"); logger.info(answer); - Assert.assertNotNull(answer); + assertNotNull(answer); } - private static Path toPath(String fileName) { - try { - URL fileUrl = new File(fileName).toURI() - .toURL(); - System.out.println(new File(fileName).toURI() - .toURL()); - return Paths.get(fileUrl.toURI()); - } catch (URISyntaxException | MalformedURLException e) { - throw new RuntimeException(e); - } - } - } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java index a7dc89afde..7ae50c6bc4 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java @@ -4,18 +4,13 @@ import static dev.langchain4j.data.document.FileSystemDocumentLoader.loadDocumen import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; import static java.time.Duration.ofSeconds; import static java.util.stream.Collectors.joining; +import static org.junit.Assert.assertNotNull; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,13 +33,13 @@ import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; public class ChatWithDocumentLiveTest { - - Logger logger = LoggerFactory.getLogger(ChatWithDocumentLiveTest.class); + + private static final Logger logger = LoggerFactory.getLogger(ChatWithDocumentLiveTest.class); @Test - public void givenChainWithDocument_whenPrompted_thenValidResponse() { + public void givenDocument_whenPrompted_thenValidResponse() { - Document document = loadDocument(toPath("src/test/resources/example-files/simpson's_adventures.txt")); + Document document = loadDocument(Paths.get("src/test/resources/example-files/simpson's_adventures.txt")); DocumentSplitter splitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO)); List segments = splitter.split(document); @@ -81,20 +76,8 @@ public class ChatWithDocumentLiveTest { .content(); logger.info(aiMessage.text()); - Assert.assertNotNull(aiMessage.text()); + assertNotNull(aiMessage.text()); } - private static Path toPath(String fileName) { - try { - URL fileUrl = new File(fileName).toURI() - .toURL(); - System.out.println(new File(fileName).toURI() - .toURL()); - return Paths.get(fileUrl.toURI()); - } catch (URISyntaxException | MalformedURLException e) { - throw new RuntimeException(e); - } - } - } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java index 8f7dcca1cb..cae6a7930a 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java @@ -1,5 +1,14 @@ package com.baeldung.langchain; +import static dev.langchain4j.data.message.UserMessage.userMessage; +import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.TokenWindowChatMemory; @@ -7,18 +16,9 @@ import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.openai.OpenAiTokenizer; -import static dev.langchain4j.data.message.UserMessage.userMessage; -import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Assert; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class ChatWithMemoryLiveTest { - - Logger logger = LoggerFactory.getLogger(ChatWithMemoryLiveTest.class); + + private static final Logger logger = LoggerFactory.getLogger(ChatWithMemoryLiveTest.class); @Test public void givenMemory_whenPrompted_thenValidResponse() { @@ -30,15 +30,16 @@ public class ChatWithMemoryLiveTest { AiMessage answer = model.generate(chatMemory.messages()) .content(); logger.info(answer.text()); - Assert.assertNotNull(answer.text()); chatMemory.add(answer); + assertNotNull(answer.text()); chatMemory.add(userMessage("What is my name?")); AiMessage answerWithName = model.generate(chatMemory.messages()) .content(); logger.info(answerWithName.text()); - assertThat(answerWithName.text().contains("Kumar")); chatMemory.add(answerWithName); + assertThat(answerWithName.text() + .contains("Kumar")); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java index 149858f351..b468b3a065 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java @@ -7,6 +7,6 @@ public class Constants { * registering for free at (https://platform.openai.com/signup) and then by navigating * to "Create new secret key" page at (https://platform.openai.com/account/api-keys). */ - public static String OPEN_AI_KEY = ""; + public static String OPEN_AI_KEY = "demo"; //""; } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java index 31698ee0c7..1350872eb1 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java @@ -1,6 +1,7 @@ package com.baeldung.langchain; import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO; +import static org.junit.Assert.assertNotNull; import java.util.HashMap; import java.util.Map; @@ -14,11 +15,9 @@ import dev.langchain4j.model.input.Prompt; import dev.langchain4j.model.input.PromptTemplate; import dev.langchain4j.model.openai.OpenAiChatModel; -import org.junit.Assert; - public class PromptTemplatesLiveTest { - Logger logger = LoggerFactory.getLogger(PromptTemplatesLiveTest.class); + private static final Logger logger = LoggerFactory.getLogger(PromptTemplatesLiveTest.class); @Test public void givenPromptTemplate_whenSuppliedInput_thenValidResponse() { @@ -37,7 +36,7 @@ public class PromptTemplatesLiveTest { String response = model.generate(prompt.text()); logger.info(response); - Assert.assertNotNull(response); + assertNotNull(response); } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java index 6a6144aa21..9d64d1fc97 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java @@ -2,7 +2,6 @@ package com.baeldung.langchain; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,7 +13,7 @@ import dev.langchain4j.service.AiServices; public class ServiceWithToolsLiveTest { - Logger logger = LoggerFactory.getLogger(ServiceWithToolsLiveTest.class); + private static final Logger logger = LoggerFactory.getLogger(ServiceWithToolsLiveTest.class); static class Calculator { From 2b22ffc5eae54acbae886ff4849c95953e8c556d Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Sun, 29 Oct 2023 23:23:54 +0530 Subject: [PATCH 6/7] Fixed as par some more review comments. --- libraries-llms/README.md | 6 ------ .../com/baeldung/langchain/ChainWithDocumentLiveTest.java | 2 -- .../com/baeldung/langchain/ChatWithDocumentLiveTest.java | 2 -- .../java/com/baeldung/langchain/ChatWithMemoryLiveTest.java | 5 +---- .../com/baeldung/langchain/PromptTemplatesLiveTest.java | 2 -- .../com/baeldung/langchain/ServiceWithToolsLiveTest.java | 5 ----- 6 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 libraries-llms/README.md diff --git a/libraries-llms/README.md b/libraries-llms/README.md deleted file mode 100644 index 2e250d42d6..0000000000 --- a/libraries-llms/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Language Model Integration Libraries - -This module contains articles about libraries for language model integration in Java. - -### Relevant articles -- [Introduction to LangChain](https://www.baeldung.com/langchain) \ No newline at end of file diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java index 804a052990..eec7da99fd 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java @@ -31,7 +31,6 @@ public class ChainWithDocumentLiveTest { @Test public void givenChainWithDocument_whenPrompted_thenValidResponse() { - EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); @@ -61,7 +60,6 @@ public class ChainWithDocumentLiveTest { logger.info(answer); assertNotNull(answer); - } } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java index 7ae50c6bc4..cbbcc7dd23 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java @@ -38,7 +38,6 @@ public class ChatWithDocumentLiveTest { @Test public void givenDocument_whenPrompted_thenValidResponse() { - Document document = loadDocument(Paths.get("src/test/resources/example-files/simpson's_adventures.txt")); DocumentSplitter splitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO)); List segments = splitter.split(document); @@ -77,7 +76,6 @@ public class ChatWithDocumentLiveTest { logger.info(aiMessage.text()); assertNotNull(aiMessage.text()); - } } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java index cae6a7930a..7a67c0be0e 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java @@ -22,7 +22,6 @@ public class ChatWithMemoryLiveTest { @Test public void givenMemory_whenPrompted_thenValidResponse() { - ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY); ChatMemory chatMemory = TokenWindowChatMemory.withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO)); @@ -38,9 +37,7 @@ public class ChatWithMemoryLiveTest { .content(); logger.info(answerWithName.text()); chatMemory.add(answerWithName); - assertThat(answerWithName.text() - .contains("Kumar")); - + assertThat(answerWithName.text()).contains("Kumar"); } } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java index 1350872eb1..b05727f15f 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java @@ -21,7 +21,6 @@ public class PromptTemplatesLiveTest { @Test public void givenPromptTemplate_whenSuppliedInput_thenValidResponse() { - PromptTemplate promptTemplate = PromptTemplate.from("Tell me a {{adjective}} joke about {{content}}.."); Map variables = new HashMap<>(); variables.put("adjective", "funny"); @@ -37,7 +36,6 @@ public class PromptTemplatesLiveTest { String response = model.generate(prompt.text()); logger.info(response); assertNotNull(response); - } } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java index 9d64d1fc97..1df08e6d35 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java @@ -16,7 +16,6 @@ public class ServiceWithToolsLiveTest { private static final Logger logger = LoggerFactory.getLogger(ServiceWithToolsLiveTest.class); static class Calculator { - @Tool("Calculates the length of a string") int stringLength(String s) { return s.length(); @@ -26,17 +25,14 @@ public class ServiceWithToolsLiveTest { int add(int a, int b) { return a + b; } - } interface Assistant { - String chat(String userMessage); } @Test public void givenServiceWithTools_whenPrompted_thenValidResponse() { - Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY)) .tools(new Calculator()) @@ -48,7 +44,6 @@ public class ServiceWithToolsLiveTest { logger.info(answer); assertThat(answer).contains("13"); - } } From 1a2a6582ad81eb7d7a82b5a5fb7185bf631e8546 Mon Sep 17 00:00:00 2001 From: CHANDRAKANT Kumar Date: Mon, 30 Oct 2023 11:05:16 +0530 Subject: [PATCH 7/7] Corrected the name of a constant. --- .../java/com/baeldung/langchain/ChainWithDocumentLiveTest.java | 2 +- .../java/com/baeldung/langchain/ChatWithDocumentLiveTest.java | 2 +- .../java/com/baeldung/langchain/ChatWithMemoryLiveTest.java | 2 +- .../src/test/java/com/baeldung/langchain/Constants.java | 2 +- .../java/com/baeldung/langchain/PromptTemplatesLiveTest.java | 2 +- .../java/com/baeldung/langchain/ServiceWithToolsLiveTest.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java index eec7da99fd..39746ce810 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChainWithDocumentLiveTest.java @@ -45,7 +45,7 @@ public class ChainWithDocumentLiveTest { ingestor.ingest(document); ChatLanguageModel chatModel = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_AI_KEY) + .apiKey(Constants.OPENAI_API_KEY) .timeout(ofSeconds(60)) .build(); diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java index cbbcc7dd23..41540f4888 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithDocumentLiveTest.java @@ -68,7 +68,7 @@ public class ChatWithDocumentLiveTest { Prompt prompt = promptTemplate.apply(variables); ChatLanguageModel chatModel = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_AI_KEY) + .apiKey(Constants.OPENAI_API_KEY) .timeout(ofSeconds(60)) .build(); AiMessage aiMessage = chatModel.generate(prompt.toUserMessage()) diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java index 7a67c0be0e..3d265d3f3f 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ChatWithMemoryLiveTest.java @@ -22,7 +22,7 @@ public class ChatWithMemoryLiveTest { @Test public void givenMemory_whenPrompted_thenValidResponse() { - ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY); + ChatLanguageModel model = OpenAiChatModel.withApiKey(Constants.OPENAI_API_KEY); ChatMemory chatMemory = TokenWindowChatMemory.withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO)); chatMemory.add(userMessage("Hello, my name is Kumar")); diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java index b468b3a065..380415bf9c 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/Constants.java @@ -7,6 +7,6 @@ public class Constants { * registering for free at (https://platform.openai.com/signup) and then by navigating * to "Create new secret key" page at (https://platform.openai.com/account/api-keys). */ - public static String OPEN_AI_KEY = "demo"; //""; + public static String OPENAI_API_KEY = ""; } diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java index b05727f15f..cd2ea642ed 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/PromptTemplatesLiveTest.java @@ -28,7 +28,7 @@ public class PromptTemplatesLiveTest { Prompt prompt = promptTemplate.apply(variables); ChatLanguageModel model = OpenAiChatModel.builder() - .apiKey(Constants.OPEN_AI_KEY) + .apiKey(Constants.OPENAI_API_KEY) .modelName(GPT_3_5_TURBO) .temperature(0.3) .build(); diff --git a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java index 1df08e6d35..7ebfcba4df 100644 --- a/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java +++ b/libraries-llms/src/test/java/com/baeldung/langchain/ServiceWithToolsLiveTest.java @@ -34,7 +34,7 @@ public class ServiceWithToolsLiveTest { @Test public void givenServiceWithTools_whenPrompted_thenValidResponse() { Assistant assistant = AiServices.builder(Assistant.class) - .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPEN_AI_KEY)) + .chatLanguageModel(OpenAiChatModel.withApiKey(Constants.OPENAI_API_KEY)) .tools(new Calculator()) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build();