// Copyright (c) Microsoft. All rights reserved.
using Events;
using Microsoft.SemanticKernel;
using SharedSteps;
using Step02.Models;
using Step02.Processes;
using Step02.Steps;
namespace Step02;
///
/// Demonstrate creation of and
/// eliciting its response to five explicit user messages.
/// For each test there is a different set of user messages that will cause different steps to be triggered using the same pipeline.
/// For visual reference of the process check the diagram.
///
public class Step02b_AccountOpening(ITestOutputHelper output) : BaseTest(output, redirectSystemConsoleOutput: true)
{
// Target Open AI Services
protected override bool ForceOpenAI => true;
private KernelProcess SetupAccountOpeningProcess() where TUserInputStep : ScriptedUserInputStep
{
ProcessBuilder process = new("AccountOpeningProcessWithSubprocesses");
var newCustomerFormStep = process.AddStepFromType();
var userInputStep = process.AddStepFromType();
var displayAssistantMessageStep = process.AddStepFromType();
var accountVerificationStep = process.AddStepFromProcess(NewAccountVerificationProcess.CreateProcess());
var accountCreationStep = process.AddStepFromProcess(NewAccountCreationProcess.CreateProcess());
var mailServiceStep = process.AddStepFromType();
process
.OnInputEvent(AccountOpeningEvents.StartProcess)
.SendEventTo(new ProcessFunctionTargetBuilder(newCustomerFormStep, CompleteNewCustomerFormStep.ProcessStepFunctions.NewAccountWelcome));
// When the welcome message is generated, send message to displayAssistantMessageStep
newCustomerFormStep
.OnEvent(AccountOpeningEvents.NewCustomerFormWelcomeMessageComplete)
.SendEventTo(new ProcessFunctionTargetBuilder(displayAssistantMessageStep, DisplayAssistantMessageStep.ProcessStepFunctions.DisplayAssistantMessage));
// When the userInput step emits a user input event, send it to the newCustomerForm step
// Function names are necessary when the step has multiple public functions like CompleteNewCustomerFormStep: NewAccountWelcome and NewAccountProcessUserInfo
userInputStep
.OnEvent(CommonEvents.UserInputReceived)
.SendEventTo(new ProcessFunctionTargetBuilder(newCustomerFormStep, CompleteNewCustomerFormStep.ProcessStepFunctions.NewAccountProcessUserInfo, "userMessage"));
userInputStep
.OnEvent(CommonEvents.Exit)
.StopProcess();
// When the newCustomerForm step emits needs more details, send message to displayAssistantMessage step
newCustomerFormStep
.OnEvent(AccountOpeningEvents.NewCustomerFormNeedsMoreDetails)
.SendEventTo(new ProcessFunctionTargetBuilder(displayAssistantMessageStep, DisplayAssistantMessageStep.ProcessStepFunctions.DisplayAssistantMessage));
// After any assistant message is displayed, user input is expected to the next step is the userInputStep
displayAssistantMessageStep
.OnEvent(CommonEvents.AssistantResponseGenerated)
.SendEventTo(new ProcessFunctionTargetBuilder(userInputStep, ScriptedUserInputStep.ProcessStepFunctions.GetUserInput));
// When the newCustomerForm is completed...
newCustomerFormStep
.OnEvent(AccountOpeningEvents.NewCustomerFormCompleted)
// The information gets passed to the account verificatino step
.SendEventTo(accountVerificationStep.WhereInputEventIs(AccountOpeningEvents.NewCustomerFormCompleted))
// The information gets passed to the validation process step
.SendEventTo(accountCreationStep.WhereInputEventIs(AccountOpeningEvents.NewCustomerFormCompleted));
// When the newCustomerForm is completed, the user interaction transcript with the user is passed to the core system record creation step
newCustomerFormStep
.OnEvent(AccountOpeningEvents.CustomerInteractionTranscriptReady)
.SendEventTo(accountCreationStep.WhereInputEventIs(AccountOpeningEvents.CustomerInteractionTranscriptReady));
// When the creditScoreCheck step results in Rejection, the information gets to the mailService step to notify the user about the state of the application and the reasons
accountVerificationStep
.OnEvent(AccountOpeningEvents.CreditScoreCheckRejected)
.SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep));
// When the fraudDetectionCheck step fails, the information gets to the mailService step to notify the user about the state of the application and the reasons
accountVerificationStep
.OnEvent(AccountOpeningEvents.FraudDetectionCheckFailed)
.SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep));
// When the fraudDetectionCheck step passes, the information gets to core system record creation step to kickstart this step
accountVerificationStep
.OnEvent(AccountOpeningEvents.FraudDetectionCheckPassed)
.SendEventTo(accountCreationStep.WhereInputEventIs(AccountOpeningEvents.NewAccountVerificationCheckPassed));
// After crmRecord and marketing gets created, a welcome packet is created to then send information to the user with the mailService step
accountCreationStep
.OnEvent(AccountOpeningEvents.WelcomePacketCreated)
.SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep));
// All possible paths end up with the user being notified about the account creation decision throw the mailServiceStep completion
mailServiceStep
.OnEvent(AccountOpeningEvents.MailServiceSent)
.StopProcess();
KernelProcess kernelProcess = process.Build();
return kernelProcess;
}
///
/// This test uses a specific userId and DOB that makes the creditScore and Fraud detection to pass
///
[Fact]
public async Task UseAccountOpeningProcessSuccessfulInteractionAsync()
{
Kernel kernel = CreateKernelWithChatCompletion();
KernelProcess kernelProcess = SetupAccountOpeningProcess();
await using var runningProcess = await kernelProcess.StartAsync(kernel, new KernelProcessEvent() { Id = AccountOpeningEvents.StartProcess, Data = null });
}
///
/// This test uses a specific DOB that makes the creditScore to fail
///
[Fact]
public async Task UseAccountOpeningProcessFailureDueToCreditScoreFailureAsync()
{
Kernel kernel = CreateKernelWithChatCompletion();
KernelProcess kernelProcess = SetupAccountOpeningProcess();
await using var runningProcess = await kernelProcess.StartAsync(kernel, new KernelProcessEvent() { Id = AccountOpeningEvents.StartProcess, Data = null });
}
///
/// This test uses a specific userId that makes the fraudDetection to fail
///
[Fact]
public async Task UseAccountOpeningProcessFailureDueToFraudFailureAsync()
{
Kernel kernel = CreateKernelWithChatCompletion();
KernelProcess kernelProcess = SetupAccountOpeningProcess();
await using var runningProcess = await kernelProcess.StartAsync(kernel, new KernelProcessEvent() { Id = AccountOpeningEvents.StartProcess, Data = null });
}
}