use of org.kie.kogito.explainability.api.BaseExplainabilityRequest in project kogito-apps by kiegroup.
the class ExplainabilityMessagingHandler method handleCloudEvent.
@SuppressWarnings("unchecked")
private CompletionStage<Void> handleCloudEvent(CloudEvent cloudEvent) {
BaseExplainabilityRequest request = null;
try {
if (cloudEvent.getData() != null) {
request = objectMapper.readValue(cloudEvent.getData().toBytes(), BaseExplainabilityRequest.class);
}
} catch (IOException e) {
LOGGER.error("Unable to deserialize CloudEvent data as ExplainabilityRequest", e);
return CompletableFuture.completedFuture(null);
}
if (request == null) {
LOGGER.error("Received CloudEvent with id {} from {} with empty data", cloudEvent.getId(), cloudEvent.getSource());
return CompletableFuture.completedFuture(null);
}
LOGGER.info("Received CloudEvent with id {} from {}", cloudEvent.getId(), cloudEvent.getSource());
return explanationService.explainAsync(request, this::sendEvent).thenApply(this::sendEvent);
}
use of org.kie.kogito.explainability.api.BaseExplainabilityRequest in project kogito-apps by kiegroup.
the class BaseExplainabilityMessagingHandlerIT method explainabilityRequestIsProcessedAndAnIntermediateMessageIsSent.
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
void explainabilityRequestIsProcessedAndAnIntermediateMessageIsSent() throws Exception {
BaseExplainabilityRequest request = buildRequest();
BaseExplainabilityResult result = buildResult();
doAnswer(i -> {
Object parameter = i.getArguments()[1];
Consumer<BaseExplainabilityResult> consumer = (Consumer) parameter;
mockExplainAsyncInvocationWithIntermediateResults(consumer);
return CompletableFuture.completedFuture(result);
}).when(explanationService).explainAsync(any(BaseExplainabilityRequest.class), any());
kafkaClient.produce(ExplainabilityCloudEventBuilder.buildCloudEventJsonString(request), TOPIC_REQUEST);
verify(explanationService, timeout(2000).times(1)).explainAsync(any(BaseExplainabilityRequest.class), any());
final CountDownLatch countDownLatch = new CountDownLatch(getTotalExpectedEventCountWithIntermediateResults());
kafkaClient.consume(TOPIC_RESULT, s -> {
LOGGER.info("Received from kafka: {}", s);
CloudEventUtils.decode(s).ifPresent((CloudEvent cloudEvent) -> {
try {
BaseExplainabilityResult event = objectMapper.readValue(cloudEvent.getData().toBytes(), BaseExplainabilityResult.class);
assertNotNull(event);
assertResult(event);
countDownLatch.countDown();
} catch (IOException e) {
LOGGER.error("Error parsing {}", s, e);
throw new RuntimeException(e);
}
});
});
assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
kafkaClient.shutdown();
}
use of org.kie.kogito.explainability.api.BaseExplainabilityRequest in project kogito-apps by kiegroup.
the class TrustyServiceTest method doGivenStoredExecutionWhenCounterfactualRequestIsMadeThenExplainabilityEventIsEmittedTest.
@SuppressWarnings("unchecked")
void doGivenStoredExecutionWhenCounterfactualRequestIsMadeThenExplainabilityEventIsEmittedTest(CounterfactualDomain domain) {
Storage<String, Decision> decisionStorage = mock(Storage.class);
Storage<String, CounterfactualExplainabilityRequest> counterfactualStorage = mock(Storage.class);
ArgumentCaptor<BaseExplainabilityRequest> explainabilityEventArgumentCaptor = ArgumentCaptor.forClass(BaseExplainabilityRequest.class);
when(decisionStorage.containsKey(eq(TEST_EXECUTION_ID))).thenReturn(true);
when(trustyStorageServiceMock.getDecisionsStorage()).thenReturn(decisionStorage);
when(trustyStorageServiceMock.getCounterfactualRequestStorage()).thenReturn(counterfactualStorage);
when(decisionStorage.get(eq(TEST_EXECUTION_ID))).thenReturn(TrustyServiceTestUtils.buildCorrectDecision(TEST_EXECUTION_ID));
// The Goals structures must be comparable to the original decisions outcomes.
// The Search Domain structures must be identical those of the original decision inputs.
trustyService.requestCounterfactuals(TEST_EXECUTION_ID, List.of(new NamedTypedValue("Fine", new StructureValue("tFine", Map.of("Amount", new UnitValue("number", "number", new IntNode(0)), "Points", new UnitValue("number", "number", new IntNode(0))))), new NamedTypedValue("Should the driver be suspended?", new UnitValue("string", "string", new TextNode("No")))), List.of(new CounterfactualSearchDomain("Violation", new CounterfactualSearchDomainStructureValue("tViolation", Map.of("Type", new CounterfactualSearchDomainUnitValue("string", "string", true, domain), "Actual Speed", new CounterfactualSearchDomainUnitValue("number", "number", true, domain), "Speed Limit", new CounterfactualSearchDomainUnitValue("number", "number", true, domain)))), new CounterfactualSearchDomain("Driver", new CounterfactualSearchDomainStructureValue("tDriver", Map.of("Age", new CounterfactualSearchDomainUnitValue("number", "number", true, domain), "Points", new CounterfactualSearchDomainUnitValue("number", "number", true, domain))))));
verify(explainabilityRequestProducerMock).sendEvent(explainabilityEventArgumentCaptor.capture());
BaseExplainabilityRequest event = explainabilityEventArgumentCaptor.getValue();
assertNotNull(event);
assertTrue(event instanceof CounterfactualExplainabilityRequest);
CounterfactualExplainabilityRequest request = (CounterfactualExplainabilityRequest) event;
assertEquals(TEST_EXECUTION_ID, request.getExecutionId());
}
use of org.kie.kogito.explainability.api.BaseExplainabilityRequest in project kogito-apps by kiegroup.
the class LocalExplainerServiceHandler method explainAsyncWithResults.
/**
* Requests calculation of an explanation decorated with both "success" and "failure" result handlers.
* See:
* - {@link LocalExplainer#explainAsync}
* - {@link LocalExplainerServiceHandler#createSucceededResult(BaseExplainabilityRequest, Object)}
* - {@link LocalExplainerServiceHandler#createFailedResult(BaseExplainabilityRequest, Throwable)}
*
* @param request The explanation request.
* @param intermediateResultsConsumer A consumer for intermediate results provided by the explainer.
* @return
*/
default CompletableFuture<BaseExplainabilityResult> explainAsyncWithResults(R request, Consumer<BaseExplainabilityResult> intermediateResultsConsumer) {
Prediction prediction = getPrediction(request);
PredictionProvider predictionProvider = getPredictionProvider(request);
return explainAsync(prediction, predictionProvider, s -> intermediateResultsConsumer.accept(createIntermediateResult(request, s))).thenApply(input -> createSucceededResult(request, input)).exceptionally(e -> createFailedResult(request, e));
}
use of org.kie.kogito.explainability.api.BaseExplainabilityRequest in project kogito-apps by kiegroup.
the class BaseExplainabilityMessagingHandlerIT method explainabilityRequestIsProcessedAndAResultMessageIsSent.
@Test
void explainabilityRequestIsProcessedAndAResultMessageIsSent() throws Exception {
BaseExplainabilityRequest request = buildRequest();
BaseExplainabilityResult result = buildResult();
when(explanationService.explainAsync(any(BaseExplainabilityRequest.class), any())).thenReturn(CompletableFuture.completedFuture(result));
kafkaClient.produce(ExplainabilityCloudEventBuilder.buildCloudEventJsonString(request), TOPIC_REQUEST);
verify(explanationService, timeout(2000).times(1)).explainAsync(any(BaseExplainabilityRequest.class), any());
final CountDownLatch countDownLatch = new CountDownLatch(1);
kafkaClient.consume(TOPIC_RESULT, s -> {
LOGGER.info("Received from kafka: {}", s);
CloudEventUtils.decode(s).ifPresent((CloudEvent cloudEvent) -> {
try {
BaseExplainabilityResult event = objectMapper.readValue(cloudEvent.getData().toBytes(), BaseExplainabilityResult.class);
assertNotNull(event);
assertResult(event);
countDownLatch.countDown();
} catch (IOException e) {
LOGGER.error("Error parsing {}", s, e);
throw new RuntimeException(e);
}
});
});
assertTrue(countDownLatch.await(5, TimeUnit.SECONDS));
kafkaClient.shutdown();
}
Aggregations