// 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 }); } }