### Java Usage Example with Redis Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-redis.adoc Example demonstrating how to use the Redis document store for ingesting data with Quarkus LangChain4j after installation and configuration. ```java import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.DocumentSplitter; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.OnnxEmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore; import java.util.List; public class IngestorExampleWithRedis { public static void main(String[] args) { // Configure Redis connection details String redisHost = System.getenv("REDIS_HOST"); Integer redisPort = Integer.parseInt(System.getenv("REDIS_PORT")); // Initialize RedisEmbeddingStore EmbeddingStore embeddingStore = RedisEmbeddingStore.builder() .host(redisHost) .port(redisPort) .dimension(384) // Dimension must match the embedding model .build(); // Initialize an embedding model (e.g., OnnxEmbeddingModel) // Ensure the model path and dimension are correctly configured EmbeddingModel embeddingModel = new OnnxEmbeddingModel( "path/to/your/model/model.onnx", "path/to/your/model/tokenizer.json", 384 ); // Create a document splitter DocumentSplitter splitter = DocumentSplitter.builder() .maxSplitSize(1000) // Max segment size in characters .build(); // Load and split documents (example: from a list of strings) List documents = List.of( Document.from("This is the first document."), Document.from("This is the second document, which is a bit longer.") ); List textSegments = splitter.split(documents); // Embed and add segments to the store for (TextSegment segment : textSegments) { Embedding embedding = embeddingModel.embed(segment.text()).content(); embeddingStore.add(embedding, segment); } System.out.println("Documents ingested successfully into Redis."); } } ``` -------------------------------- ### Example AI Service Test Setup Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/testing.adoc This Java code demonstrates the setup for testing an AI Service used by a Chatbot, including RAG content retriever integration and necessary imports for evaluation. ```java package dev.langchain4j.quarkus; import dev.langchain4j.data.message.UserMessage; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.quarkus.workshop.CustomerSupportAssistant; import dev.langchain4j.rag.AugmentationRequest; import dev.langchain4j.rag.RetrievalAugmentor; import dev.langchain4j.rag.content.Content; import dev.langchain4j.rag.query.Metadata; import io.quarkiverse.langchain4j.evaluation.junit5.Evaluate; import io.quarkiverse.langchain4j.evaluation.junit5.SampleLocation; import io.quarkiverse.langchain4j.evaluation.junit5.ScorerConfiguration; import io.quarkiverse.langchain4j.testing.evaluation.EvaluationReport; import io.quarkiverse.langchain4j.testing.evaluation.EvaluationSample; import io.quarkiverse.langchain4j.testing.evaluation.EvaluationStrategy; import io.quarkiverse.langchain4j.testing.evaluation.Parameters; import io.quarkiverse.langchain4j.testing.evaluation.Samples; ``` -------------------------------- ### Start Documentation Live Reload Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/README.adoc Starts the Quarkus development server for live-reloading documentation. Navigate to the 'docs' directory and run the Maven command. ```shell $ cd docs $ mvn quarkus:dev ``` -------------------------------- ### Install and Use TornadoVM with JDK 21 Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/gpu-llama3/README.md Installs and sets the TornadoVM SDK for JDK 21 using SDKMAN!. Verifies the installation by listing available devices. ```bash sdk install java 21.0.2-open sdk use java 21.0.2-open sdk install tornadovm 3.0.0-opencl sdk use tornadovm 3.0.0-opencl # verify installation tornado --devices ``` -------------------------------- ### Install and Use TornadoVM with JDK 25 Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/gpu-llama3/README.md Installs and sets the TornadoVM SDK for JDK 25 using SDKMAN!. Verifies the installation by listing available devices. ```bash sdk install java 25.0.2-open sdk use java 25.0.2-open sdk install tornadovm 3.0.0-jdk25-opencl sdk use tornadovm 3.0.0-jdk25-opencl # verify installation tornado --devices ``` -------------------------------- ### Install WebSocket Client Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-streamed-responses.adoc Install the `wscat` command-line tool to test WebSocket connections. This client allows you to connect to and interact with WebSocket servers. ```bash npm install -g wscat ``` -------------------------------- ### Start PostgreSQL for Production Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/secure-mcp-client-server/README.md Launch a PostgreSQL instance using Docker for the production environment. ```shell docker run --rm=true --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:17.0 ``` -------------------------------- ### Enable Tool Use Examples Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/anthropic-chat-model.adoc Set this property to true to enable the Tool Use Examples feature. This allows providing sample tool calls directly in tool definitions. When enabled, the extension automatically sends the 'input_examples' metadata key and includes the required beta header. ```properties quarkus.langchain4j.anthropic.chat-model.tool-use-examples.enabled=true ``` -------------------------------- ### Add Few-Shot Examples to AI Service Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-few-shots.adoc Define a method with @UserMessage that inlines input-output examples. The multi-line string contains example pairs and a placeholder for the new query, which Quarkus Langchain4j will replace with the actual text parameter. ```java package io.quarkiverse.langchain4j.samples.fewshots; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; import io.quarkiverse.langchain4j.RegisterAiService; @RegisterAiService @SystemMessage("You are an assistant that classifies text sentiment.") public interface SentimentAiService { @UserMessage("Classify the sentiment of the following text as positive or negative.\n\nINPUT: \"I love this product!\"\nOUTPUT: positive\n\nINPUT: \"I hate this product.\"\nOUTPUT: negative\n\nINPUT: {text}\nOUTPUT:") String classify(String text); } ``` -------------------------------- ### Start Application in Dev Mode with Gemini Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/dynamic-mcp-clients/dynamic-mcp-clients-assistant/README.md Use this command to start the application in development mode when using Gemini as the LLM provider. Ensure the API key is set as an environment variable. ```bash mvn quarkus:dev -Dquarkus.langchain4j.ai.gemini.api-key=$API_KEY ``` -------------------------------- ### Define Tool with Input Examples Metadata Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/anthropic-chat-model.adoc Tools that include examples must define the 'input_examples' metadata. This Java snippet demonstrates defining a 'create_ticket' tool with a metadata string containing an array of input examples, each with a title and optional fields like priority, labels, and date. ```java private static final String METADATA = """ { \"input_examples\": [ { \"title\": \"Login page returns 500 error\", \"priority\": \"critical\", \"labels\": [\"bug\", \"authentication\"], \"date\": \"2024-11-06\" }, { \"title\": \"Update API documentation\", \"date\": \"2024-12-01\" }, { \"title\": \"Brainstorming session\" } ] } """; @Tool(name = "create_ticket", value = "Create a support ticket", metadata = METADATA) public String createTicket(String title, String priority, String date) { return "TICKET-123"; } ``` -------------------------------- ### Create an Agent Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/simple-ollama/src/main/resources/META-INF/resources/index.html Example of creating a simple agent that can use tools. ```java import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.QueryParam; import dev.langchain4j.agent.tool.Tool; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.service.AiServices; public class AgentResource { @Inject ChatLanguageModel chatLanguageModel; interface MyAgent { @Tool String search(String query); String chat(String message); } @GET @Path("/agent") public String askAgent(@QueryParam("query") String query) { MyAgent agent = AiServices.create(MyAgent.class, chatLanguageModel); return agent.chat(query); } // Dummy tool implementation for demonstration public static class DummyTool { @Tool public String search(String query) { return "Results for " + query + ": Some dummy data."; } } } ``` -------------------------------- ### Start Application in Dev Mode with OpenAI Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/dynamic-mcp-clients/dynamic-mcp-clients-assistant/README.md Use this command to start the application in development mode when using OpenAI as the LLM provider. Ensure the API key is set as an environment variable. ```bash mvn quarkus:dev -Dquarkus.langchain4j.openai.api-key=$API_KEY ``` -------------------------------- ### Create a Question Answering System Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/simple-ollama/src/main/resources/META-INF/resources/index.html Example of building a question-answering system with document retrieval. ```java import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.QueryParam; import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.loader.TextDocumentLoader; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.linalg.Matrix; import dev.langchain4j.model.linalg.Vector; import dev.langchain4j.store.embedding.EmbeddingStore; import java.util.List; @Path("/qa") public class QaResource { @Inject EmbeddingModel embeddingModel; @Inject EmbeddingStore embeddingStore; @GET public String answer(@QueryParam("question") String question) { Embedding questionEmbedding = embeddingModel.embed(question).content(); List> matches = embeddingStore.findRelevant(questionEmbedding, 1, 0.8); if (matches.isEmpty()) { return "Sorry, I could not find any relevant information."; } // In a real application, you would use the content of the matched documents to generate an answer. return "Found relevant document: " + matches.get(0).embedded().toString(); } // Helper method to add documents to the store (for demonstration purposes) public void addDocument(String text) { Document document = TextDocumentLoader.from(text); Embedding embedding = embeddingModel.embed(document).content(); embeddingStore.add(embedding, document.metadata()); } } ``` -------------------------------- ### Install JDK and TornadoVM SDK (JDK 21) Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/gpullama3-chat-model.adoc Installs Java 21 and a TornadoVM SDK for a specific backend using SDKMAN!. Ensure you select the correct backend (opencl, ptx, spirv, full). ```shell # Java version sdk install java 21.0.2-open sdk use java 21.0.2-open # TornadoVM SDK sdk install tornadovm 3.0.0- sdk use tornadovm 3.0.0- ``` -------------------------------- ### Install JDK and TornadoVM SDK (JDK 25) Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/gpullama3-chat-model.adoc Installs Java 25 and a TornadoVM SDK for JDK 25 using SDKMAN!. Ensure you select the correct backend (opencl, ptx, spirv, full). ```shell # Java version sdk install java 25.0.2-open sdk use java 25.0.2-open # TornadoVM SDK sdk install tornadovm 3.0.0-jdk25- sdk use tornadovm 3.0.0-jdk25- ``` -------------------------------- ### Run Packaged MCP Server Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/secure-mcp-client-server/README.md Execute the packaged MCP server JAR file to start the server in production. ```shell java -jar target/quarkus-app/quarkus-run.jar ``` -------------------------------- ### Ingestor Example with Milvus Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-milvus-store.adoc Example demonstrating how to use Milvus as an embedding store for ingesting vectorized content and making it retrievable via similarity search within a Quarkus application. ```java package io.quarkiverse.langchain4j.samples; import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.loader.TextDocumentLoader; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.AllMiniLmL6V2QuantizedEmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.MilvusEmbeddingStore; import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @ApplicationScoped public class IngestorExampleWithMilvus { @Inject MilvusEmbeddingStore embeddingStore; private final EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel(); public void ingest() { Document document = TextDocumentLoader.load("src/main/resources/documents/ulysses.txt"); EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .build(); ingestor.ingest(document); } } ``` -------------------------------- ### Configure IBM Granite Chat Model Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/watsonx-chat-model.adoc Example configuration for the ibm/granite-3-3-8b-instruct chat model, including reasoning and response tags. ```properties quarkus.langchain4j.watsonx.chat-model.model-name=ibm/granite-3-3-8b-instruct quarkus.langchain4j.watsonx.chat-model.thinking.tags.think=think quarkus.langchain4j.watsonx.chat-model.thinking.tags.response=response ``` -------------------------------- ### SemanticSimilarityStrategy Examples Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/testing.adoc Instantiate SemanticSimilarityStrategy with a minimum similarity threshold or with an embedding model and threshold. ```java EvaluationStrategy strategy = new SemanticSimilarityStrategy(0.9); EvaluationStrategy strategy2 = new SemanticSimilarityStrategy(embeddingModel, 0.85); ``` -------------------------------- ### Create a Simple Chatbot Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/simple-ollama/src/main/resources/META-INF/resources/index.html Example of creating a simple chatbot using Langchain4j in Quarkus. ```java import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.QueryParam; import dev.langchain4j.model.chat.ChatLanguageModel; @Path("/chat") public class ChatResource { @Inject ChatLanguageModel chatLanguageModel; @GET public String chat(@QueryParam("message") String message) { return chatLanguageModel.generate(message); } } ``` -------------------------------- ### Ingest Documents with Weaviate Embedding Store Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-weaviate.adoc Example demonstrating how to ingest documents into Weaviate using the WeaviateEmbeddingStore. This allows for vector-based retrieval with minimal setup. ```java package io.quarkiverse.langchain4j.samples; 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.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import java.util.List; @ApplicationScoped public class IngestorExampleWithWeaviate { @Inject EmbeddingStore embeddingStore; @Inject EmbeddingModel embeddingModel; public void ingest(List documents) { DocumentSplitter splitter = DocumentSplitters.recursive(300, 0); List textSegments = splitter.split(documents); List embeddings = embeddingModel.embed(textSegments).content().embeddings(); embeddingStore.addAll(embeddings, textSegments); } } ``` -------------------------------- ### Sentiment Classification with Few-Shot Prompting Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-prompt-engineering.adoc Demonstrates how to use few-shot prompting for sentiment classification, providing examples to guide the model towards specific enum-like outputs. ```APIDOC ## Sentiment Classification with Few-Shot Prompting ### Description This example shows how to implement a sentiment classifier using few-shot prompting. By providing examples of movie reviews and their corresponding sentiments (POSITIVE, NEUTRAL, NEGATIVE), the AI model is guided to produce consistent and predictable outputs. ### Method POST (Implicit, as AI services typically involve sending requests to a model) ### Endpoint `/api/sentiment` (Hypothetical endpoint for the AI service) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **review** (String) - Required - The movie review text to classify. ### Request Example ```json { "review": "This movie was absolutely fantastic!" } ``` ### Response #### Success Response (200) - **sentiment** (Sentiment Enum) - The classified sentiment of the review (POSITIVE, NEUTRAL, or NEGATIVE). #### Response Example ```json { "sentiment": "POSITIVE" } ``` ``` -------------------------------- ### Few-Shot Sentiment Classification Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-prompt-engineering.adoc Use few-shot prompting to guide the model to produce predictable enum-like answers. This example classifies movie review sentiment using predefined categories. ```java public enum Sentiment { POSITIVE, NEUTRAL, NEGATIVE } @RegisterAiService public interface SentimentClassifier { @UserMessage(""" Classify the sentiment of each movie review using one of the following categories: POSITIVE, NEUTRAL, or NEGATIVE. Here are a few examples: - "I love this product." - POSITIVE - "Not bad, but could be better." - NEUTRAL - "I'm thoroughly disappointed." - NEGATIVE Review: {review} Sentiment: """) Sentiment classify(String review); } ``` -------------------------------- ### Get Customer Info with Output Filtering Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/guardrails/README.md Example request to retrieve customer information. Sensitive data like SSN and credit card numbers will be redacted by the output guardrail. ```bash curl "http://localhost:8080/email?request=Get%20customer%20information%20for%20customer%20ID%2012345" ``` -------------------------------- ### Create Catalog Directory for Documents Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/chatbot-easy-rag-kotlin/README.md Create a directory named 'catalog' in src/main/resources to store financial product documents. ```shell mkdir -p src/main/resources/catalog ``` -------------------------------- ### Simple Document Ingestion with Recursive Splitter Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-ingestion.adoc Ingest documents using a recursive splitter that chunks text based on token count and overlap. This example demonstrates basic setup for embedding store ingestion. ```java @ApplicationScoped public class IngestorExampleWithPgvector { @Inject PgVectorEmbeddingStore store; @Inject EmbeddingModel embeddingModel; public void ingest(List documents) { EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .documentSplitter(recursive(500, 0)) .build(); ingestor.ingest(documents); } } ``` -------------------------------- ### Audit All AI Service Events with CDI Observers Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/observability.adoc This example demonstrates how to create a CDI bean to observe all AI service events. It covers events like service start, completion, errors, responses, tool executions, and guardrail invocations. ```java import dev.langchain4j.observability.api.event.AiServiceCompletedEvent; import dev.langchain4j.observability.api.event.AiServiceErrorEvent; import dev.langchain4j.observability.api.event.AiServiceResponseReceivedEvent; import dev.langchain4j.observability.api.event.AiServiceStartedEvent; import dev.langchain4j.observability.api.event.InputGuardrailExecutedEvent; import dev.langchain4j.observability.api.event.OutputGuardrailExecutedEvent; import dev.langchain4j.observability.api.event.ToolExecutedEvent; import io.quarkiverse.langchain4j.observability.AiServiceSelector; @ApplicationScoped public class AuditingListener { public void aiServiceStarted(@Observes AiServiceStartedEvent serviceStartedEvent) { // Invoked when the invocation begins on any AI service } public void assistant1ServiceStarted(@Observes @AiServiceSelector(Assistant1.class) AiServiceStartedEvent serviceStartedEvent) { // Invoked when an invocation begins on the Assistant1 AI service } public void aiServiceCompleted(@Observes AiServiceCompletedEvent serviceCompletedEvent) { // Invoked when the final result of any AiService method has been computed } public void assistant1ServiceCompleted(@Observes @AiServiceSelector(Assistant1.class) AiServiceCompletedEvent serviceCompletedEvent) { // Invoked when the final result of the Assistant1 AiService method has been computed } public void aiServiceError(@Observes AiServiceErrorEvent serviceErrorEvent) { // Invoked when there was an exception computing the result of the AiService method } public void assistant2ServiceError(@Observes @AiServiceSelector(Assistant2.class) AiServiceErrorEvent serviceErrorEvent) { // Invoked when there was an exception computing the result of the Assistant2 AiService method } public void serviceResponseReceived(@Observes AiServiceResponseReceivedEvent serviceResponseReceivedEvent) { // Invoked with a response from an LLM on any AI Service. // It is important to note that this can be invoked multiple times when tools exist. } public void toolExecuted(@Observes ToolExecutedEvent toolExecutedEvent) { // Invoked with a tool response from an LLM. // It is important to note that this can be invoked multiple times when tools exist. } public void assistant3ToolExecuted(@Observes @AiServiceSelector(Assistant3.class) ToolExecutedEvent toolExecutedEvent) { // Invoked with a tool response from the Assistant3 AI service. // It is important to note that this can be invoked multiple times when tools exist. } public void inputGuardrailExecuted(@Observes InputGuardrailExecutedEvent inputGuardrailExecutedEvent) { // Invoked after an InputGuardrail is invoked on any AI service // Could be invoked multiple times in a single LLM invocation } public void assistant4InputGuardrailExecuted(@Observes @AiServiceSelector(Assistant4.class) InputGuardrailExecutedEvent inputGuardrailExecutedEvent) { // Invoked after an InputGuardrail is invoked on the Assistant4 AI service // Could be invoked multiple times in a single LLM invocation } public void outputGuardrailExecuted(@Observes OutputGuardrailExecutedEvent outputGuardrailExecutedEvent) { // Invoked after an OutputGuardrail is invoked on any AI service // Could be invoked multiple times in a single LLM invocation } } ``` -------------------------------- ### Verify TornadoVM Installation Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/gpullama3-chat-model.adoc Checks the available TornadoVM devices and the installed TornadoVM version. This helps confirm that the SDK has been correctly installed and configured. ```shell tornado --devices tornado --version ``` -------------------------------- ### Startup Ingestion from File System Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-ingestion.adoc Ingest documents from the file system on application startup. This example resets the vector store and loads documents recursively, using a specific splitter configuration. ```java @ApplicationScoped public class RagIngestion { public void ingest(@Observes StartupEvent ev, // Run on application startup EmbeddingStore store, EmbeddingModel embeddingModel, @ConfigProperty(name = "rag.location") Path documents) { store.removeAll(); // Reset the vector store (for demo purposes only) List list = FileSystemDocumentLoader.loadDocumentsRecursively(documents); EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .documentSplitter(recursive(100, 25)) .build(); ingestor.ingest(list); Log.info("Documents ingested successfully"); } } ``` -------------------------------- ### Verify Ollama Installation Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/ollama-chat-model.adoc Run this command in your terminal to ensure Ollama is installed correctly. ```shell $ ollama --version ``` -------------------------------- ### Run Ollama Model Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-ollama.adoc Verifies the Ollama installation by running the llama3 model. Ensure Ollama is installed and accessible. ```bash ollama run llama3 ``` -------------------------------- ### Configure LLM and MCP Server Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/mcp.adoc Configure your LLM provider and the MCP server. This example shows configuration for OpenAI and a filesystem MCP server. ```properties # Configure your LLM (this example uses OpenAI) quarkus.langchain4j.openai.api-key=sk-... # Configure the filesystem MCP server (requires npm installed) ``` -------------------------------- ### Upload File and Start Text Classification Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/watsonx-chat-model.adoc Upload a local file and immediately start the text classification process. ```java File file = new File("path/to/document"); TextClassificationResponse response = classificationService.uploadAndStartClassification(file); String id = response.metadata().id(); ``` -------------------------------- ### Sample Location Path Resolution Examples Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/testing.adoc Demonstrates different ways to specify paths for sample files using the @SampleLocation annotation. Paths are relative to the project root. ```java @SampleLocation("src/test/resources/samples.yaml") // Relative to project root @SampleLocation("test-data/samples.yaml") // Also relative to project root @SampleLocation("/absolute/path/to/samples.yaml") // Absolute path (not recommended) ``` -------------------------------- ### Custom Chat Memory Provider Supplier Example Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/messages-and-memory.adoc Implement a Supplier for ChatMemoryProvider to provide a custom memory configuration. This example builds a MessageWindowChatMemory with a maximum of 5 messages. ```java public class MyMemoryProviderSupplier implements Supplier { @Override public ChatMemoryProvider get() { return new ChatMemoryProvider() { @Override public ChatMemory get(Object memoryId) { return new MessageWindowChatMemory.Builder().maxMessages(5).build(); } }; } } ``` -------------------------------- ### Java Usage Example with Pinecone Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-pinecone-store.adoc Demonstrates how to use the Pinecone vector store to ingest and retrieve embedded documents, including text segments and metadata. ```java include::{examples-dir}/io/quarkiverse/langchain4j/samples/IngestorExampleWithPinecone.java[] ``` -------------------------------- ### Basic AiJudgeStrategy Example Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/testing.adoc Instantiate AiJudgeStrategy with a ChatModel and a custom evaluation prompt. The prompt should clearly define the evaluation criteria and include placeholders for the response and expected output. ```java EvaluationStrategy strategy = new AiJudgeStrategy(myChatLanguageModel, """ You are an AI evaluating a response and the expected output. You need to evaluate whether the model response is correct or not. Return true if the response is correct, false otherwise. Response to evaluate: {response} Expected output: {expected_output} """); ``` -------------------------------- ### Create a Local Chat Client and Connect to a Chat Route Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/chat-scopes.adoc Demonstrates how to create a local client for invoking chat routes. It sets up event handlers for messages and errors, connects to the 'RagBot' chat route, and processes user input from the console. ```java import io.quarkiverse.langchain4j.chatscopes.LocalChatRoutes; import java.util.Scanner; @QuarkusMain public class ChatApp implements QuarkusApplication { @Inject LocalChatRoutes.Client client; @Override public int run(String... args) throws Exception { LocalChatRoutes.SessionBuilder builder = client.builder() .messageHandler(message -> System.out.println(message)) .errorHandler(message -> System.err.println(message)); LocalChatRoutes.Session session = builder.connect("RagBot"); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { String userMessage = scanner.nextLine().trim(); if (userMessage.isEmpty()) continue; session.chat(userMessage); } return 0; } } ``` -------------------------------- ### Configure Named MCP Servers (GitHub and Filesystem) Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/mcp.adoc Configure one or more MCP servers using named configurations. Each block creates an MCP client with the specified name. Ensure necessary environment variables like GITHUB_PERSONAL_ACCESS_TOKEN are set. ```properties # Configure a GitHub MCP server quarkus.langchain4j.mcp.github.transport-type=stdio quarkus.langchain4j.mcp.github.command=npm,exec,@modelcontextprotocol/server-github quarkus.langchain4j.mcp.github.environment.GITHUB_PERSONAL_ACCESS_TOKEN= # Configure a filesystem MCP server quarkus.langchain4j.mcp.filesystem.transport-type=stdio quarkus.langchain4j.mcp.filesystem.command=npm,exec,@modelcontextprotocol/server-filesystem,/home/user/documents ``` -------------------------------- ### Example SourceAugmenter Implementation Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/response-augmenter.adoc This example demonstrates an `AiResponseAugmenter` that adds sources used to compute the response. It embeds the response, extracts source information from parameters, filters similar sources, and appends them to the original response. ```java @ApplicationScoped public class SourceAugmenter implements AiResponseAugmenter { @Inject EmbeddingModel embeddingModel; record SourceEmbedding(TextSegment textSegment, String file, Embedding embedding) {} @Override public String augment(String response, ResponseAugmenterParams params) { // Only add sources that are similar to the computed response var embeddingOfTheResponse = embeddingModel.embed(response).content(); // You can also: // - Ignore segments not similar enough // - Remove duplicates // - Append the sources to the response List sources = params.augmentationResult() .contents().stream().map(c -> { var embedding = embeddingModel.embed(c.textSegment().text()).content(); // Extract the "source" of the content from the metadata: return new SourceEmbedding(c.textSegment(), c.textSegment().metadata().getString("file"), embedding); }).toList(); // Ignore segments not similar enough Set filtered = filter(embeddingOfTheResponse, sources); // Remove duplicates Set names = new LinkedHashSet<>(); for (var source : filtered) { names.add(source.file()); } // Append the sources to the response return response + " (Sources: " + String.join(", ", names) + ")"; } } ``` -------------------------------- ### Install Quarkus LangChain4j Modules for Main Branch Testing Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/integration-tests/README.md Install Quarkus LangChain4j modules into the local Maven cache before running integration tests from the main branch. This is necessary due to the handling of *-deployment artifacts. ```bash mvn clean install -DskipTests -DskipITs ``` -------------------------------- ### Run JBang Sample Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/samples/jbang-joke-bot/README.md Execute the AI bot sample using JBang. Ensure JBang is installed and the API key is set. ```bash jbang jokes.java ``` ```bash ./jokes.java ``` -------------------------------- ### Ingest and Retrieve Documents with Infinispan Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/rag-infinispan-store.adoc Example demonstrating how to store and retrieve embedded documents using Infinispan as the backend vector store. Ensure Infinispan is running and configured. ```java import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @ApplicationScoped public class IngestorExampleWithInfinispan { @Inject EmbeddingStore embeddingStore; public void ingest() { EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingStore(embeddingStore) .build(); ingestor.ingest(new TextSegment("This is the first document.")); ingestor.ingest(new TextSegment("This is the second document.")); ingestor.ingest(new TextSegment("This is the third document.")); } } ``` -------------------------------- ### Example User Request for Taxi Information Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/guide-semantic-compression.adoc This `curl` command demonstrates a user asking for information about taxi travel time from Athens airport to the city center. It's an example of a user query that might trigger semantic compression if the chat history is long. ```bash curl -X POST http://localhost:8080/chat \ -H "Content-Type: text/plain" \ -d "Thanks, I will take a taxi from the airport to the city center. How long does it take to get from Athens airport to the city center by taxi?" ``` -------------------------------- ### JavaScript WebSocket Client Initialization Source: https://github.com/quarkiverse/quarkus-langchain4j/blob/main/docs/modules/ROOT/pages/chat-scopes.adoc Example of how to include and initialize the JavaScript client for interacting with WebSocket chat routes. Connects to the endpoint and sets up message handling. ```html ``` ```javascript client = new ChatScopesClient(); await client.open("ws://localhost:8080/_chat/routes"); builder = client.builder(); builder.messageHandler(handleMessage); session = await builder.connect("theRoute"); session.chat("hello world"); function handleMessage(data) { // output string message from server console.log("Message: " + data); } ```