test corrected
This commit is contained in:
parent
ea25273601
commit
dfd835ba56
|
|
@ -1,4 +1,4 @@
|
|||
package it.cnr.isti.workflow.manager.auth.model;
|
||||
package it.cnr.isti.workflow.manager.auth.repo;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ import lombok.Singular;
|
|||
|
||||
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
|
||||
@Getter
|
||||
public class Block<T extends BlockType, C extends BlockConfiguration<T>> {
|
||||
public class Block<T extends BlockType> {
|
||||
|
||||
final String id = UUID.randomUUID().toString();
|
||||
|
||||
@Builder
|
||||
public Block(C specificConfiguration, String name, T type, @Singular List<String> inputs, @Singular List<String> outputs, @Singular List<Brick> bricks) {
|
||||
public Block(BlockConfiguration<T> specificConfiguration, String name, T type, @Singular List<String> inputs, @Singular List<String> outputs, @Singular List<Brick> bricks) {
|
||||
this.specificConfiguration = specificConfiguration;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
|
|
@ -35,6 +35,6 @@ public class Block<T extends BlockType, C extends BlockConfiguration<T>> {
|
|||
|
||||
List<String> outputs;
|
||||
|
||||
C specificConfiguration;
|
||||
BlockConfiguration<T> specificConfiguration;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public interface BlockFactory<T extends BlockType, C extends BlockConfiguration<
|
|||
* @param configuration the configuration for the block
|
||||
* @return a new Block instance
|
||||
*/
|
||||
Block<T, C> create(@Valid C configuration);
|
||||
Block<T> create(@Valid C configuration);
|
||||
|
||||
/**
|
||||
* Returns the type of block this factory creates.
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import it.cnr.isti.workflow.manager.blocks.Block;
|
||||
import it.cnr.isti.workflow.manager.blocks.configurations.LLMBlockConfiguration;
|
||||
import it.cnr.isti.workflow.manager.blocks.types.LLMBlockType;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Component
|
||||
public class LLMBlockFactory implements BlockFactory<LLMBlockType, LLMBlockConfiguration> {
|
||||
|
|
@ -19,16 +18,7 @@ public class LLMBlockFactory implements BlockFactory<LLMBlockType, LLMBlockConfi
|
|||
@Autowired
|
||||
LLMBlockType blockType;
|
||||
|
||||
@Override
|
||||
public Block<LLMBlockType, LLMBlockConfiguration> create(LLMBlockConfiguration configuration) {
|
||||
String prompt =configuration.getPrompt();
|
||||
Block<LLMBlockType, LLMBlockConfiguration> block = Block.<LLMBlockType, LLMBlockConfiguration>builder()
|
||||
.type(blockType).inputs(retrieveInputs(prompt)).output("response")
|
||||
.specificConfiguration(configuration)
|
||||
.build();
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<LLMBlockType> getBlockType() {
|
||||
|
|
@ -46,4 +36,15 @@ public class LLMBlockFactory implements BlockFactory<LLMBlockType, LLMBlockConfi
|
|||
return names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block<LLMBlockType> create(@Valid LLMBlockConfiguration configuration) {
|
||||
String prompt =configuration.getPrompt();
|
||||
Block<LLMBlockType> block = Block.<LLMBlockType>builder()
|
||||
.type(blockType).inputs(retrieveInputs(prompt)).output("response")
|
||||
.specificConfiguration(configuration)
|
||||
.build();
|
||||
|
||||
return block; }
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,30 @@
|
|||
package it.cnr.isti.workflow.manager.bricks;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class LLMBrick extends Brick {
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import it.cnr.isti.workflow.manager.llms.providers.LLMProvider;
|
||||
|
||||
private final String provider;
|
||||
public class LLMBrick extends Brick {
|
||||
|
||||
@JsonIgnore
|
||||
private final LLMProvider provider;
|
||||
|
||||
private final String model;
|
||||
|
||||
public String generate(String prompt, Map<String, Object> executionParameters) {
|
||||
return provider.generate(model, prompt);
|
||||
}
|
||||
|
||||
public LLMBrick(String provider, String model, String brickManager) {
|
||||
super(provider + "_" + model, brickManager);
|
||||
|
||||
public LLMBrick(LLMProvider provider, String model, String brickManager) {
|
||||
super(provider.getName() + "_" + model, brickManager);
|
||||
this.provider = provider;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getProvider() {
|
||||
return provider;
|
||||
return provider.getName();
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class LLMBrickManager extends BrickManager<LLMBrick> {
|
|||
public List<LLMBrick> getBricks() {
|
||||
List<LLMBrick> bricks = new ArrayList<>();
|
||||
llmProviders.forEach(p -> p.getRegisteredModels().stream()
|
||||
.map(model -> new LLMBrick(p.getClass().getSimpleName(), model, "llmBrickProvider"))
|
||||
.map(model -> new LLMBrick(p, model, "llmBrickProvider"))
|
||||
.forEach(brick -> bricks.add(brick)));
|
||||
return bricks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package it.cnr.isti.workflow.manager.bricks.extensions;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ExecutionBrick<OUTPUT> {
|
||||
|
||||
OUTPUT execute(Map<String, Object> parameters, Map<String, Object> configParameters);
|
||||
}
|
||||
|
|
@ -51,12 +51,12 @@ public class BlocksController {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
@PostMapping
|
||||
public <T extends BlockType, C extends BlockConfiguration<T>> Block<T, C> create(@RequestBody @Valid C blockConfiguration) {
|
||||
public <T extends BlockType, C extends BlockConfiguration<T>> Block<T> create(@RequestBody @Valid C blockConfiguration) {
|
||||
BlockFactory<T, C> factory = (BlockFactory<T, C>) blockFactories.stream()
|
||||
.filter(f -> f.getBlockType().equals(blockConfiguration.getType()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Block factory not found for type: " + blockConfiguration.getType()));
|
||||
Block<T, C> block = factory.create(blockConfiguration);
|
||||
Block<T> block = factory.create(blockConfiguration);
|
||||
return block;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,32 @@
|
|||
package it.cnr.isti.workflow.manager.controllers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import it.cnr.isti.workflow.manager.auth.repo.LoginEntity;
|
||||
import it.cnr.isti.workflow.manager.flows.FlowService;
|
||||
import it.cnr.isti.workflow.manager.flows.model.Flow;
|
||||
import it.cnr.isti.workflow.manager.flows.repo.FlowEntity;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/flows")
|
||||
public class FlowController {
|
||||
|
||||
@Autowired
|
||||
FlowService flowService;
|
||||
|
||||
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<FlowEntity> createFlow(@RequestBody FlowEntity flowEntity) {
|
||||
FlowEntity createdFlow = flowService.createFlow(flowEntity);
|
||||
|
||||
public ResponseEntity<FlowEntity> createFlow(@RequestBody Flow flow, @AuthenticationPrincipal
|
||||
LoginEntity userDetails) {
|
||||
FlowEntity createdFlow = flowService.createFlow(userDetails.getUsername(), flow);
|
||||
return ResponseEntity.ok(createdFlow);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
package it.cnr.isti.workflow.manager.executions;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter()
|
||||
@NoArgsConstructor
|
||||
public class ExecutionContext {
|
||||
|
||||
public enum Status {
|
||||
CREATED(true, false, false),
|
||||
INITIALIZING(true, false, false),
|
||||
READY(true, false, false),
|
||||
RUNNING(false, false, false),
|
||||
WAITING(false, false, true),
|
||||
SUCCESS(false, true, false),
|
||||
ERROR(false, true, false);
|
||||
|
||||
private boolean initState;
|
||||
|
||||
private boolean finalState;
|
||||
private boolean waitingState;
|
||||
|
||||
Status(boolean initState, boolean finalState, boolean waitingState) {
|
||||
this.initState = initState;
|
||||
this.finalState = finalState;
|
||||
this.waitingState = waitingState;
|
||||
}
|
||||
|
||||
public boolean isInitState() {
|
||||
return initState;
|
||||
}
|
||||
|
||||
public boolean isFinalState() {
|
||||
return finalState;
|
||||
}
|
||||
|
||||
public boolean isWaitingState() {
|
||||
return waitingState ;
|
||||
}
|
||||
|
||||
public boolean isRunningState() {
|
||||
return !finalState && !initState && !waitingState;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> inputs = new HashMap<>();
|
||||
|
||||
@Getter()
|
||||
private Map<FieldKey, Object> result = new HashMap<>();
|
||||
|
||||
Long startTime = null;
|
||||
Long endTime = null;
|
||||
|
||||
List<String> stepsUnderExecution = new ArrayList<>();
|
||||
List<String> waitingSteps = new ArrayList<>();
|
||||
Map<String, String> errors = new HashMap<>();
|
||||
List<String> warnings = new ArrayList<>();
|
||||
|
||||
|
||||
Map<String, Map<String, Object>> nodeResult = new HashMap<>();
|
||||
|
||||
Status status = Status.CREATED;
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
if (status == Status.RUNNING) {
|
||||
this.startTime = System.currentTimeMillis();
|
||||
} else if (status == Status.SUCCESS || status == Status.ERROR) {
|
||||
this.endTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void addNodeResult(String nodeId, Map<String, Object> result) {
|
||||
this.nodeResult.put(nodeId, result);
|
||||
}
|
||||
|
||||
public void addResult(String nodeId, String key, Object value) {
|
||||
this.result.put(new FieldKey(nodeId, key), value);
|
||||
}
|
||||
|
||||
public void addInput(String key, Object value) {
|
||||
this.inputs.put(key, value);
|
||||
}
|
||||
|
||||
public void addError(String nodeId, String error) {
|
||||
this.errors.put(nodeId, error);
|
||||
}
|
||||
|
||||
public Map<FieldKey, Object> getExecutionResult() {
|
||||
return Collections.unmodifiableMap(this.result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package it.cnr.isti.workflow.manager.executions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import lombok.Singular;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ExecutorDescriptor {
|
||||
|
||||
|
||||
@NonNull
|
||||
String identifier;
|
||||
@NonNull
|
||||
String name;
|
||||
|
||||
String description;
|
||||
@Singular
|
||||
List<String> inputNames;
|
||||
@Singular
|
||||
List<String> outputNames;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package it.cnr.isti.workflow.manager.executions;
|
||||
|
||||
public record FieldKey(String nodeId, String fieldId) {
|
||||
@Override
|
||||
public final String toString() {
|
||||
return nodeId + ":" + fieldId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package it.cnr.isti.workflow.manager.executions;
|
||||
|
||||
public interface InputConsumer {
|
||||
|
||||
void consumeInput(String key, Object value);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package it.cnr.isti.workflow.manager.executions;
|
||||
|
||||
public interface OutputProducer {
|
||||
|
||||
void produceOutput(String key, Object value);
|
||||
|
||||
void registerConsumer(InputConsumer consumer );
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package it.cnr.isti.workflow.manager.executions.steps;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class Input {
|
||||
|
||||
String name;
|
||||
private Object value = null;
|
||||
|
||||
private boolean registered = false;
|
||||
|
||||
Input(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected void registered() {
|
||||
this.registered = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package it.cnr.isti.workflow.manager.executions.steps;
|
||||
|
||||
import it.cnr.isti.workflow.manager.blocks.Block;
|
||||
import it.cnr.isti.workflow.manager.blocks.types.LLMBlockType;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
|
||||
public class LLMStep extends Step<LLMBlockType> {
|
||||
|
||||
LLMStep(Block<LLMBlockType> block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package it.cnr.isti.workflow.manager.executions.steps;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class Output {
|
||||
|
||||
@Getter
|
||||
String name;
|
||||
|
||||
private List<Input> consumers = List.of();
|
||||
|
||||
Output(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void register(Input input) {
|
||||
this.consumers.add(input);
|
||||
input.registered();
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
for (Input consumer : consumers) {
|
||||
consumer.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package it.cnr.isti.workflow.manager.executions.steps;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import it.cnr.isti.workflow.manager.blocks.Block;
|
||||
import it.cnr.isti.workflow.manager.blocks.types.BlockType;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
|
||||
@Getter
|
||||
public abstract class Step<B extends BlockType> {
|
||||
|
||||
private Block<B> block;
|
||||
|
||||
List<Input> inputs = List.of();
|
||||
List<Output> outputs = List.of();
|
||||
|
||||
protected Step(Block<B> block) {
|
||||
// Initialize the step with the provided block
|
||||
this.block = block;
|
||||
this.block.getOutputs().forEach(outputName -> {
|
||||
Output output = new Output(outputName);
|
||||
this.outputs.add(output);
|
||||
});
|
||||
this.block.getInputs().forEach(inputName -> {
|
||||
Input input = new Input(inputName);
|
||||
this.inputs.add(input);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package it.cnr.isti.workflow.manager.flows;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import it.cnr.isti.workflow.manager.flows.model.Flow;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter(autoApply = false)
|
||||
public class FlowConverter implements AttributeConverter<Flow, String> {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(Flow flow) {
|
||||
if (flow == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.writeValueAsString(flow);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Errore nella serializzazione di Flow in JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flow convertToEntityAttribute(String dbData) {
|
||||
if (dbData == null || dbData.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(dbData, Flow.class);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Errore nella deserializzazione di JSON in Flow", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,15 +15,13 @@ public class FlowService {
|
|||
@Autowired
|
||||
FlowRepository flowRepository;
|
||||
|
||||
public FlowEntity createFlow(String name, String description, String owner, Flow flow) {
|
||||
public FlowEntity createFlow(String owner, Flow flow) {
|
||||
FlowEntity flowEntity = new FlowEntity();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
flowEntity.setCreatedAt(now);
|
||||
flowEntity.setLastUpdateAt(now);
|
||||
flowEntity.setFlow(flow);
|
||||
flowEntity.setOwner(owner);
|
||||
flowEntity.setName(name);
|
||||
flowEntity.setDescription(description);
|
||||
return flowRepository.save(flowEntity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package it.cnr.isti.workflow.manager.flows;
|
||||
package it.cnr.isti.workflow.manager.flows.model;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ package it.cnr.isti.workflow.manager.flows.model;
|
|||
import java.util.List;
|
||||
|
||||
import it.cnr.isti.workflow.manager.blocks.Block;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.Singular;
|
||||
|
||||
@Data
|
||||
|
|
@ -15,8 +17,14 @@ import lombok.Singular;
|
|||
@AllArgsConstructor
|
||||
public class Flow {
|
||||
|
||||
@NonNull
|
||||
@NotBlank
|
||||
String name;
|
||||
|
||||
String description;
|
||||
|
||||
@Singular
|
||||
List<Block<?, ?>> blocks;
|
||||
List<Block<?>> blocks;
|
||||
|
||||
@Singular
|
||||
List<Connection> connections;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package it.cnr.isti.workflow.manager.flows.repo;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import it.cnr.isti.workflow.manager.flows.FlowConverter;
|
||||
import it.cnr.isti.workflow.manager.flows.model.Flow;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
|
|
@ -51,5 +52,6 @@ public class FlowEntity {
|
|||
|
||||
@Lob
|
||||
@Column(name = "flow_data", columnDefinition = "TEXT")
|
||||
@Convert(converter = FlowConverter.class)
|
||||
private Flow flow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||
|
||||
public interface LLMProvider {
|
||||
|
||||
String getName();
|
||||
List<String> getRegisteredModels();
|
||||
String generate(String model, String prompt);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,17 @@ public class GeminiLLMProvider implements LLMProvider {
|
|||
"gemini-1.5-flash",
|
||||
"gemini-1.5-pro",
|
||||
"gemini-2.0-flash",
|
||||
"gemini-2.0-flash-lite"
|
||||
);
|
||||
|
||||
"gemini-2.0-flash-lite");
|
||||
|
||||
public GeminiLLMProvider(WebClient.Builder webClientBuilder) {
|
||||
this.webClientBuilder = webClientBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "GeminiLLMProvider";
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
|
@ -40,9 +43,9 @@ public class GeminiLLMProvider implements LLMProvider {
|
|||
public String generate(String model, String prompt) {
|
||||
Objects.requireNonNull(prompt, "prompt cannot be null");
|
||||
Objects.requireNonNull(model, "model cannot be null");
|
||||
if (!MODELS.contains(model))
|
||||
if (!MODELS.contains(model))
|
||||
throw new IllegalArgumentException("Model not supported: " + model);
|
||||
|
||||
|
||||
Map<String, Object> requestBody = Map.of(
|
||||
"contents", List.of( // Usa List.of invece di new Object[]
|
||||
Map.of(
|
||||
|
|
@ -68,7 +71,7 @@ public class GeminiLLMProvider implements LLMProvider {
|
|||
.retryWhen(
|
||||
Retry.backoff(10, Duration.ofSeconds(30))
|
||||
.filter(throwable -> throwable instanceof RuntimeException
|
||||
|| throwable instanceof java.util.concurrent.TimeoutException)
|
||||
|| throwable instanceof java.util.concurrent.TimeoutException)
|
||||
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> new RuntimeException(
|
||||
"Error contacting Gemini API", retrySignal.failure())));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package it.cnr.isti.workflow.manager.llms.providers.ollama;
|
||||
|
||||
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -23,82 +21,88 @@ import reactor.core.publisher.Mono;
|
|||
@Service
|
||||
public class InternalOllamaLLMProvider implements LLMProvider {
|
||||
|
||||
private static final Logger log = org.slf4j.LoggerFactory.getLogger(InternalOllamaLLMProvider.class);
|
||||
private String ollamaKey;
|
||||
private static final Logger log = org.slf4j.LoggerFactory.getLogger(InternalOllamaLLMProvider.class);
|
||||
private String ollamaKey;
|
||||
|
||||
private final WebClient.Builder webClientBuilder;
|
||||
private String ollamaURL;
|
||||
private final WebClient.Builder webClientBuilder;
|
||||
private String ollamaURL;
|
||||
|
||||
public InternalOllamaLLMProvider(WebClient.Builder webClientBuilder, @Value("${app.ollama.internal.key}") String ollamakey,
|
||||
@Value("${app.ollama.internal.url}") String ollamaUri) {
|
||||
Objects.requireNonNull(ollamakey, "ollamaKey cannot be null");
|
||||
Objects.requireNonNull(ollamaUri, "ollamaUri cannot be null");
|
||||
this.ollamaKey = ollamakey;
|
||||
this.ollamaURL = ollamaUri;
|
||||
public InternalOllamaLLMProvider(WebClient.Builder webClientBuilder,
|
||||
@Value("${app.ollama.internal.key}") String ollamakey,
|
||||
@Value("${app.ollama.internal.url}") String ollamaUri) {
|
||||
Objects.requireNonNull(ollamakey, "ollamaKey cannot be null");
|
||||
Objects.requireNonNull(ollamaUri, "ollamaUri cannot be null");
|
||||
this.ollamaKey = ollamakey;
|
||||
this.ollamaURL = ollamaUri;
|
||||
|
||||
this.webClientBuilder = webClientBuilder;
|
||||
}
|
||||
|
||||
public String generate(String model, String prompt) {
|
||||
Objects.requireNonNull(prompt, "prompt cannot be null");
|
||||
Objects.requireNonNull(model, "model cannot be null");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, Object> bodyMap = Map.of(
|
||||
"model", model,
|
||||
"prompt", prompt,
|
||||
"stream", false);
|
||||
String requestBody = null;
|
||||
try{
|
||||
requestBody = mapper.writeValueAsString(bodyMap);
|
||||
}catch (Exception e) {
|
||||
log.error("Error serializing request body: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("Error serializing request body", e);
|
||||
this.webClientBuilder = webClientBuilder;
|
||||
}
|
||||
log.debug("ollama body request: {} ", requestBody);
|
||||
|
||||
// Implement the logic to call the Ollama API and return the response
|
||||
WebClient webClient = webClientBuilder.baseUrl(this.ollamaURL).build();
|
||||
@Override
|
||||
public String getName() {
|
||||
return "InternalOllamaLLMProvider";
|
||||
}
|
||||
|
||||
Mono<GenerateResponse> result = webClient.post()
|
||||
.uri(uriBuilder -> uriBuilder.pathSegment("generate")
|
||||
.build())
|
||||
.header("Authorization", "Bearer " + ollamaKey)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(requestBody)
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is5xxServerError(),
|
||||
clientResponse -> clientResponse.bodyToMono(String.class)
|
||||
.defaultIfEmpty("Error: server without body")
|
||||
.flatMap(body -> Mono.error(new RuntimeException("Error 5xx: " + body))))
|
||||
.bodyToMono(GenerateResponse.class) // deserialize JSON in oggetto Java
|
||||
.timeout(Duration.ofMinutes(2));
|
||||
public String generate(String model, String prompt) {
|
||||
Objects.requireNonNull(prompt, "prompt cannot be null");
|
||||
Objects.requireNonNull(model, "model cannot be null");
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, Object> bodyMap = Map.of(
|
||||
"model", model,
|
||||
"prompt", prompt,
|
||||
"stream", false);
|
||||
String requestBody = null;
|
||||
try {
|
||||
requestBody = mapper.writeValueAsString(bodyMap);
|
||||
} catch (Exception e) {
|
||||
log.error("Error serializing request body: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("Error serializing request body", e);
|
||||
}
|
||||
log.debug("ollama body request: {} ", requestBody);
|
||||
|
||||
return result.block().getResponse(); // Placeholder for actual implementation
|
||||
}
|
||||
// Implement the logic to call the Ollama API and return the response
|
||||
WebClient webClient = webClientBuilder.baseUrl(this.ollamaURL).build();
|
||||
|
||||
public List<String> getRegisteredModels() {
|
||||
WebClient webClient = webClientBuilder.baseUrl(this.ollamaURL).build();
|
||||
Mono<GenerateResponse> result = webClient.post()
|
||||
.uri(uriBuilder -> uriBuilder.pathSegment("generate")
|
||||
.build())
|
||||
.header("Authorization", "Bearer " + ollamaKey)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(requestBody)
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is5xxServerError(),
|
||||
clientResponse -> clientResponse.bodyToMono(String.class)
|
||||
.defaultIfEmpty("Error: server without body")
|
||||
.flatMap(body -> Mono.error(new RuntimeException(
|
||||
"Error 5xx: " + body))))
|
||||
.bodyToMono(GenerateResponse.class) // deserialize JSON in oggetto Java
|
||||
.timeout(Duration.ofMinutes(2));
|
||||
|
||||
Mono<List<String>> result = webClient.get()
|
||||
.uri(uriBuilder -> uriBuilder.pathSegment("tags")
|
||||
.build())
|
||||
.header("Authorization", "Bearer " + ollamaKey)
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is5xxServerError(),
|
||||
clientResponse -> clientResponse.bodyToMono(String.class)
|
||||
.defaultIfEmpty("Error: server without body")
|
||||
.flatMap(body -> Mono.error(new RuntimeException("Error 5xx: " + body))))
|
||||
.bodyToMono(ModelResponse.class) // deserialize JSON in oggetto Java
|
||||
.timeout(Duration.ofMinutes(1))
|
||||
.map(modelResponse -> modelResponse.getModels().stream()
|
||||
.map(ModelInfo::getName)
|
||||
.toList());
|
||||
return result.block().getResponse(); // Placeholder for actual implementation
|
||||
}
|
||||
|
||||
return result.block();
|
||||
}
|
||||
public List<String> getRegisteredModels() {
|
||||
WebClient webClient = webClientBuilder.baseUrl(this.ollamaURL).build();
|
||||
|
||||
Mono<List<String>> result = webClient.get()
|
||||
.uri(uriBuilder -> uriBuilder.pathSegment("tags")
|
||||
.build())
|
||||
.header("Authorization", "Bearer " + ollamaKey)
|
||||
.retrieve()
|
||||
.onStatus(
|
||||
status -> status.is5xxServerError(),
|
||||
clientResponse -> clientResponse.bodyToMono(String.class)
|
||||
.defaultIfEmpty("Error: server without body")
|
||||
.flatMap(body -> Mono.error(new RuntimeException(
|
||||
"Error 5xx: " + body))))
|
||||
.bodyToMono(ModelResponse.class) // deserialize JSON in oggetto Java
|
||||
.timeout(Duration.ofMinutes(1))
|
||||
.map(modelResponse -> modelResponse.getModels().stream()
|
||||
.map(ModelInfo::getName)
|
||||
.toList());
|
||||
|
||||
return result.block();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import org.springframework.context.annotation.Profile;
|
|||
|
||||
import it.cnr.isti.workflow.manager.bricks.Brick;
|
||||
import it.cnr.isti.workflow.manager.bricks.BrickManager;
|
||||
import it.cnr.isti.workflow.manager.bricks.LLMBrick;
|
||||
import it.cnr.isti.workflow.manager.llms.providers.LLMProvider;
|
||||
|
||||
@TestConfiguration
|
||||
@Profile("test")
|
||||
public class MyTestConfiguration {
|
||||
|
||||
@Bean(name = "testProvider")
|
||||
|
|
@ -27,4 +28,35 @@ public class MyTestConfiguration {
|
|||
};
|
||||
}
|
||||
|
||||
@Bean(name = "llmBrickTestManager")
|
||||
BrickManager<LLMBrick> llmBrickManagerProvider() {
|
||||
return new BrickManager<LLMBrick>() {
|
||||
@Override
|
||||
public List<LLMBrick> getBricks() {
|
||||
|
||||
LLMProvider provider = new LLMProvider() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "llmTestProvider";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRegisteredModels() {
|
||||
return List.of("testModel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generate(String model, String prompt) {
|
||||
return "Generated response on " + model + " for prompt: " + prompt;
|
||||
}
|
||||
};
|
||||
|
||||
LLMBrick b = new LLMBrick(provider, "testModel", "testBrickManager");
|
||||
|
||||
return List.of(b);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import it.cnr.isti.workflow.manager.MyTestConfiguration;
|
||||
import it.cnr.isti.workflow.manager.blocks.configurations.LLMBlockConfiguration;
|
||||
|
|
@ -23,7 +24,7 @@ public class BlockTest {
|
|||
@Autowired
|
||||
LLMBlockFactory llmBlockFactory;
|
||||
|
||||
@Qualifier("brickTestManager")
|
||||
@Qualifier("llmBrickTestManager")
|
||||
@Autowired
|
||||
BrickManager<LLMBrick> llmBrickManager;
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ public class BlockTest {
|
|||
@Test
|
||||
void createLLMBlock() {
|
||||
BlockFactory<LLMBlockType, LLMBlockConfiguration> factory = llmBlockFactory;
|
||||
LLMBrick brick = llmBrickManager.getBricks().getFirst();
|
||||
LLMBrick brick = (LLMBrick) llmBrickManager.getBricks().getFirst();
|
||||
assertNotNull(factory);
|
||||
assertNotNull(brick);
|
||||
// Assuming LLMBlockConfiguration is a valid configuration class for
|
||||
|
|
@ -44,7 +45,7 @@ public class BlockTest {
|
|||
.brick(brick)
|
||||
.name("master")
|
||||
.build();
|
||||
Block<LLMBlockType, LLMBlockConfiguration> block = factory.create(config);
|
||||
Block<LLMBlockType> block = factory.create(config);
|
||||
System.out.println("Created block: " + block);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import it.cnr.isti.workflow.manager.MyTestConfiguration;
|
||||
import it.cnr.isti.workflow.manager.blocks.Block;
|
||||
|
|
@ -23,11 +22,10 @@ import it.cnr.isti.workflow.manager.bricks.LLMBrick;
|
|||
|
||||
@SpringBootTest
|
||||
@Import(MyTestConfiguration.class)
|
||||
@ActiveProfiles("test")
|
||||
public class BlocksControllerTest {
|
||||
|
||||
|
||||
@Qualifier("brickTestManager")
|
||||
@Qualifier("llmBrickTestManager")
|
||||
@Autowired
|
||||
BrickManager<LLMBrick> llmBrickManager;
|
||||
|
||||
|
|
@ -51,7 +49,7 @@ public class BlocksControllerTest {
|
|||
.name("master")
|
||||
.brick(llmBrickManager.getBricks().get(0))
|
||||
.build();
|
||||
Block<LLMBlockType, LLMBlockConfiguration> block = blocksController.create(config);
|
||||
Block<LLMBlockType> block = blocksController.create(config);
|
||||
assertNotNull(block);
|
||||
assertTrue(block.getInputs().size() == 1);
|
||||
assertTrue(block.getInputs().getFirst().equals("name"));
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import java.util.List;
|
|||
|
||||
@SpringBootTest()
|
||||
@Import(MyTestConfiguration.class)
|
||||
@ActiveProfiles("test")
|
||||
public class BricksControllerTest {
|
||||
|
||||
@Autowired
|
||||
|
|
|
|||
Loading…
Reference in New Issue