/// <summary> /// Converts a source to a destination. /// </summary> protected override void Convert(TSource source, TDestination destination, ContextStore userContextStore) { _conversionCallback(source, destination, userContextStore); }
public static ITelemetryClient CreateMats( IApplicationConfiguration applicationConfiguration, IPlatformProxy platformProxy, ITelemetryConfig telemetryConfig) { string dpti = platformProxy.GetDevicePlatformTelemetryId(); if (!IsDeviceEnabled(telemetryConfig.AudienceType, dpti)) { return(null); } string deviceNetworkState = platformProxy.GetDeviceNetworkState(); int osPlatformCode = platformProxy.GetMatsOsPlatformCode(); bool enableAggregation = true; IEventFilter eventFilter = new EventFilter(enableAggregation); var errorStore = new ErrorStore(); var scenarioStore = new ScenarioStore(TimeConstants.ScenarioTimeoutMilliseconds, errorStore); var allowedScopes = new HashSet <string>(); // TODO: need to determine what MATS was doing with the AllowedScopes and DeniedScopes values in the C++ impl // and possibly expose this value in the ITelemetryConfig interface. //if (telemetryConfig.AllowedScopes != null) //{ // foreach (string s in telemetryConfig.AllowedScopes) // { // allowedScopes.Add(s); // } //} var actionStore = new ActionStore( TimeConstants.ActionTimeoutMilliseconds, TimeConstants.AggregationWindowMilliseconds, errorStore, eventFilter, allowedScopes); var contextStore = ContextStore.CreateContextStore( telemetryConfig.AudienceType, applicationConfiguration.ClientName, applicationConfiguration.ClientVersion, dpti, deviceNetworkState, telemetryConfig.SessionId, osPlatformCode); IUploader uploader = new TelemetryUploader(telemetryConfig.DispatchAction, platformProxy, applicationConfiguration.ClientName); // it's this way in mats c++ bool isScenarioUploadDisabled = true; return(new TelemetryClient( applicationConfiguration, platformProxy, errorStore, uploader, actionStore, scenarioStore, contextStore, isScenarioUploadDisabled)); }
// Start chatting loop public async Task StartChatAsync(string userId, bool skipPrompt = false, Request preRequest = null, Dictionary <string, object> payloads = null) { // Get cancellation token var token = GetChatToken(); // Get user var user = await UserStore.GetUserAsync(userId); if (user == null || string.IsNullOrEmpty(user.Id)) { Debug.LogError($"Error occured in getting user: {userId}"); await OnErrorAsync(null, null, token); return; } // Get context var context = await ContextStore.GetContextAsync(user.Id); if (context == null) { Debug.LogError($"Error occured in getting context: {user.Id}"); await OnErrorAsync(null, null, token); return; } // Request Request request = null; try { IsChatting = true; // Prompt if (!skipPrompt) { await OnPromptAsync(preRequest, user, context, token); } // Chat loop. Exit when session ends, canceled or error occures while (true) { if (token.IsCancellationRequested) { return; } var requestProvider = preRequest == null || preRequest.Type == RequestType.None ? RequestProviders[context.Topic.RequiredRequestType] : RequestProviders[preRequest.Type]; // Get or update request (microphone / camera / QR code, etc) request = await requestProvider.GetRequestAsync(user, context, token, preRequest); if (!request.IsSet() || request.IsCanceled) { // Clear context when request is not set or canceled context.Clear(); await ContextStore.SaveContextAsync(context); return; } if (token.IsCancellationRequested) { return; } // Extract intent if (preRequest == null || string.IsNullOrEmpty(preRequest.Intent)) { await DialogRouter.ExtractIntentAsync(request, context, token); } if (string.IsNullOrEmpty(request.Intent) && string.IsNullOrEmpty(context.Topic.Name)) { // Just exit loop without clearing context when NoIntent await OnNoIntentAsync(request, context, token); return; } else { Debug.Log($"Intent:{request.Intent}({request.IntentPriority.ToString()})"); if (request.Entities.Count > 0) { var entitiesString = "Entities:"; foreach (var kv in request.Entities) { var v = kv.Value != null?kv.Value.ToString() : "null"; entitiesString += $"\n - {kv.Key}: {v}"; } Debug.Log(entitiesString); } } if (token.IsCancellationRequested) { return; } // Get dialog to process intent / topic var dialogProcessor = DialogRouter.Route(request, context, token); if (token.IsCancellationRequested) { return; } // PreProcess var preProcessResponse = await dialogProcessor.PreProcessAsync(request, context, token); // Start showing waiting animation var waitingAnimationTask = dialogProcessor.ShowWaitingAnimationAsync(preProcessResponse, request, context, token); // Process dialog var dialogResponse = await dialogProcessor.ProcessAsync(request, context, token); if (token.IsCancellationRequested) { return; } // Wait for waiting animation before show response of dialog // TODO: Enable to cancel waitingAnimation instead of await when ProcessAsync ends. await waitingAnimationTask; if (token.IsCancellationRequested) { return; } // Show response of dialog await dialogProcessor.ShowResponseAsync(dialogResponse, request, context, token); if (token.IsCancellationRequested) { return; } // Post process if (context.Topic.ContinueTopic) { // Clear pre-request preRequest = null; // Save user await UserStore.SaveUserAsync(user); // Save context await ContextStore.SaveContextAsync(context); // Update properties for next context.IsNew = false; context.Topic.IsNew = false; context.Topic.ContinueTopic = false; } else { // Clear context data and topic when topic doesn't continue context.Clear(); await ContextStore.SaveContextAsync(context); break; } } } catch (Exception ex) { await ContextStore.DeleteContextAsync(user.Id); if (!token.IsCancellationRequested) { IsError = true; Debug.LogError($"Error occured in processing chat: {ex.Message}\n{ex.StackTrace}"); // Stop running animation and voice then get new token to say error token = GetChatToken(); await OnErrorAsync(request, context, token); } } finally { IsError = false; IsChatting = false; if (!token.IsCancellationRequested) { // NOTE: Cancel is triggered not only when just canceled but when invoked another chat session // Restart idling animation and reset face expression _ = ModelController?.StartIdlingAsync(); _ = ModelController?.SetDefaultFace(); } else { // Clear context when canceled context.Clear(); await ContextStore.SaveContextAsync(context); } } }