diff --git a/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java b/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java index 41da461..250b57b 100644 --- a/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java +++ b/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java @@ -12,7 +12,7 @@ import org.springframework.util.ResourceUtils; import com.fasterxml.jackson.databind.ObjectMapper; -import it.cnr.isti.workflow.manager.executors.ai.AIModel; +import it.cnr.isti.workflow.manager.executors.ai.models.AIModel; import it.cnr.isti.workflow.manager.model.auth.LoginEntity; import it.cnr.isti.workflow.manager.model.flows.Flow; import it.cnr.isti.workflow.manager.model.types.IOType; diff --git a/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java b/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java index 6af69b2..370ea1a 100644 --- a/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java +++ b/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java @@ -4,7 +4,6 @@ import java.util.List; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; diff --git a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/AIModel.java b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/AIModel.java deleted file mode 100644 index d4a5c92..0000000 --- a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/AIModel.java +++ /dev/null @@ -1,15 +0,0 @@ -package it.cnr.isti.workflow.manager.executors.ai; - -import java.util.Map; - -public interface AIModel { - - String getName(); - - String getDescription(); - - String executePrompt(Map parameters, String prompt) throws Throwable; - - public Map> getRequiredPreExecutionParameters(); - -} diff --git a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GeminiModel.java b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GeminiModel.java deleted file mode 100644 index 79956e4..0000000 --- a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GeminiModel.java +++ /dev/null @@ -1,120 +0,0 @@ -package it.cnr.isti.workflow.manager.executors.ai; - -import java.io.IOException; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.ObjectMapper; - -import it.cnr.isti.workflow.manager.executors.ai.services.GeminiService; - -@Service("google-gemini") -public class GeminiModel implements AIModel { - - private static final Logger log = org.slf4j.LoggerFactory.getLogger(GeminiModel.class); - - private GeminiService geminiService; - - GeminiModel(@Autowired GeminiService geminiService) { - this.geminiService = geminiService; - } - - @Override - public String getName() { - return "google-gemini"; - } - - @Override - public String getDescription() { - return "Gemini is an LLM model provided by Google"; - } - - @Override - public String executePrompt(Map parameters, String prompt) throws Throwable { - geminiService.setApiKey("***REMOVED-API-KEY***"); - //log.info("------- REQUEST ------------"); - //log.info(prompt); - //log.info("-------------------"); - String result = geminiService.getResponse(prompt).block(); - ObjectMapper objectMapper = new ObjectMapper(); - - // Deserializzazione della risposta JSON in un oggetto GeminiResponse - GeminiResponse response = objectMapper.readValue(result, GeminiResponse.class); - - - // Estrazione del testo dal primo candidato - String candidateText = response.getCandidates().get(0).getContent().getParts().get(0).getText(); - - //log.info("------- RESPONSE ------------"); - //log.info(candidateText); - //log.info("-------------------"); - - return candidateText; - - } - - - @Override - public Map> getRequiredPreExecutionParameters() { - return Map.of("API-KEY", String.class); - } - -} - -@JsonIgnoreProperties(ignoreUnknown = true) -class GeminiResponse { - private java.util.List candidates; - - public java.util.List getCandidates() { - return candidates; - } - - public void setCandidates(java.util.List candidates) { - this.candidates = candidates; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Candidate { - private Content content; - - public Content getContent() { - return content; - } - - public void setContent(Content content) { - this.content = content; - } - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Content { - private java.util.List parts; - - public java.util.List getParts() { - return parts; - } - - public void setParts(java.util.List parts) { - this.parts = parts; - } - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class Part { - private String text; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - } -} diff --git a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GenericAIExecutor.java b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GenericAIExecutor.java index 1d9a3df..5e0a48a 100644 --- a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GenericAIExecutor.java +++ b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/GenericAIExecutor.java @@ -12,6 +12,7 @@ import org.springframework.stereotype.Service; import it.cnr.isti.workflow.manager.exceptions.ExecutionException; import it.cnr.isti.workflow.manager.executors.Executor; +import it.cnr.isti.workflow.manager.executors.ai.models.AIModel; import it.cnr.isti.workflow.manager.model.ExecutorDescriptor; import it.cnr.isti.workflow.manager.model.types.ParameterDefinition; import it.cnr.isti.workflow.manager.model.types.ParameterType; diff --git a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/OpenRouterModel.java b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/OpenRouterModel.java deleted file mode 100644 index 35caf8f..0000000 --- a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/OpenRouterModel.java +++ /dev/null @@ -1,68 +0,0 @@ -package it.cnr.isti.workflow.manager.executors.ai; - -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import it.cnr.isti.workflow.manager.executors.ai.services.OpenRouterService; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - - - -@Service("open-router") -public class OpenRouterModel implements AIModel { - - private static final Logger log = org.slf4j.LoggerFactory.getLogger(OpenRouterModel.class); - - @Autowired - private OpenRouterService openRouterService; - - @Override - public String getName() { - return "open-router"; - } - - @Override - public String getDescription() { - return "OpenRouter is a free LLM based on DeepSeek v1 model"; - } - - - @Override - public String executePrompt(Map parameters, String prompt) { - openRouterService.setApiKey("***REMOVED-API-KEY***"); - String result = openRouterService.getResponse(prompt).block(); - log.debug("openrouter called with result {}",result); - result = parseResponse(result); - log.debug("post parsing: {}",result); - return result; - - } - - private String parseResponse(String response) { - Pattern pattern = Pattern.compile("\"text\"\\s*:\\s*\"(.*?)\""); - Matcher matcher = pattern.matcher(response); - if (matcher.find()) { - return matcher.group(1); // Estratto il testo - } - return response; - } - - - @Override - public Map> getRequiredPreExecutionParameters() { - return Map.of("API-KEY", String.class); - } - - /* - @Override - public Map execute(Map userParameters, Map preExecutionParameters, - Map inputsFromParent) { - String returnString = (String)executePrompt(preExecutionParameters, (String) inputsFromParent.get("prompt")); - return Map.of("response", returnString); - }*/ - -} - - diff --git a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/services/OpenRouterService.java b/src/main/java/it/cnr/isti/workflow/manager/executors/ai/services/OpenRouterService.java deleted file mode 100644 index 4556907..0000000 --- a/src/main/java/it/cnr/isti/workflow/manager/executors/ai/services/OpenRouterService.java +++ /dev/null @@ -1,53 +0,0 @@ -package it.cnr.isti.workflow.manager.executors.ai.services; - -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.stereotype.Service; - -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; - -import java.util.Map; -import java.time.Duration; -import java.util.List; -import java.util.Objects; - -@Service -public class OpenRouterService { - - private final WebClient.Builder webClientBuilder; - private String apiKey; - private static final String OpenRouter_URL = "https://openrouter.ai/api/v1/chat/completions"; - - public OpenRouterService(WebClient.Builder webClientBuilder) { - HttpClient client = HttpClient.create() - .responseTimeout(Duration.ofMinutes(2)); - this.webClientBuilder = webClientBuilder.clientConnector(new ReactorClientHttpConnector(client)); - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public Mono getResponse(String prompt) { - Objects.requireNonNull(prompt, "prompt cannot be null"); - Map requestBody = Map.of( - "model", "deepseek/deepseek-v3-base:free", - "messages", List.of( Map.of( - "role", "user", - "content", prompt - ) - )); - - WebClient webClient = webClientBuilder.baseUrl(OpenRouter_URL).build(); - Mono result = webClient.post() - .header("Authorization", "Bearer " + apiKey) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(requestBody) - .retrieve() - .bodyToMono(String.class); - - return result; - } -} diff --git a/src/main/java/it/cnr/isti/workflow/manager/model/types/ParameterType.java b/src/main/java/it/cnr/isti/workflow/manager/model/types/ParameterType.java index a4d1605..9a8d6ca 100644 --- a/src/main/java/it/cnr/isti/workflow/manager/model/types/ParameterType.java +++ b/src/main/java/it/cnr/isti/workflow/manager/model/types/ParameterType.java @@ -3,6 +3,7 @@ package it.cnr.isti.workflow.manager.model.types; public enum ParameterType { Select, + DynamicMultiOptions, Text, Boolean, Number diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 23adf20..4ec7eee 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,7 +6,7 @@ spring.datasource.username=${DB_USER:lucio} spring.datasource.password=${DB_PASSWORD:password} spring.datasource.driver-class-name=org.postgresql.Driver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect - +spring.jpa.hibernate.ddl-auto=update # Keycloak #keycloak.realm=${REALM_NAME:wf-editor} @@ -25,9 +25,10 @@ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect # create and drop table, good for testing, production set to none or comment it -spring.jpa.hibernate.ddl-auto=create-drop app.db.init.enabled=false app.security.key=${WFEDITOR_SECRET_KEY:088c65fd2a5ca418a79cd10df5dff15c0a79781c0da4fd43c1c14e4e2d7af1ff} +app.ollama.internal.key=${OLLAMA_INTERNAL_KEY:ollama} +app.ollama.internal.url=${OLLAMA_INTERNAL_URL:https://ollama.internal/api} cors.allowed-origins=${CORS_ALLOWED_ORIGINS:http://localhost:4200} app.import.path=${IMPORT_PATH:/workflow-editor-init} app.import.enabled=true diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties index fd9e7a7..f103d7f 100644 --- a/src/test/resources/test.properties +++ b/src/test/resources/test.properties @@ -4,7 +4,7 @@ spring.datasource.username= spring.datasource.password= # We add the MySQL Dialect so that it understands and generates the query based on MySQL spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect - +spring.jpa.hibernate.ddl-auto=create-drop app.db.init.enabled=true app.import.path=src/main/resources/workflow-editor-init