Adding sourcecode for reference in the article tracked under BAEL-6970.

This commit is contained in:
CHANDRAKANT Kumar 2023-10-23 14:33:05 +05:30
parent 193fa95e8c
commit 7392b003f1
11 changed files with 420 additions and 0 deletions

6
libraries-llms/README.md Normal file
View File

@ -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)

43
libraries-llms/pom.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libraries-llms</artifactId>
<name>libraries-llms</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!-- dependencies for langchain4j -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
<properties>
<langchain4j.version>0.23.0</langchain4j.version>
</properties>
</project>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -
%msg%n
</pattern>
</encoder>
</appender>
<logger name="io.ebean.DDL" level="TRACE" />
<logger name="io.ebean.SQL" level="TRACE" />
<logger name="io.ebean.TXN" level="TRACE" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -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<TextSegment> segments = splitter.split(document);
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
List<Embedding> embeddings = embeddingModel.embedAll(segments)
.content();
EmbeddingStore<TextSegment> 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<EmbeddingMatch<TextSegment>> 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<String, Object> 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);
}
}
}

View File

@ -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<TextSegment> 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);
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.langchain;
public class Constants {
public static String OPEN_API_KEY = "demo";
}

View File

@ -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<String, Object> 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);
}
}

View File

@ -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);
}
}

View File

@ -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.

View File

@ -936,6 +936,7 @@
<module>spring-di-4</module>
<module>spring-kafka-2</module>
<!--<module>java-panama</module> Java-19 module-->
<module>libraries-llms</module>
</modules>
<properties>
@ -1223,6 +1224,7 @@
<module>spring-di-4</module>
<module>spring-kafka-2</module>
<!--<module>java-panama</module> Java-19 module-->
<module>libraries-llms</module>
</modules>
<properties>