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