From ac3d7edd41282bf55febd18fbb187e3f4a1b1333 Mon Sep 17 00:00:00 2001 From: Andrea Terzani Date: Mon, 30 Jun 2025 11:59:42 +0200 Subject: [PATCH] Aggiungi la classe DocAndSourceCodeTool per la gestione della documentazione e del codice sorgente --- .../stepSolvers/AdvancedAIPromptSolver.java | 42 ++++- .../hermione/tools/DocAndSourceCodeTool.java | 155 ++++++++++++++++++ 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/olympus/hermione/tools/DocAndSourceCodeTool.java diff --git a/src/main/java/com/olympus/hermione/stepSolvers/AdvancedAIPromptSolver.java b/src/main/java/com/olympus/hermione/stepSolvers/AdvancedAIPromptSolver.java index e6bcab9..b8faebe 100644 --- a/src/main/java/com/olympus/hermione/stepSolvers/AdvancedAIPromptSolver.java +++ b/src/main/java/com/olympus/hermione/stepSolvers/AdvancedAIPromptSolver.java @@ -83,9 +83,25 @@ public class AdvancedAIPromptSolver extends StepSolver { switch(tool.trim()){ case "DocumentationTool" -> { logger.info("Instantiating DocumentationTool"); + String selctedProject = ""; + String selectedApplication = ""; + + if(this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project")!=null){ + selctedProject = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project"); + } else { + selctedProject = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("input_project"); + } + if(this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_application")!=null){ + selectedApplication = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_application"); + } else { + selectedApplication = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("input_application"); + } + + this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project"); + tools = new com.olympus.hermione.tools.DocumentationTool( - this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_application"), - this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project"), + selectedApplication, + selctedProject, vectorStore); } @@ -93,6 +109,28 @@ public class AdvancedAIPromptSolver extends StepSolver { logger.info("Instantiating SourceCodeTool"); tools = new com.olympus.hermione.tools.SourceCodeTool(this.discoveryClient); } + case "DocAndSourceCodeTool" -> { + logger.info("Instantiating DocAndSourceCodeTool"); + String selctedProject = ""; + String selectedApplication = ""; + + if(this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project")!=null){ + selctedProject = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_project"); + } else { + selctedProject = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("input_project"); + } + if(this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_application")!=null){ + selectedApplication = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("selected_application"); + } else { + selectedApplication = this.scenarioExecution.getScenarioExecutionInput().getInputs().get("input_application"); + } + + tools = new com.olympus.hermione.tools.DocAndSourceCodeTool( + selectedApplication, + selctedProject, + vectorStore, + this.discoveryClient); + } } } diff --git a/src/main/java/com/olympus/hermione/tools/DocAndSourceCodeTool.java b/src/main/java/com/olympus/hermione/tools/DocAndSourceCodeTool.java new file mode 100644 index 0000000..5709d0d --- /dev/null +++ b/src/main/java/com/olympus/hermione/tools/DocAndSourceCodeTool.java @@ -0,0 +1,155 @@ +package com.olympus.hermione.tools; + +import java.util.List; +import java.util.logging.Logger; + +import org.springframework.ai.document.Document; +import org.springframework.ai.tool.annotation.Tool; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.cloud.client.ServiceInstance; + + +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.web.client.RestTemplate; + +import com.olympus.dto.CodeRagResponse; +import com.olympus.dto.SimilaritySearchCodeInput; + + + +public class DocAndSourceCodeTool { + + + + + private static final Logger logger = Logger.getLogger(DocAndSourceCodeTool.class.getName()); + private static final int DEFAULT_TOP_K = 5; + private static final double DEFAULT_SIMILARITY_THRESHOLD = 0.7; + + private final String application; + private final String project; + private final VectorStore vectorStore; + private DiscoveryClient discoveryClient; + + + public DocAndSourceCodeTool(String application, String project, VectorStore vectorStore, DiscoveryClient discoveryClient) { + this.application = application; + this.project = project; + this.vectorStore = vectorStore; + this.discoveryClient = discoveryClient; + } + + + + + @Tool(description = "Retrieves functional information about the application based on the provided query.\r\n" + // + " * It performs a semantic search over the application's documentation and returns the most relevant results.") + public String getDocumentation(String query) { + + String filterExpression = buildFilterExpression(); + logger.info("[TOOL]LLM Doc&SourceTool getDocumentation for filterExpression: " + filterExpression); + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for query: " + query); + + SearchRequest request = buildSearchRequest(query, filterExpression); + List docs = this.vectorStore.similaritySearch(request); + + logger.info("Number of VDB retrieved documents: " + docs.size()); + + return formatDocumentsResponse(docs); + } + + + + @Tool(description = "Get the source code of a class by fully qualified name") + public String getClassCodeByFullyQualifidClassName(String fullyQualifiedClassName) { + + logger.info("[TOOL]LLM SourceCodeTool getClassCodeByFullyQualifidClassName source code for class: " + fullyQualifiedClassName); + ServiceInstance serviceInstance = discoveryClient.getInstances("source-code-module").get(0); + RestTemplate restTemplate = new RestTemplate(); + + String sourceCodeResponse = + restTemplate.getForEntity(serviceInstance.getUri() + "/getClassDetailedInfo?id="+fullyQualifiedClassName,String.class ).getBody(); + + + return sourceCodeResponse; + } + + + @Tool(description = "Retrieve the source code that match concept with natural language query input ") + public String getCodeBySimilarity(String query) { + + logger.info("[TOOL]LLM SourceCodeTool getCodeBySimilarity source code for class: " + query); + SimilaritySearchCodeInput similaritySearchCodeInput = new SimilaritySearchCodeInput(); + similaritySearchCodeInput.setQuery(query); + similaritySearchCodeInput.setTopK("3"); + similaritySearchCodeInput.setSimilarityThreshold("0.7"); + similaritySearchCodeInput.setFilterExpression(""); + + ServiceInstance serviceInstance = discoveryClient.getInstances("source-code-module").get(0); + RestTemplate restTemplate = new RestTemplate(); + + CodeRagResponse[] ragresponse = + restTemplate.postForEntity(serviceInstance.getUri() + "/similarity-search-code", + similaritySearchCodeInput,CodeRagResponse[].class ).getBody(); + String code=""; + + if (ragresponse == null || ragresponse.length == 0) { + logger.warning("No source code found for the given query: " + query); + return "No source code found for the given query."; + } + + logger.info("Number of source code retrieved documents: " + ragresponse.length); + + + for (CodeRagResponse codeRagResponse : ragresponse) { + code += "SOURCE CODE OF "+codeRagResponse.getCodeType()+" : " + codeRagResponse.getFullyQualifiedName() +" \n"; + code += codeRagResponse.getCode() + "\n"; + code += "-----------------------------------\n"; + } + + return code; + } + + + + private void logRequestDetails(String query) { + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for query: " + query); + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for project: " + this.project); + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for vectorStore: " + this.vectorStore); + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for application: " + this.application); + logger.info("[TOOL]LLM Doc&SourceTool Getting documentation for discoveryClient: " + this.discoveryClient); + } + + + private String buildFilterExpression() { + return "'KsProjectName' == '"+ this.project +"' AND 'KsDoctype' == 'functional'"; + } + + + private SearchRequest buildSearchRequest(String query, String filterExpression) { + return SearchRequest.builder() + .query(query) + .topK(DEFAULT_TOP_K) + .similarityThreshold(DEFAULT_SIMILARITY_THRESHOLD) + .filterExpression(filterExpression) + .build(); + } + + + private String formatDocumentsResponse(List docs) { + if (docs.isEmpty()) { + return "Nessun documento trovato per la query."; + } + + StringBuilder response = new StringBuilder(); + for (Document doc : docs) { + response.append("-------USE THIS AS PART OF YOUR CONTEXT-----------------------------------------\n") + .append(doc.getText()) + .append("------------------------------------------------------------------------------------------\n"); + } + + return response.toString(); + } + +} \ No newline at end of file