diff --git a/adaptive-rag/README.md b/adaptive-rag/README.md
new file mode 100644
index 0000000..cc62692
--- /dev/null
+++ b/adaptive-rag/README.md
@@ -0,0 +1,9 @@
+# Langgraph4j - Adaptive RAG
+
+Java implementation of [Adaptive Rag]
+
+
+[Adaptive Rag]:https://github.com/langchain-ai/langgraph/blob/main/examples/rag/langgraph_adaptive_rag.ipynb
+
+
+
diff --git a/adaptive-rag/agentexecutor.puml.png b/adaptive-rag/agentexecutor.puml.png
new file mode 100644
index 0000000..7c6ca0d
Binary files /dev/null and b/adaptive-rag/agentexecutor.puml.png differ
diff --git a/adaptive-rag/correction_process.puml.png b/adaptive-rag/correction_process.puml.png
new file mode 100644
index 0000000..53537c5
Binary files /dev/null and b/adaptive-rag/correction_process.puml.png differ
diff --git a/adaptive-rag/image_to_diagram.puml.png b/adaptive-rag/image_to_diagram.puml.png
new file mode 100644
index 0000000..4de3e2b
Binary files /dev/null and b/adaptive-rag/image_to_diagram.puml.png differ
diff --git a/adaptive-rag/image_to_diagram_with_correction.puml.png b/adaptive-rag/image_to_diagram_with_correction.puml.png
new file mode 100644
index 0000000..8d54190
Binary files /dev/null and b/adaptive-rag/image_to_diagram_with_correction.puml.png differ
diff --git a/adaptive-rag/logging.properties b/adaptive-rag/logging.properties
new file mode 100644
index 0000000..5e1d068
--- /dev/null
+++ b/adaptive-rag/logging.properties
@@ -0,0 +1,6 @@
+handlers=java.util.logging.ConsoleHandler
+.level=INFO
+DiagramCorrectionProcess.level=FINEST
+ImageToDiagramProcess.level=FINEST
+java.util.logging.ConsoleHandler.level=ALL
+java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
diff --git a/adaptive-rag/pom.xml b/adaptive-rag/pom.xml
new file mode 100644
index 0000000..91f8fb8
--- /dev/null
+++ b/adaptive-rag/pom.xml
@@ -0,0 +1,99 @@
+
+ 4.0.0
+
+ org.bsc.langgraph4j
+ langgraph4j-parent
+ 1.0-SNAPSHOT
+
+
+ langgraph4j-adaptive-rag
+ jar
+
+ langgraph4j::adaptive-rag
+
+
+
+
+
+
+
+ org.bsc.langgraph4j
+ langgraph4j-jdk8
+ ${project.version}
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ dev.langchain4j
+ langchain4j
+ ${langchai4j.version}
+
+
+ dev.langchain4j
+ langchain4j-open-ai
+ ${langchai4j.version}
+
+
+ dev.langchain4j
+ langchain4j-chroma
+ ${langchai4j.version}
+
+
+
+ net.sourceforge.plantuml
+ plantuml-mit
+ 1.2024.4
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.slf4j
+ slf4j-jdk14
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+ org.projectlombok
+ lombok-maven-plugin
+ 1.18.20.0
+
+ src/main/java
+
+
+
+
+
diff --git a/adaptive-rag/src/main/docker/docker-compose.yml b/adaptive-rag/src/main/docker/docker-compose.yml
new file mode 100644
index 0000000..6ae1698
--- /dev/null
+++ b/adaptive-rag/src/main/docker/docker-compose.yml
@@ -0,0 +1,19 @@
+services:
+ chroma:
+ container_name: chromadb
+ image: chromadb/chroma:latest
+ command: "--workers 1 --host 0.0.0.0 --port 8000 --proxy-headers --log-config chromadb/log_config.yml --timeout-keep-alive 30"
+ ports:
+ - "8000:8000"
+ environment:
+ - IS_PERSISTENT=TRUE
+ - ALLOW_RESET=TRUE
+ upsert:
+ container_name: upsert
+ build:
+ context: ./upsert
+ dockerfile: Dockerfile
+ depends_on:
+ - chroma
+ environment:
+ - OPENAI_API_KEY=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
diff --git a/adaptive-rag/src/main/docker/upsert/Dockerfile b/adaptive-rag/src/main/docker/upsert/Dockerfile
new file mode 100644
index 0000000..a1e015c
--- /dev/null
+++ b/adaptive-rag/src/main/docker/upsert/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:latest
+
+COPY requirements.txt /tmp
+
+RUN pip install --no-cache-dir --user -r /tmp/requirements.txt
+
+WORKDIR /workspace
+
+COPY index.py /workspace
+
+CMD ["python", "index.py"]
diff --git a/adaptive-rag/src/main/docker/upsert/index.py b/adaptive-rag/src/main/docker/upsert/index.py
new file mode 100644
index 0000000..14f0c8a
--- /dev/null
+++ b/adaptive-rag/src/main/docker/upsert/index.py
@@ -0,0 +1,84 @@
+### Build Index
+
+import chromadb
+from chromadb.config import Settings
+
+from langchain.text_splitter import RecursiveCharacterTextSplitter
+from langchain_community.document_loaders import WebBaseLoader
+from langchain_community.vectorstores import Chroma
+from langchain_openai import OpenAIEmbeddings
+
+## see https://stackoverflow.com/a/77925278/521197
+class CustomOpenAIEmbeddings(OpenAIEmbeddings):
+ "make OpenAIEmbeddings compliant with chromadb api"
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def _embed_documents(self, texts):
+ return super().embed_documents(texts) # <--- use OpenAIEmbedding's embedding function
+
+ def __call__(self, input):
+ return self._embed_documents(input) # <--- get the embeddings
+
+
+def upsert_chroma_via_http( client, docs, embedding_function ):
+ import uuid
+
+ client.reset() # resets the database
+ collection = client.create_collection("rag-chroma", embedding_function=CustomOpenAIEmbeddings())
+ for doc in docs:
+ collection.add(
+ ids=[str(uuid.uuid1())],
+ metadatas=doc.metadata,
+ documents=doc.page_content
+ )
+ return client
+
+def upsert_chroma_local():
+ "Add to vectorstore"
+
+ vectorstore = Chroma.from_documents(
+ documents=doc_splits,
+ collection_name="rag-chroma",
+ embedding=embd,
+ )
+ retriever = vectorstore.as_retriever()
+
+def test_query( client, embedding_function ):
+
+ db4 = Chroma(
+ client=client,
+ collection_name="rag-chroma",
+ embedding_function=embedding_function,
+ )
+ query = "What are the types of agent memory?"
+ docs = db4.similarity_search(query)
+ print(docs[0].page_content)
+
+
+# Set embeddings
+embd = OpenAIEmbeddings()
+
+# Docs to index
+urls = [
+ "https://lilianweng.github.io/posts/2023-06-23-agent/",
+ "https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/",
+ "https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/",
+]
+
+# Load
+docs = [WebBaseLoader(url).load() for url in urls]
+docs_list = [item for sublist in docs for item in sublist]
+
+# Split
+text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
+ chunk_size=500, chunk_overlap=0
+)
+doc_splits = text_splitter.split_documents(docs_list)
+
+client = chromadb.HttpClient( host="chromadb", port=8000, settings=Settings(allow_reset=True))
+
+upsert_chroma_via_http( client, doc_splits, embd )
+
+test_query( client, embd)
\ No newline at end of file
diff --git a/adaptive-rag/src/main/docker/upsert/requirements.txt b/adaptive-rag/src/main/docker/upsert/requirements.txt
new file mode 100644
index 0000000..468c90f
--- /dev/null
+++ b/adaptive-rag/src/main/docker/upsert/requirements.txt
@@ -0,0 +1,10 @@
+langchain_community
+langchain-openai
+tiktoken
+langchain
+chromadb
+beautifulsoup4
+#langgraph
+#tavily-python
+#langchain-cohere
+#langchainhub
diff --git a/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Grader.java b/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Grader.java
new file mode 100644
index 0000000..0874523
--- /dev/null
+++ b/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Grader.java
@@ -0,0 +1,33 @@
+package dev.langchain4j.adaptiverag;
+
+import dev.langchain4j.model.input.structured.StructuredPrompt;
+import dev.langchain4j.model.output.structured.Description;
+import dev.langchain4j.service.SystemMessage;
+
+public class Grader {
+
+ /**
+ * Binary score for relevance check on retrieved documents.
+ */
+ public static class Documents {
+
+ @Description("Documents are relevant to the question, 'yes' or 'no'")
+ public String binaryScore;
+ }
+
+ @StructuredPrompt("Retrieved document: \n\n {{document}} \n\n User question: {{question}}")
+ public static class CreateRecipePrompt {
+
+ private String document;
+ private String question;
+ }
+
+ public interface Retrieval {
+
+ @SystemMessage("You are a grader assessing relevance of a retrieved document to a user question. \n" +
+ " If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \n" +
+ " It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n" +
+ " Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.")
+ Documents invoke(String question);
+ }
+}
diff --git a/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Router.java b/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Router.java
new file mode 100644
index 0000000..b890b52
--- /dev/null
+++ b/adaptive-rag/src/main/java/dev/langchain4j/adaptiverag/Router.java
@@ -0,0 +1,32 @@
+package dev.langchain4j.adaptiverag;
+
+import dev.langchain4j.model.output.structured.Description;
+import dev.langchain4j.service.SystemMessage;
+
+/**
+ * Router for user queries to the most relevant datasource.
+ */
+public class Router {
+
+ public enum Type {
+ vectorstore,
+ websearch
+ }
+ /**
+ * Route a user query to the most relevant datasource.
+ */
+ public static class DataSource {
+
+ @Description("Given a user question choose to route it to web search or a vectorstore.")
+ Type datasource;
+ }
+
+
+ public interface Extractor {
+
+ @SystemMessage("You are an expert at routing a user question to a vectorstore or web search.\n" +
+ "The vectorstore contains documents related to agents, prompt engineering, and adversarial attacks.\n" +
+ "Use the vectorstore for questions on these topics. Otherwise, use web-search.")
+ DataSource route(String question);
+ }
+}
diff --git a/adaptive-rag/src/main/java/resources/convert_generic_diagram_to_plantuml.txt b/adaptive-rag/src/main/java/resources/convert_generic_diagram_to_plantuml.txt
new file mode 100644
index 0000000..c9a3da3
--- /dev/null
+++ b/adaptive-rag/src/main/java/resources/convert_generic_diagram_to_plantuml.txt
@@ -0,0 +1,20 @@
+Translate the json data representing the diagram data into a plantuml script considering:
+
+1. The participants' shape must be translated in their plantuml counterpart using the following conversion rules :
+ - "rectangle" shape must be translated into plantuml's "rectangle"
+ - "circle" shape must be translated into plantuml's "circle"
+ - "person" or "stickman" shape must be translated into plantuml's "actor"
+ - "oval" or "ellipse" shape must be translated into plantuml's "usecase"
+ - "cylinder" shape must be translated into plantuml's "database"
+ - "diamond" shape must be translated into plantuml's "hexagon"
+2. Each recognised participant must be written in the form: "" "" as <>
+3. Relations must be the arrow that connect participants
+4. Put diagram description in the legend of the diagram in the form:
+ legend
+
+ end legend
+5. Put diagram title in the form:
+ title ""
+
+diagram data:
+ {{diagram_description}}
diff --git a/adaptive-rag/src/main/java/resources/convert_sequence_diagram_to_plantuml.txt b/adaptive-rag/src/main/java/resources/convert_sequence_diagram_to_plantuml.txt
new file mode 100644
index 0000000..a1aca2d
--- /dev/null
+++ b/adaptive-rag/src/main/java/resources/convert_sequence_diagram_to_plantuml.txt
@@ -0,0 +1,8 @@
+Translate the diagram description into plantUML syntax.
+Also put the diagram description in the legend in the form:
+legend
+
+end legend
+
+diagram description with title {{diagram_title}}:
+{{diagram_description}}
diff --git a/adaptive-rag/src/main/java/resources/describe_diagram_image.txt b/adaptive-rag/src/main/java/resources/describe_diagram_image.txt
new file mode 100644
index 0000000..71a90dc
--- /dev/null
+++ b/adaptive-rag/src/main/java/resources/describe_diagram_image.txt
@@ -0,0 +1,36 @@
+describe the diagram in the image step by step so we can translate it into diagram-as-code syntax.
+
+ Return a markdown code snippet with a JSON object formatted to look like:
+```json
+{
+ "type": string // Diagram tipology (one word). Eg. "sequence", "class", "process", etc."
+ "title": string // Diagram summary (max one line) or title (if any)
+ "participants": array[
+ {
+ "name": string // participant name
+ "shape": string // participant shape
+ "description": string // participant description
+ }
+ ] // list of participants in the diagram
+ "relations": array[
+ {
+ "source": string // source participant
+ "target": string // target participant
+ "description": string // relation description
+ }
+ ] // list of relations in the diagram
+ "containers": array[
+ {
+ "name": string // container name
+ "children": array[
+ string
+ ] // list of contained elements name
+ "description": string // container description
+ }
+ ] // list of participants that contain other ones in the diagram
+ "description": array[
+ string
+ ] // Step by step description of the diagram with clear indication of participants and actions between them.
+}
+```
+Must not include the "JSON schema" in the response
\ No newline at end of file
diff --git a/adaptive-rag/src/main/java/resources/review_diagram.txt b/adaptive-rag/src/main/java/resources/review_diagram.txt
new file mode 100644
index 0000000..a6d09fb
--- /dev/null
+++ b/adaptive-rag/src/main/java/resources/review_diagram.txt
@@ -0,0 +1,24 @@
+You are my PlantUML reviewer:
+
+In the follow PlantUML diagram script there is the error:
+
+{{evaluationError}}.
+
+the wrong element is indicated by a sequence of '^' characters that underline it followed by the kind of error. below an example
+
+Error sample
+----------------
+@startuml
+participant a1
+ b1
+^^^^^^^^^^^^^^^^^^
+ Syntax Error?
+
+In the sample above the error indicates that there is an and must be substituted with a valid one.
+
+Rewrite the PlantUML diagram script, correcting the error and applying this correction to any similar errors you find in the script itself.
+You MUST return only PlantUML script as plain text not using markdown notation
+
+PlantUML diagram script
+----------------
+{{diagramCode}}
diff --git a/adaptive-rag/src/test/java/dev/langchain4j/DotEnvConfig.java b/adaptive-rag/src/test/java/dev/langchain4j/DotEnvConfig.java
new file mode 100644
index 0000000..2fcd12c
--- /dev/null
+++ b/adaptive-rag/src/test/java/dev/langchain4j/DotEnvConfig.java
@@ -0,0 +1,54 @@
+package dev.langchain4j;
+
+
+import java.io.FileReader;
+import java.io.Reader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+import static java.util.Optional.ofNullable;
+
+public interface DotEnvConfig {
+
+ static void load() {
+
+ // Search for .env file
+ Path path = Paths.get(".").toAbsolutePath();
+
+ Path filePath = Paths.get( path.toString(), ".env");
+
+ for( int i=0; !filePath.toFile().exists(); ++i ) {
+ path = path.getParent();
+
+ filePath = Paths.get(path.toString(), ".env");
+
+ if (i == 3) {
+ throw new RuntimeException("no .env file found!");
+ }
+ }
+
+ // load .env contents in System.properties
+ try {
+ final java.util.Properties properties = new java.util.Properties();
+
+ try( Reader r = new FileReader(filePath.toFile())) {
+ properties.load(r);
+ }
+ System.getProperties().putAll(properties);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ static Optional valueOf(String key ) {
+ String value = System.getenv(key);
+ if (value == null) {
+ value = System.getProperty(key);
+ }
+ return ofNullable(value);
+ }
+
+
+}
diff --git a/adaptive-rag/src/test/java/dev/langchain4j/PromptTest.java b/adaptive-rag/src/test/java/dev/langchain4j/PromptTest.java
new file mode 100644
index 0000000..1d1e356
--- /dev/null
+++ b/adaptive-rag/src/test/java/dev/langchain4j/PromptTest.java
@@ -0,0 +1,48 @@
+package dev.langchain4j;
+
+import dev.langchain4j.model.input.Prompt;
+import dev.langchain4j.model.input.PromptTemplate;
+import org.junit.jupiter.api.Test;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import static org.bsc.langgraph4j.utils.CollectionsUtils.mapOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PromptTest {
+
+ private String readPromptTemplate( String resourceName ) throws Exception {
+ final ClassLoader classLoader = getClass().getClassLoader();
+ final InputStream inputStream = classLoader.getResourceAsStream(resourceName);
+ if (inputStream == null) {
+ throw new IllegalArgumentException("File not found: " + resourceName);
+ }
+ try( final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)) ) {
+ StringBuilder result = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ result.append(line).append('\n');
+ }
+ return result.toString();
+ }
+ }
+ @Test
+ void loadPrompt() throws Exception {
+
+ String template = readPromptTemplate("prompt_template.txt");
+ assertNotNull(template);
+
+ Prompt systemMessage = PromptTemplate.from( template )
+ .apply( mapOf( "format_instructions", "{ schema: true }"));
+
+ assertNotNull(systemMessage);
+ String result = "describe the diagram in the image step by step so we can translate it into diagram-as-code syntax. \n" +
+ "\n" +
+ " { schema: true }\n" +
+ "Must not include the \"JSON schema\" in the response\n";
+ assertEquals( result, systemMessage.text() );
+ }
+}
diff --git a/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/ChromaTest.java b/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/ChromaTest.java
new file mode 100644
index 0000000..fe7fe09
--- /dev/null
+++ b/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/ChromaTest.java
@@ -0,0 +1,58 @@
+package dev.langchain4j.adaptiverag;
+
+import dev.langchain4j.DotEnvConfig;
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingMatch;
+import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
+import dev.langchain4j.store.embedding.EmbeddingSearchResult;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import dev.langchain4j.store.embedding.chroma.ChromaEmbeddingStore;
+
+import java.io.FileInputStream;
+import java.time.Duration;
+import java.util.List;
+import java.util.logging.LogManager;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ChromaTest {
+
+ @BeforeEach
+ public void init() throws Exception {
+ FileInputStream configFile = new FileInputStream("logging.properties");
+ LogManager.getLogManager().readConfiguration(configFile);
+
+ DotEnvConfig.load();
+ }
+
+ @Test
+ public void connect() throws Exception {
+ String openApiKey = DotEnvConfig.valueOf("OPENAI_API_KEY")
+ .orElseThrow( () -> new IllegalArgumentException("no APIKEY provided!"));
+
+ ChromaEmbeddingStore chroma = new ChromaEmbeddingStore(
+ "http://localhost:8000",
+ "rag-chroma",
+ Duration.ofMinutes(2) );
+
+ OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
+ .apiKey(openApiKey)
+ .build();
+ Embedding queryEmbedding = embeddingModel.embed( "What are the types of agent memory?" ).content();
+
+ EmbeddingSearchRequest query = EmbeddingSearchRequest.builder()
+ .queryEmbedding( queryEmbedding )
+ .maxResults( 3 )
+ .minScore( 0.0 )
+ .build();
+ EmbeddingSearchResult relevant = chroma.search( query );
+
+ List> matches = relevant.matches();
+
+ assertEquals( 3, matches.size() );
+ System.out.println( matches );
+ }
+}
diff --git a/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/RouteTest.java b/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/RouteTest.java
new file mode 100644
index 0000000..db7ced9
--- /dev/null
+++ b/adaptive-rag/src/test/java/dev/langchain4j/adaptiverag/RouteTest.java
@@ -0,0 +1,48 @@
+package dev.langchain4j.adaptiverag;
+
+import dev.langchain4j.DotEnvConfig;
+import dev.langchain4j.model.chat.ChatLanguageModel;
+import dev.langchain4j.model.openai.OpenAiChatModel;
+import dev.langchain4j.service.AiServices;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.FileInputStream;
+import java.time.Duration;
+import java.util.logging.LogManager;
+
+public class RouteTest {
+
+ @BeforeEach
+ public void init() throws Exception {
+ FileInputStream configFile = new FileInputStream("logging.properties");
+ LogManager.getLogManager().readConfiguration(configFile);
+
+ DotEnvConfig.load();
+ }
+ @Test
+ public void route() {
+ String openApiKey = DotEnvConfig.valueOf("OPENAI_API_KEY")
+ .orElseThrow( () -> new IllegalArgumentException("no APIKEY provided!"));
+
+ ChatLanguageModel chatLanguageModel = OpenAiChatModel.builder()
+ .apiKey( openApiKey )
+ .modelName( "gpt-3.5-turbo-0125" )
+ .timeout(Duration.ofMinutes(2))
+ .logRequests(true)
+ .logResponses(true)
+ .maxRetries(2)
+ .temperature(0.0)
+ .maxTokens(2000)
+ .build();
+
+ Router.Extractor extractor = AiServices.create(Router.Extractor.class, chatLanguageModel);
+
+ String text = "What are the stock options?";
+
+
+ Router.DataSource ds = extractor.route(text);
+
+ System.out.println( ds.datasource ); // Person { firstName = "John", las
+ }
+}
diff --git a/adaptive-rag/src/test/resources/01_expected_result.txt b/adaptive-rag/src/test/resources/01_expected_result.txt
new file mode 100644
index 0000000..8fa31a0
--- /dev/null
+++ b/adaptive-rag/src/test/resources/01_expected_result.txt
@@ -0,0 +1,8 @@
+@startuml
+participant Alice
+participant Bob
+participant Jack
+diamond "My Friend" as M
+Bob --> Alice : hello
+M --> Jack
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/01_wrong_result.txt b/adaptive-rag/src/test/resources/01_wrong_result.txt
new file mode 100644
index 0000000..644abef
--- /dev/null
+++ b/adaptive-rag/src/test/resources/01_wrong_result.txt
@@ -0,0 +1,8 @@
+@startuml
+participant Alice
+oval Bob
+participant Jack
+diamond "My Friend" as M
+Bob --> Alice : hello
+M --> Jack
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/02_expected_result.txt b/adaptive-rag/src/test/resources/02_expected_result.txt
new file mode 100644
index 0000000..902adfa
--- /dev/null
+++ b/adaptive-rag/src/test/resources/02_expected_result.txt
@@ -0,0 +1,7 @@
+@startuml
+actor Alice
+actor Bob
+actor Jack
+actor MyFriend
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/02_wrong_result.txt b/adaptive-rag/src/test/resources/02_wrong_result.txt
new file mode 100644
index 0000000..d4f7bce
--- /dev/null
+++ b/adaptive-rag/src/test/resources/02_wrong_result.txt
@@ -0,0 +1,7 @@
+@startuml
+actor Alice
+oval Bob
+actor Jack
+oval MyFriend
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/03_expected_result.txt b/adaptive-rag/src/test/resources/03_expected_result.txt
new file mode 100644
index 0000000..f0b4589
--- /dev/null
+++ b/adaptive-rag/src/test/resources/03_expected_result.txt
@@ -0,0 +1,7 @@
+@startuml
+actor Bob
+actor Alice
+actor Jack
+rectangle MyFriend
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/03_wrong_result.txt b/adaptive-rag/src/test/resources/03_wrong_result.txt
new file mode 100644
index 0000000..456263b
--- /dev/null
+++ b/adaptive-rag/src/test/resources/03_wrong_result.txt
@@ -0,0 +1,7 @@
+@startuml
+oval Bob
+actor Alice
+actor Jack
+rectangle MyFriend
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/04_expected_result.txt b/adaptive-rag/src/test/resources/04_expected_result.txt
new file mode 100644
index 0000000..68cfc58
--- /dev/null
+++ b/adaptive-rag/src/test/resources/04_expected_result.txt
@@ -0,0 +1,7 @@
+@startuml
+actor Bob
+rect MyFriend
+actor Alice
+actor Jack
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/04_wrong_result.txt b/adaptive-rag/src/test/resources/04_wrong_result.txt
new file mode 100644
index 0000000..babb8b0
--- /dev/null
+++ b/adaptive-rag/src/test/resources/04_wrong_result.txt
@@ -0,0 +1,7 @@
+@startuml
+oval Bob
+rect MyFriend
+actor Alice
+actor Jack
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/05_expected_result.txt b/adaptive-rag/src/test/resources/05_expected_result.txt
new file mode 100644
index 0000000..beb4a98
--- /dev/null
+++ b/adaptive-rag/src/test/resources/05_expected_result.txt
@@ -0,0 +1,7 @@
+@startuml
+diamond MyFriend
+actor Alice
+actor Jack
+oval Bob
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/05_wrong_result.txt b/adaptive-rag/src/test/resources/05_wrong_result.txt
new file mode 100644
index 0000000..beb4a98
--- /dev/null
+++ b/adaptive-rag/src/test/resources/05_wrong_result.txt
@@ -0,0 +1,7 @@
+@startuml
+diamond MyFriend
+actor Alice
+actor Jack
+oval Bob
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/06_expected_result.txt b/adaptive-rag/src/test/resources/06_expected_result.txt
new file mode 100644
index 0000000..97c1973
--- /dev/null
+++ b/adaptive-rag/src/test/resources/06_expected_result.txt
@@ -0,0 +1,7 @@
+@startuml
+rectangle MyFriend
+actor Alice
+actor Jack
+rectangle Bob
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/06_wrong_result.txt b/adaptive-rag/src/test/resources/06_wrong_result.txt
new file mode 100644
index 0000000..35521b3
--- /dev/null
+++ b/adaptive-rag/src/test/resources/06_wrong_result.txt
@@ -0,0 +1,8 @@
+@startuml
+allowmixing
+diamond MyFriend
+actor Alice
+actor Jack
+oval Bob
+Bob --> Alice : hello
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/07_expected_result.txt b/adaptive-rag/src/test/resources/07_expected_result.txt
new file mode 100644
index 0000000..e30d4d7
--- /dev/null
+++ b/adaptive-rag/src/test/resources/07_expected_result.txt
@@ -0,0 +1,6 @@
+@startuml
+actor Alice
+rectangle "first Element"
+rectangle "second Element"
+Alice --> "first Element"
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/07_wrong_result.txt b/adaptive-rag/src/test/resources/07_wrong_result.txt
new file mode 100644
index 0000000..6ad9764
--- /dev/null
+++ b/adaptive-rag/src/test/resources/07_wrong_result.txt
@@ -0,0 +1,6 @@
+@startuml
+actor Alice
+rectangle "first Element"
+rectangle "second Element"
+Alice --> first element
+@enduml
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/LangChainAgents.png b/adaptive-rag/src/test/resources/LangChainAgents.png
new file mode 100644
index 0000000..a1e4927
Binary files /dev/null and b/adaptive-rag/src/test/resources/LangChainAgents.png differ
diff --git a/adaptive-rag/src/test/resources/convert_generic_diagram_to_plantuml.txt b/adaptive-rag/src/test/resources/convert_generic_diagram_to_plantuml.txt
new file mode 100644
index 0000000..52d0df1
--- /dev/null
+++ b/adaptive-rag/src/test/resources/convert_generic_diagram_to_plantuml.txt
@@ -0,0 +1,20 @@
+Translate the json data representing the diagram data into a plantuml script considering:
+
+- The participants' shape must be translated in their plantuml counterpart using the following table :
+"rectangle" translate to "rectangle"
+"circle" translate to "circle"
+"person" translate to "actor"
+"stickman" translate to "actor"
+"oval" translate to "use case"
+"cylinder" translate to "database"
+"diamond" translate to "hexagon"
+
+ - each recognised participant must be written in the form: "" "" as <>
+- relations must be the arrow that connect participants
+- put diagram description in the legend of the diagram in the form:
+ legend
+
+ end legend
+
+diagram data:
+ {{diagram_description}}
diff --git a/adaptive-rag/src/test/resources/convert_sequence_diagram_to_plantuml.txt b/adaptive-rag/src/test/resources/convert_sequence_diagram_to_plantuml.txt
new file mode 100644
index 0000000..a1aca2d
--- /dev/null
+++ b/adaptive-rag/src/test/resources/convert_sequence_diagram_to_plantuml.txt
@@ -0,0 +1,8 @@
+Translate the diagram description into plantUML syntax.
+Also put the diagram description in the legend in the form:
+legend
+
+end legend
+
+diagram description with title {{diagram_title}}:
+{{diagram_description}}
diff --git a/adaptive-rag/src/test/resources/describe_diagram_image.txt b/adaptive-rag/src/test/resources/describe_diagram_image.txt
new file mode 100644
index 0000000..be2c54e
--- /dev/null
+++ b/adaptive-rag/src/test/resources/describe_diagram_image.txt
@@ -0,0 +1,36 @@
+describe the diagram in the image step by step so we can translate it into diagram-as-code syntax.
+
+ Return a markdown code snippet with a JSON object formatted to look like:
+```json
+{
+ "type": string // Diagram typology (one word). Eg. "sequence", "class", "process", etc."
+ "title": string // Diagram summary (max one line) or title (if any)
+ "participants": array[
+ {
+ "name": string // participant name
+ "shape": string // participant shape
+ "description": string // participant description
+ }
+ ] // list of participants in the diagram
+ "relations": array[
+ {
+ "source": string // source participant
+ "target": string // target participant
+ "description": string // relation description
+ }
+ ] // list of relations in the diagram
+ "containers": array[
+ {
+ "name": string // container name
+ "children": array[
+ string
+ ] // list of contained elements name
+ "description": string // container description
+ }
+ ] // list of participants that contain other ones in the diagram
+ "description": array[
+ string
+ ] // Step by step description of the diagram with clear indication of participants and actions between them.
+}
+```
+Must not include the "JSON schema" in the response
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/describe_result.txt b/adaptive-rag/src/test/resources/describe_result.txt
new file mode 100644
index 0000000..1dc4711
--- /dev/null
+++ b/adaptive-rag/src/test/resources/describe_result.txt
@@ -0,0 +1,61 @@
+```json
+{
+ "type": "process",
+ "title": "User Request Routing",
+ "participants": [
+ {
+ "name": "User",
+ "shape": "rectangle",
+ "description": "The user initiating the request"
+ },
+ {
+ "name": "Supervisor",
+ "shape": "rectangle",
+ "description": "The entity responsible for routing the request"
+ },
+ {
+ "name": "Agent 1",
+ "shape": "ellipse",
+ "description": "A potential handler of the request"
+ },
+ {
+ "name": "Agent 2",
+ "shape": "ellipse",
+ "description": "Another potential handler of the request"
+ },
+ {
+ "name": "Agent 3",
+ "shape": "ellipse",
+ "description": "Another potential handler of the request"
+ }
+ ],
+ "relations": [
+ {
+ "source": "User",
+ "target": "Supervisor",
+ "description": "The user sends a request to the supervisor"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 1",
+ "description": "The supervisor routes the request to Agent 1"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 2",
+ "description": "The supervisor routes the request to Agent 2"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 3",
+ "description": "The supervisor routes the request to Agent 3"
+ }
+ ],
+ "containers": [],
+ "description": [
+ "A User sends a request to the Supervisor.",
+ "The Supervisor then has the option to route the request to one of three agents: Agent 1, Agent 2, or Agent 3.",
+ "The routing is represented by dashed arrows labeled 'route' from the Supervisor to each Agent."
+ ]
+}
+```
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/diagram_data.json b/adaptive-rag/src/test/resources/diagram_data.json
new file mode 100644
index 0000000..a762ba7
--- /dev/null
+++ b/adaptive-rag/src/test/resources/diagram_data.json
@@ -0,0 +1,59 @@
+{
+ "type": "process",
+ "title": "User Request Routing",
+ "participants": [
+ {
+ "name": "User",
+ "shape": "rectangle",
+ "description": "The user initiating the request"
+ },
+ {
+ "name": "Supervisor",
+ "shape": "rectangle",
+ "description": "The entity responsible for routing the request"
+ },
+ {
+ "name": "Agent 1",
+ "shape": "ellipse",
+ "description": "A potential handler of the request"
+ },
+ {
+ "name": "Agent 2",
+ "shape": "ellipse",
+ "description": "Another potential handler of the request"
+ },
+ {
+ "name": "Agent 3",
+ "shape": "ellipse",
+ "description": "Another potential handler of the request"
+ }
+ ],
+ "relations": [
+ {
+ "source": "User",
+ "target": "Supervisor",
+ "description": "The user sends a request to the Supervisor"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 1",
+ "description": "The Supervisor routes the request to Agent 1"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 2",
+ "description": "The Supervisor routes the request to Agent 2"
+ },
+ {
+ "source": "Supervisor",
+ "target": "Agent 3",
+ "description": "The Supervisor routes the request to Agent 3"
+ }
+ ],
+ "containers": [],
+ "description": [
+ "The User sends a request to the Supervisor.",
+ "The Supervisor receives the request and has the option to route it to one of three agents: Agent 1, Agent 2, or Agent 3.",
+ "The routing from the Supervisor to the agents is represented by dashed arrows, indicating potential routes."
+ ]
+}
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/prompt_template.txt b/adaptive-rag/src/test/resources/prompt_template.txt
new file mode 100644
index 0000000..902a164
--- /dev/null
+++ b/adaptive-rag/src/test/resources/prompt_template.txt
@@ -0,0 +1,4 @@
+describe the diagram in the image step by step so we can translate it into diagram-as-code syntax.
+
+ {{format_instructions}}
+Must not include the "JSON schema" in the response
\ No newline at end of file
diff --git a/adaptive-rag/src/test/resources/review_diagram.txt b/adaptive-rag/src/test/resources/review_diagram.txt
new file mode 100644
index 0000000..43795c6
--- /dev/null
+++ b/adaptive-rag/src/test/resources/review_diagram.txt
@@ -0,0 +1,33 @@
+You are my PlantUML reviewer:
+
+In the follow PlantUML diagram script there is the error:
+
+{{evaluationError}}.
+
+the wrong element is indicated by a sequence of '^' characters that underline it followed by the kind of error. below an example
+
+Error sample
+----------------
+@startuml
+participant a1
+ b1
+^^^^^^^^^^^^^^^^^^
+ Syntax Error?
+
+In the sample above the error indicates that there is an and must be substituted with a valid one.
+
+Rewrite the PlantUML diagram script, correcting the error and applying this correction to any similar errors you find in the script itself.
+Correct diagram considering:
+- mixing is not admitted so if the diagram is not a class diagram "diamond" must be translated in "rectangle"
+
+
+You MUST return only PlantUML script as plain text not using markdown notation
+
+PlantUML diagram script
+----------------
+{{diagramCode}}
+
+
+
+
+
diff --git a/adaptive-rag/src/test/resources/supervisor-diagram.png b/adaptive-rag/src/test/resources/supervisor-diagram.png
new file mode 100644
index 0000000..898f753
Binary files /dev/null and b/adaptive-rag/src/test/resources/supervisor-diagram.png differ