// Copyright (c) Microsoft. All rights reserved. using Events; using Microsoft.SemanticKernel; using SharedSteps; using Step02.Models; 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 Step02a_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("AccountOpeningProcess"); var newCustomerFormStep = process.AddStepFromType(); var userInputStep = process.AddStepFromType(); var displayAssistantMessageStep = process.AddStepFromType(); var customerCreditCheckStep = process.AddStepFromType(); var fraudDetectionCheckStep = process.AddStepFromType(); var mailServiceStep = process.AddStepFromType(); var coreSystemRecordCreationStep = process.AddStepFromType(); var marketingRecordCreationStep = process.AddStepFromType(); var crmRecordStep = process.AddStepFromType(); var welcomePacketStep = 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 core system record creation step .SendEventTo(new ProcessFunctionTargetBuilder(customerCreditCheckStep, functionName: CreditScoreCheckStep.ProcessStepFunctions.DetermineCreditScore, parameterName: "customerDetails")) // The information gets passed to the fraud detection step for validation .SendEventTo(new ProcessFunctionTargetBuilder(fraudDetectionCheckStep, functionName: FraudDetectionStep.ProcessStepFunctions.FraudDetectionCheck, parameterName: "customerDetails")) // The information gets passed to the core system record creation step .SendEventTo(new ProcessFunctionTargetBuilder(coreSystemRecordCreationStep, functionName: NewAccountStep.ProcessStepFunctions.CreateNewAccount, parameterName: "customerDetails")); // 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(new ProcessFunctionTargetBuilder(coreSystemRecordCreationStep, functionName: NewAccountStep.ProcessStepFunctions.CreateNewAccount, parameterName: "interactionTranscript")); // 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 customerCreditCheckStep .OnEvent(AccountOpeningEvents.CreditScoreCheckRejected) .SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep, functionName: MailServiceStep.ProcessStepFunctions.SendMailToUserWithDetails, parameterName: "message")); // When the creditScoreCheck step results in Approval, the information gets to the fraudDetection step to kickstart this step customerCreditCheckStep .OnEvent(AccountOpeningEvents.CreditScoreCheckApproved) .SendEventTo(new ProcessFunctionTargetBuilder(fraudDetectionCheckStep, functionName: FraudDetectionStep.ProcessStepFunctions.FraudDetectionCheck, parameterName: "previousCheckSucceeded")); // 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 fraudDetectionCheckStep .OnEvent(AccountOpeningEvents.FraudDetectionCheckFailed) .SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep, functionName: MailServiceStep.ProcessStepFunctions.SendMailToUserWithDetails, parameterName: "message")); // When the fraudDetectionCheck step passes, the information gets to core system record creation step to kickstart this step fraudDetectionCheckStep .OnEvent(AccountOpeningEvents.FraudDetectionCheckPassed) .SendEventTo(new ProcessFunctionTargetBuilder(coreSystemRecordCreationStep, functionName: NewAccountStep.ProcessStepFunctions.CreateNewAccount, parameterName: "previousCheckSucceeded")); // When the coreSystemRecordCreation step successfully creates a new accountId, it will trigger the creation of a new marketing entry through the marketingRecordCreation step coreSystemRecordCreationStep .OnEvent(AccountOpeningEvents.NewMarketingRecordInfoReady) .SendEventTo(new ProcessFunctionTargetBuilder(marketingRecordCreationStep, functionName: NewMarketingEntryStep.ProcessStepFunctions.CreateNewMarketingEntry, parameterName: "userDetails")); // When the coreSystemRecordCreation step successfully creates a new accountId, it will trigger the creation of a new CRM entry through the crmRecord step coreSystemRecordCreationStep .OnEvent(AccountOpeningEvents.CRMRecordInfoReady) .SendEventTo(new ProcessFunctionTargetBuilder(crmRecordStep, functionName: CRMRecordCreationStep.ProcessStepFunctions.CreateCRMEntry, parameterName: "userInteractionDetails")); // ParameterName is necessary when the step has multiple input arguments like welcomePacketStep.CreateWelcomePacketAsync // When the coreSystemRecordCreation step successfully creates a new accountId, it will pass the account information details to the welcomePacket step coreSystemRecordCreationStep .OnEvent(AccountOpeningEvents.NewAccountDetailsReady) .SendEventTo(new ProcessFunctionTargetBuilder(welcomePacketStep, parameterName: "accountDetails")); // When the marketingRecordCreation step successfully creates a new marketing entry, it will notify the welcomePacket step it is ready marketingRecordCreationStep .OnEvent(AccountOpeningEvents.NewMarketingEntryCreated) .SendEventTo(new ProcessFunctionTargetBuilder(welcomePacketStep, parameterName: "marketingEntryCreated")); // When the crmRecord step successfully creates a new CRM entry, it will notify the welcomePacket step it is ready crmRecordStep .OnEvent(AccountOpeningEvents.CRMRecordInfoEntryCreated) .SendEventTo(new ProcessFunctionTargetBuilder(welcomePacketStep, parameterName: "crmRecordCreated")); // After crmRecord and marketing gets created, a welcome packet is created to then send information to the user with the mailService step welcomePacketStep .OnEvent(AccountOpeningEvents.WelcomePacketCreated) .SendEventTo(new ProcessFunctionTargetBuilder(mailServiceStep, functionName: MailServiceStep.ProcessStepFunctions.SendMailToUserWithDetails, parameterName: "message")); // 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 }); } }