예제 #1
0
 public ModelHelpers(IBackend gallifrey, FlyoutsControl flyoutsControl)
 {
     this.flyoutsControl = flyoutsControl;
     Gallifrey = gallifrey;
     DialogContext = new DialogContext();
     openFlyouts = new List<OpenFlyoutDetails>();
 }
예제 #2
0
        protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await _conversationStateAccessor.GetAsync(dc.Context, () => new SkillConversationState());

            // get current activity locale
            var locale       = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
            var localeConfig = _services.LocaleConfigurations[locale];

            // Get skill LUIS model from configuration
            localeConfig.LuisServices.TryGetValue("FakeSkill", out var luisService);

            if (luisService == null)
            {
                throw new Exception("The specified LUIS Model could not be found in your Bot Services configuration.");
            }
            else
            {
                var skillOptions = new SkillTemplateDialogOptions
                {
                    SkillMode = _skillMode,
                };

                var result = await luisService.RecognizeAsync <FakeSkillLU>(dc.Context, CancellationToken.None);

                var intent = result?.TopIntent().intent;

                switch (intent)
                {
                case FakeSkillLU.Intent.Sample:
                {
                    await dc.BeginDialogAsync(nameof(SampleDialog), skillOptions);

                    break;
                }

                case FakeSkillLU.Intent.Auth:
                {
                    await dc.BeginDialogAsync(nameof(AuthDialog), skillOptions);

                    break;
                }

                case FakeSkillLU.Intent.None:
                {
                    // No intent was identified, send confused message
                    await dc.Context.SendActivityAsync(_responseManager.GetResponse(SharedResponses.DidntUnderstandMessage));

                    if (_skillMode)
                    {
                        await CompleteAsync(dc);
                    }

                    break;
                }

                default:
                {
                    // intent was identified but not yet implemented
                    await dc.Context.SendActivityAsync(_responseManager.GetResponse(MainResponses.FeatureNotAvailable));

                    if (_skillMode)
                    {
                        await CompleteAsync(dc);
                    }

                    break;
                }
                }
            }
        }
 public override async Task <DialogTurnResult> ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
 {
     // We're being continued after an interruption so just run next action
     return(await OnNextActionAsync(dc, null, cancellationToken).ConfigureAwait(false));
 }
예제 #4
0
 public override Task <RecognizerResult> RecognizeAsync(DialogContext dialogContext, CancellationToken cancellationToken = default)
 {
     return(this.RecognizeAsync(dialogContext.Context, cancellationToken));
 }
예제 #5
0
 protected virtual object OnInitializeOptions(DialogContext dc, object options)
 {
     return(options);
 }
예제 #6
0
 public override async Task <DialogTurnResult> ResumeDialogAsync(DialogContext dc, DialogReason reason, object result = null, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(await this.PromptUser(dc, InputState.Missing).ConfigureAwait(false));
 }
예제 #7
0
 protected async override Task <DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options, CancellationToken cancellationToken = default(CancellationToken))
 {
     // Override default begin() logic with interruption orchestration logic
     return(await InterruptionDispatchAsync(innerDc, options));
 }
예제 #8
0
 /// <summary>
 /// Deletes any state in storage and the cache for this <see cref="BotState"/>.
 /// </summary>
 /// <param name="dialogContext">The dialog context object for this turn.</param>
 /// <param name="cancellationToken">A cancellation token that can be used by other objects
 /// or threads to receive notice of cancellation.</param>
 /// <returns>A task that represents the work queued to execute.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="turnContext"/> is <c>null</c>.</exception>
 public virtual Task DeleteAsync(DialogContext dialogContext, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(Task.CompletedTask);
 }
예제 #9
0
        protected async Task DigestCalendarLuisResult(DialogContext dc, Calendar luisResult, bool isBeginDialog)
        {
            try
            {
                var state = await Accessor.GetAsync(dc.Context);

                var intent = luisResult.TopIntent().intent;

                var entity = luisResult.Entities;

                if (entity.ordinal != null)
                {
                    try
                    {
                        var eventList = state.SummaryEvents;
                        var value     = entity.ordinal[0];
                        var num       = int.Parse(value.ToString());
                        if (eventList != null && num > 0)
                        {
                            var currentList = eventList.GetRange(0, Math.Min(CalendarSkillState.PageSize, eventList.Count));
                            if (num <= currentList.Count)
                            {
                                state.ReadOutEvents.Clear();
                                state.ReadOutEvents.Add(currentList[num - 1]);
                            }
                        }
                    }
                    catch
                    {
                        // ignored
                    }
                }

                if (entity.number != null && entity.ordinal != null && entity.ordinal.Length == 0)
                {
                    try
                    {
                        var eventList = state.SummaryEvents;
                        var value     = entity.ordinal[0];
                        var num       = int.Parse(value.ToString());
                        if (eventList != null && num > 0)
                        {
                            var currentList = eventList.GetRange(0, Math.Min(CalendarSkillState.PageSize, eventList.Count));
                            if (num <= currentList.Count)
                            {
                                state.ReadOutEvents.Clear();
                                state.ReadOutEvents.Add(currentList[num - 1]);
                            }
                        }
                    }
                    catch
                    {
                        // ignored
                    }
                }

                if (!isBeginDialog)
                {
                    return;
                }

                switch (intent)
                {
                case Calendar.Intent.FindMeetingRoom:
                case Calendar.Intent.CreateCalendarEntry:
                {
                    if (entity.Subject != null)
                    {
                        state.Title = GetSubjectFromEntity(entity);
                    }

                    if (entity.ContactName != null)
                    {
                        state.AttendeesNameList = GetAttendeesFromEntity(entity, luisResult.Text, state.AttendeesNameList);
                    }

                    if (entity.FromDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.FromDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.StartDate = date;
                        }
                    }


                    if (entity.ToDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.ToDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.EndDate = date;
                        }
                    }

                    if (entity.FromTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), true);
                        if (time != null)
                        {
                            state.StartTime = time;
                        }

                        time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), false);
                        if (time != null)
                        {
                            state.EndTime = time;
                        }
                    }

                    if (entity.ToTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.ToTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (time != null)
                        {
                            state.EndTime = time;
                        }
                    }

                    if (entity.Duration != null)
                    {
                        int duration = GetDurationFromEntity(entity, dc.Context.Activity.Locale);
                        if (duration != -1)
                        {
                            state.Duration = duration;
                        }
                    }

                    if (entity.MeetingRoom != null)
                    {
                        state.Location = GetMeetingRoomFromEntity(entity);
                    }

                    if (entity.Location != null)
                    {
                        state.Location = GetLocationFromEntity(entity);
                    }

                    break;
                }

                case Calendar.Intent.DeleteCalendarEntry:
                {
                    if (entity.Subject != null)
                    {
                        state.Title = GetSubjectFromEntity(entity);
                    }


                    if (entity.FromDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.FromDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.StartDate = date;
                        }
                    }

                    if (entity.FromTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), true);
                        if (time != null)
                        {
                            state.StartTime = time;
                        }
                    }

                    break;
                }

                case Calendar.Intent.NextMeeting:
                {
                    break;
                }

                case Calendar.Intent.ChangeCalendarEntry:
                {
                    if (entity.Subject != null)
                    {
                        state.Title = GetSubjectFromEntity(entity);
                    }

                    if (entity.FromDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.FromDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.OriginalStartDate = date;
                        }
                    }

                    if (entity.ToDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.ToDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.StartDate = date;
                        }
                    }

                    if (entity.FromTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), true);
                        if (time != null)
                        {
                            state.OriginalStartTime = time;
                        }

                        time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), false);
                        if (time != null)
                        {
                            state.OriginalEndTime = time;
                        }
                    }

                    if (entity.ToTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.ToTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), true);
                        if (time != null)
                        {
                            state.StartTime = time;
                        }

                        time = GetTimeFromDateTimeString(entity.ToTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), false);
                        if (time != null)
                        {
                            state.EndTime = time;
                        }
                    }

                    if (entity.MoveEarlierTimeSpan != null)
                    {
                        state.MoveTimeSpan = GetMoveTimeSpanFromEntity(entity.MoveEarlierTimeSpan[0], dc.Context.Activity.Locale, false);
                    }

                    if (entity.MoveLaterTimeSpan != null)
                    {
                        state.MoveTimeSpan = GetMoveTimeSpanFromEntity(entity.MoveLaterTimeSpan[0], dc.Context.Activity.Locale, true);
                    }

                    break;
                }

                case Calendar.Intent.FindCalendarEntry:
                case Calendar.Intent.Summary:
                {
                    if (entity.FromDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.FromDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.StartDate = date;
                        }
                    }

                    if (entity.ToDate != null)
                    {
                        var date = GetDateFromDateTimeString(entity.ToDate[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (date != null)
                        {
                            state.EndDate = date;
                        }
                    }

                    if (entity.FromTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), true);
                        if (time != null)
                        {
                            state.StartTime = time;
                        }

                        time = GetTimeFromDateTimeString(entity.FromTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone(), false);
                        if (time != null)
                        {
                            state.EndTime = time;
                        }
                    }

                    if (entity.ToTime != null)
                    {
                        var time = GetTimeFromDateTimeString(entity.ToTime[0], dc.Context.Activity.Locale, state.GetUserTimeZone());
                        if (time != null)
                        {
                            state.EndTime = time;
                        }
                    }

                    break;
                }

                case Calendar.Intent.None:
                {
                    break;
                }

                default:
                {
                    break;
                }
                }
            }
            catch
            {
                var state = await Accessor.GetAsync(dc.Context);

                state.Clear();
                await dc.CancelAllDialogsAsync();

                throw;
            }
        }
예제 #10
0
 protected abstract Task <InterruptionStatus> OnDialogInterruptionAsync(DialogContext dc, CancellationToken cancellationToken);
예제 #11
0
 public override void SetMemory(DialogContext dc, object memory)
 {
     throw new NotSupportedException("You cannot set the memory for a readonly memory scope");
 }
예제 #12
0
        private async Task RecognizeEntitiesAsync(DialogContext dialogContext, Schema.Activity activity, RecognizerResult recognizerResult)
        {
            var text       = activity.Text ?? string.Empty;
            var entityPool = new List <Entity>();

            if (EntityRecognizers != null)
            {
                // add entities from regexrecgonizer to the entities pool
                var textEntity = new TextEntity(text);
                textEntity.Properties["start"] = 0;
                textEntity.Properties["end"]   = text.Length;
                textEntity.Properties["score"] = 1.0;

                entityPool.Add(textEntity);

                // process entities using EntityRecognizerSet
                var entitySet   = new EntityRecognizerSet(EntityRecognizers);
                var newEntities = await entitySet.RecognizeEntitiesAsync(dialogContext, activity, entityPool).ConfigureAwait(false);

                if (newEntities.Any())
                {
                    entityPool.AddRange(newEntities);
                }

                entityPool.Remove(textEntity);
            }

            // map entityPool of Entity objects => RecognizerResult entity format
            recognizerResult.Entities = new JObject();

            foreach (var entityResult in entityPool)
            {
                // add value
                JToken values;
                if (!recognizerResult.Entities.TryGetValue(entityResult.Type, StringComparison.OrdinalIgnoreCase, out values))
                {
                    values = new JArray();
                    recognizerResult.Entities[entityResult.Type] = values;
                }

                // The Entity type names are not consistent, map everything to camelcase so we can process them cleaner.
                var entity = JObject.FromObject(entityResult);
                ((JArray)values).Add(entity.GetValue("text", StringComparison.InvariantCulture));

                // get/create $instance
                if (!recognizerResult.Entities.TryGetValue("$instance", StringComparison.OrdinalIgnoreCase, out JToken instanceRoot))
                {
                    instanceRoot = new JObject();
                    recognizerResult.Entities["$instance"] = instanceRoot;
                }

                // add instanceData
                if (!((JObject)instanceRoot).TryGetValue(entityResult.Type, StringComparison.OrdinalIgnoreCase, out JToken instanceData))
                {
                    instanceData = new JArray();
                    instanceRoot[entityResult.Type] = instanceData;
                }

                var instance = new JObject();
                instance.Add("startIndex", entity.GetValue("start", StringComparison.InvariantCulture));
                instance.Add("endIndex", entity.GetValue("end", StringComparison.InvariantCulture));
                instance.Add("score", (double)1.0);
                instance.Add("text", entity.GetValue("text", StringComparison.InvariantCulture));
                instance.Add("type", entity.GetValue("type", StringComparison.InvariantCulture));
                instance.Add("resolution", entity.GetValue("resolution", StringComparison.InvariantCulture));
                ((JArray)instanceData).Add(instance);
            }
        }
예제 #13
0
        /// <summary>
        /// Return recognition results.
        /// </summary>
        /// <param name="dc">Context object containing information for a single turn of conversation with a user.</param>
        /// <param name="activity">The incoming activity received from the user. The Text property value is used as the query text for QnA Maker.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <param name="telemetryProperties">Additional properties to be logged to telemetry with the LuisResult event.</param>
        /// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
        /// <returns>A <see cref="RecognizerResult"/> containing the QnA Maker result.</returns>
        public override async Task <RecognizerResult> RecognizeAsync(DialogContext dc, Schema.Activity activity, CancellationToken cancellationToken, Dictionary <string, string> telemetryProperties = null, Dictionary <string, double> telemetryMetrics = null)
        {
            var text            = activity.Text ?? string.Empty;
            var detectAmbiguity = DetectAmbiguousIntents.GetValue(dc.State);

            _modelPath    = ModelPath.GetValue(dc.State);
            _snapshotPath = SnapshotPath.GetValue(dc.State);

            InitializeModel();

            var recognizerResult = new RecognizerResult()
            {
                Text    = text,
                Intents = new Dictionary <string, IntentScore>(),
            };

            if (string.IsNullOrWhiteSpace(text))
            {
                // nothing to recognize, return empty recognizerResult
                return(recognizerResult);
            }

            if (EntityRecognizers.Count != 0)
            {
                // Run entity recognition
                await RecognizeEntitiesAsync(dc, activity, recognizerResult).ConfigureAwait(false);
            }

            // Score with orchestrator
            var results = _resolver.Score(text);

            // Add full recognition result as a 'result' property
            recognizerResult.Properties.Add(ResultProperty, results);

            if (results.Any())
            {
                var topScore = results[0].Score;

                // if top scoring intent is less than threshold, return None
                if (topScore < UnknownIntentFilterScore)
                {
                    recognizerResult.Intents.Add(NoneIntent, new IntentScore()
                    {
                        Score = 1.0
                    });
                }
                else
                {
                    // add top score
                    recognizerResult.Intents.Add(results[0].Label.Name, new IntentScore()
                    {
                        Score = results[0].Score
                    });

                    // Disambiguate if configured
                    if (detectAmbiguity)
                    {
                        var thresholdScore   = DisambiguationScoreThreshold.GetValue(dc.State);
                        var classifyingScore = Math.Round(topScore, 2) - Math.Round(thresholdScore, 2);
                        var ambiguousResults = results.Where(item => item.Score >= classifyingScore).ToList();

                        if (ambiguousResults.Count > 1)
                        {
                            // create a RecognizerResult for each ambiguous result.
                            var recognizerResults = ambiguousResults.Select(result => new RecognizerResult()
                            {
                                Text        = text,
                                AlteredText = result.ClosestText,
                                Entities    = recognizerResult.Entities,
                                Properties  = recognizerResult.Properties,
                                Intents     = new Dictionary <string, IntentScore>()
                                {
                                    { result.Label.Name, new IntentScore()
                                      {
                                          Score = result.Score
                                      } }
                                },
                            });

                            // replace RecognizerResult with ChooseIntent => Ambiguous recognizerResults as candidates.
                            recognizerResult = CreateChooseIntentResult(recognizerResults.ToDictionary(result => Guid.NewGuid().ToString(), result => result));
                        }
                    }
                }
            }
            else
            {
                // Return 'None' if no intent matched.
                recognizerResult.Intents.Add(NoneIntent, new IntentScore()
                {
                    Score = 1.0
                });
            }

            await dc.Context.TraceActivityAsync(nameof(OrchestratorAdaptiveRecognizer), JObject.FromObject(recognizerResult), nameof(OrchestratorAdaptiveRecognizer), "Orchestrator Recognition ", cancellationToken).ConfigureAwait(false);

            TrackRecognizerResult(dc, nameof(OrchestratorAdaptiveRecognizer), FillRecognizerResultTelemetryProperties(recognizerResult, telemetryProperties), telemetryMetrics);

            return(recognizerResult);
        }
예제 #14
0
 public async Task <DialogTurnResult> Handle(DialogContext dialogContext, CancellationToken cancellationToken)
 {
     //dialogContext.Dialogs.Add(dia);
     return(await dialogContext.BeginDialogAsync(_whoIsSHeDialog.Id, cancellationToken : cancellationToken));
 }
 public override Task <DialogTurnResult> ResumeDialogAsync(DialogContext dc, DialogReason reason, object result = null, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(null);
 }
예제 #16
0
 /// <summary>
 /// Writes the state cache for this <see cref="BotState"/> to the storage layer.
 /// </summary>
 /// <param name="dialogContext">The dialog context object for this turn.</param>
 /// <param name="force">Optional, <c>true</c> to save the state cache to storage;
 /// or <c>false</c> to save state to storage only if a property in the cache has changed.</param>
 /// <param name="cancellationToken">A cancellation token that can be used by other objects
 /// or threads to receive notice of cancellation.</param>
 /// <returns>A task that represents the work queued to execute.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="turnContext"/> is <c>null</c>.</exception>
 public virtual Task SaveChangesAsync(DialogContext dialogContext, bool force = false, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(Task.CompletedTask);
 }
예제 #17
0
        // Helpers
        public async Task DigestLuisResult(DialogContext dc, weather luisResult)
        {
            try
            {
                var state = await Accessor.GetAsync(dc.Context);

                // extract entities and store in state here.
                if (luisResult.Entities.Weather_Location != null && luisResult.Entities.Weather_Location.Length > 0)
                {
                    state.Locations.Clear();
                    foreach (var location in luisResult.Entities.Weather_Location)
                    {
                        if (!state.Locations.Contains(location))
                        {
                            state.Locations.Add(location);
                        }
                    }
                }

                if (luisResult.Entities.datetime != null && luisResult.Entities.datetime.Length > 0)
                {
                    state.ForecastTimes.Clear();
                    foreach (var datespcs in luisResult.Entities.datetime)
                    {
                        switch (datespcs.Type)
                        {
                        case "date":
                            if (datespcs.Expressions.Count > 0)
                            {
                                var forecast = new ForecastTime {
                                    StartTime = null, Type = ForecastType.Day
                                };
                                if (DateTime.TryParse(datespcs.Expressions[0], out DateTime time))
                                {
                                    forecast.StartTime = time;
                                }
                                state.ForecastTimes.Add(forecast);
                            }
                            break;

                        case "datetime":
                            if (datespcs.Expressions.Count > 0)
                            {
                                var forecast = new ForecastTime {
                                    StartTime = null, Type = ForecastType.Hour
                                };
                                if (DateTime.TryParse(datespcs.Expressions[0], out DateTime time))
                                {
                                    forecast.StartTime = time;
                                }
                                state.ForecastTimes.Add(forecast);
                            }
                            break;
                        }
                    }
                }

                if (luisResult.Entities.Wear_Clothes != null && luisResult.Entities.Wear_Clothes.Length > 0)
                {
                    state.Clothes.Clear();
                    foreach (var cloth in luisResult.Entities.Wear_Clothes)
                    {
                        if (!state.Clothes.Contains(cloth))
                        {
                            state.Clothes.Add(cloth);
                        }
                    }
                }
            }
            catch
            {
                // put log here
            }
        }
예제 #18
0
 public override void SetMemory(DialogContext dc, object memory)
 {
     throw new NotSupportedException("You can't modify the class scope");
 }
예제 #19
0
        private static async Task Waterfall3_Step2(DialogContext dc, object args, SkipStepFunction next)
        {
            await dc.Context.SendActivity("step2");

            await dc.Begin("test-waterfall-c");
        }
예제 #20
0
 protected async override Task <DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default(CancellationToken))
 {
     // Override default continue() logic with interruption orchestration logic
     return(await InterruptionDispatchAsync(innerDc, null));
 }
예제 #21
0
 private static async Task Waterfall4_Step1(DialogContext dc, object args, SkipStepFunction next)
 {
     await dc.Context.SendActivity("step1.1");
 }
예제 #22
0
 protected abstract Task <InputState> OnRecognizeInput(DialogContext dc);
예제 #23
0
        private static async Task Waterfall5_Step2(DialogContext dc, object args, SkipStepFunction next)
        {
            await dc.Context.SendActivity("step2.2");

            await dc.End();
        }
예제 #24
0
        private async Task <InputState> RecognizeInput(DialogContext dc, int turnCount)
        {
            dynamic input = null;

            // Use Property expression for input first
            if (!string.IsNullOrEmpty(this.Property))
            {
                dc.State.TryGetValue(this.Property, out input);

                // Clear property to avoid it being stuck on the next turn. It will get written
                // back if the value passes validations.
                dc.State.SetValue(this.Property, null);
            }

            // Use Value expression for input second
            if (input == null && !string.IsNullOrEmpty(this.Value))
            {
                dc.State.TryGetValue(this.Value, out input);
            }

            // Fallback to using activity
            if (input == null && turnCount > 0)
            {
                if (this.GetType().Name == nameof(AttachmentInput))
                {
                    input = dc.Context.Activity.Attachments;
                }
                else
                {
                    input = dc.Context.Activity.Text;
                }
            }

            // Update "this.value" and perform additional recognition and validations
            dc.State.SetValue(VALUE_PROPERTY, input);
            if (input != null)
            {
                var state = await this.OnRecognizeInput(dc).ConfigureAwait(false);

                if (state == InputState.Valid)
                {
                    foreach (var validation in this.Validations)
                    {
                        var exp = new ExpressionEngine().Parse(validation);
                        var(value, error) = exp.TryEvaluate(dc.State);
                        if (value == null || (value is bool && (bool)value == false))
                        {
                            return(InputState.Invalid);
                        }
                    }

                    return(InputState.Valid);
                }
                else
                {
                    return(state);
                }
            }
            else
            {
                return(InputState.Missing);
            }
        }
예제 #25
0
        private static async Task Waterfall2_Step1(DialogContext dc, object args, SkipStepFunction next)
        {
            await dc.Context.SendActivity("step1");

            await dc.Prompt("number", "Enter a number.", new PromptOptions { RetryPromptString = "It must be a number" });
        }
예제 #26
0
 protected virtual async Task <DialogTurnResult> OnContinueLoopAsync(DialogContext dc, ActionScopeResult actionScopeResult, CancellationToken cancellationToken = default)
 {
     // default is to simply end the dialog and propagate to parent to handle
     return(await dc.EndDialogAsync(actionScopeResult, cancellationToken).ConfigureAwait(false));
 }
        private async Task <bool> InterruptDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)
        {
            var interrupted = false;
            var activity    = innerDc.Context.Activity;
            var userProfile = await _userProfileState.GetAsync(innerDc.Context, () => new UserProfileState(), cancellationToken);

            var dialog = innerDc.ActiveDialog?.Id != null?innerDc.FindDialog(innerDc.ActiveDialog?.Id) : null;

            if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text))
            {
                // Check if the active dialog is a skill for conditional interruption.
                var isSkill = dialog is SkillDialog;

                // Get Dispatch LUIS result from turn state.
                var dispatchResult = innerDc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult);
                (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent();

                // Check if we need to switch skills.
                if (isSkill && IsSkillIntent(dispatchIntent) && dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9)
                {
                    if (_skillsConfig.Skills.TryGetValue(dispatchIntent.ToString(), out var identifiedSkill))
                    {
                        var prompt = _templateManager.GenerateActivityForLocale("SkillSwitchPrompt", new { Skill = identifiedSkill.Name });
                        await innerDc.BeginDialogAsync(_switchSkillDialog.Id, new SwitchSkillDialogOptions(prompt, identifiedSkill), cancellationToken);

                        interrupted = true;
                    }
                    else
                    {
                        throw new ArgumentException($"{dispatchIntent.ToString()} is not in the skills configuration");
                    }
                }

                if (dispatchIntent == DispatchLuis.Intent.l_General)
                {
                    // Get connected LUIS result from turn state.
                    var generalResult = innerDc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult);
                    (var generalIntent, var generalScore) = generalResult.TopIntent();

                    if (generalScore > 0.5)
                    {
                        switch (generalIntent)
                        {
                        case GeneralLuis.Intent.Cancel:
                        {
                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("CancelledMessage", userProfile), cancellationToken);

                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Escalate:
                        {
                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("EscalateMessage", userProfile), cancellationToken);

                            await innerDc.RepromptDialogAsync(cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Help:
                        {
                            if (!isSkill)
                            {
                                // If current dialog is a skill, allow it to handle its own help intent.
                                await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("HelpCard", userProfile), cancellationToken);

                                await innerDc.RepromptDialogAsync(cancellationToken);

                                interrupted = true;
                            }

                            break;
                        }

                        case GeneralLuis.Intent.Logout:
                        {
                            // Log user out of all accounts.
                            await LogUserOutAsync(innerDc, cancellationToken);

                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("LogoutMessage", userProfile), cancellationToken);

                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Repeat:
                        {
                            // Sends the activities since the last user message again.
                            var previousResponse = await _previousResponseAccessor.GetAsync(innerDc.Context, () => new List <Activity>(), cancellationToken);

                            foreach (var response in previousResponse)
                            {
                                // Reset id of original activity so it can be processed by the channel.
                                response.Id = string.Empty;
                                await innerDc.Context.SendActivityAsync(response, cancellationToken);
                            }

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.StartOver:
                        {
                            await innerDc.Context.SendActivityAsync(_templateManager.GenerateActivityForLocale("StartOverMessage", userProfile), cancellationToken);

                            // Cancel all dialogs on the stack.
                            await innerDc.CancelAllDialogsAsync(cancellationToken);

                            await innerDc.BeginDialogAsync(InitialDialogId, cancellationToken : cancellationToken);

                            interrupted = true;
                            break;
                        }

                        case GeneralLuis.Intent.Stop:
                        {
                            // Use this intent to send an event to your device that can turn off the microphone in speech scenarios.
                            break;
                        }
                        }
                    }
                }
            }

            return(interrupted);
        }
예제 #28
0
        private async Task <InterruptionAction> OnHelp(DialogContext dc)
        {
            await dc.Context.SendActivityAsync(_responseManager.GetResponse(MainResponses.HelpMessage));

            return(InterruptionAction.MessageSentToUser);
        }
예제 #29
0
 /// <summary>
 /// Get the backing memory for this scope.
 /// </summary>
 /// <param name="dc">dc.</param>
 /// <returns>memory for the scope.</returns>
 public abstract object GetMemory(DialogContext dc);
예제 #30
0
 /// <summary>
 /// Changes the backing object for the memory scope.
 /// </summary>
 /// <param name="dc">dc.</param>
 /// <param name="memory">memory.</param>
 public abstract void SetMemory(DialogContext dc, object memory);
#pragma warning restore CA2227 // Collection properties should be read only

        /// <summary>
        /// Runs current DialogContext.TurnContext.Activity through a recognizer and returns a <see cref="RecognizerResult"/>.
        /// </summary>
        /// <param name="dialogContext">The <see cref="DialogContext"/> for the current turn of conversation.</param>
        /// <param name="activity"><see cref="Activity"/> to recognize.</param>
        /// <param name="cancellationToken">Optional, <see cref="CancellationToken"/> of the task.</param>
        /// <param name="telemetryProperties">Optional, additional properties to be logged to telemetry with the LuisResult event.</param>
        /// <param name="telemetryMetrics">Optional, additional metrics to be logged to telemetry with the LuisResult event.</param>
        /// <returns>Analysis of utterance.</returns>
        public override async Task <RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken, Dictionary <string, string> telemetryProperties = null, Dictionary <string, double> telemetryMetrics = null)
        {
            // Identify matched intents
            var text   = activity.Text ?? string.Empty;
            var locale = activity.Locale ?? "en-us";

            var recognizerResult = new RecognizerResult()
            {
                Text = text,
            };

            if (string.IsNullOrWhiteSpace(text))
            {
                // nothing to recognize, return empty recognizerResult
                return(recognizerResult);
            }

            // add entities from regexrecgonizer to the entities pool
            var entityPool = new List <Entity>();

            var textEntity = new TextEntity(text);

            textEntity.Properties["start"] = 0;
            textEntity.Properties["end"]   = text.Length;
            textEntity.Properties["score"] = 1.0;

            entityPool.Add(textEntity);

            foreach (var intentPattern in this.Intents)
            {
                var matches = intentPattern.Regex.Matches(text);

                if (matches.Count > 0)
                {
                    // TODO length weighted match and multiple intents
                    var intentKey = intentPattern.Intent.Replace(" ", "_");
                    if (!recognizerResult.Intents.ContainsKey(intentKey))
                    {
                        recognizerResult.Intents.Add(intentKey, new IntentScore()
                        {
                            Score      = 1.0,
                            Properties = new Dictionary <string, object>()
                            {
                                { "pattern", intentPattern.Pattern }
                            }
                        });
                    }

                    // Check for named capture groups
                    // only if we have a value and the name is not a number "0"
                    foreach (var groupName in intentPattern.Regex.GetGroupNames().Where(name => name.Length > 1))
                    {
                        foreach (var match in matches.Cast <Match>())
                        {
                            var group = (Group)match.Groups[groupName];
                            if (group.Success)
                            {
                                // add as entity to entity pool
                                Entity entity = new Entity(groupName);
                                entity.Properties["text"]  = group.Value;
                                entity.Properties["start"] = group.Index;
                                entity.Properties["end"]   = group.Index + group.Length;
                                entityPool.Add(entity);
                            }
                        }
                    }

                    // found
                    break;
                }
            }

            if (this.Entities != null)
            {
                // process entities using EntityRecognizerSet
                var entitySet   = new EntityRecognizerSet(this.Entities);
                var newEntities = await entitySet.RecognizeEntitiesAsync(dialogContext, text, locale, entityPool).ConfigureAwait(false);

                if (newEntities.Any())
                {
                    entityPool.AddRange(newEntities);
                }
            }

            // map entityPool of Entity objects => RecognizerResult entity format
            recognizerResult.Entities = new JObject();

            foreach (var entityResult in entityPool)
            {
                // add value
                JToken values;
                if (!recognizerResult.Entities.TryGetValue(entityResult.Type, StringComparison.OrdinalIgnoreCase, out values))
                {
                    values = new JArray();
                    recognizerResult.Entities[entityResult.Type] = values;
                }

                // The Entity type names are not consistent, map everything to camelcase so we can process them cleaner.
                dynamic entity = JObject.FromObject(entityResult);
                ((JArray)values).Add(entity.text);

                // get/create $instance
                JToken instanceRoot;
                if (!recognizerResult.Entities.TryGetValue("$instance", StringComparison.OrdinalIgnoreCase, out instanceRoot))
                {
                    instanceRoot = new JObject();
                    recognizerResult.Entities["$instance"] = instanceRoot;
                }

                // add instanceData
                JToken instanceData;
                if (!((JObject)instanceRoot).TryGetValue(entityResult.Type, StringComparison.OrdinalIgnoreCase, out instanceData))
                {
                    instanceData = new JArray();
                    instanceRoot[entityResult.Type] = instanceData;
                }

                dynamic instance = new JObject();
                instance.startIndex = entity.start;
                instance.endIndex   = entity.end;
                instance.score      = (double)1.0;
                instance.text       = entity.text;
                instance.type       = entity.type;
                instance.resolution = entity.resolution;
                ((JArray)instanceData).Add(instance);
            }

            // if no match return None intent
            if (!recognizerResult.Intents.Keys.Any())
            {
                recognizerResult.Intents.Add("None", new IntentScore()
                {
                    Score = 1.0
                });
            }

            await dialogContext.Context.TraceActivityAsync(nameof(RegexRecognizer), JObject.FromObject(recognizerResult), "RecognizerResult", "Regex RecognizerResult", cancellationToken).ConfigureAwait(false);

            this.TrackRecognizerResult(dialogContext, "RegexRecognizerResult", this.FillRecognizerResultTelemetryProperties(recognizerResult, telemetryProperties), telemetryMetrics);

            return(recognizerResult);
        }