public virtual ConversationResponse ProcessUserInput(IConversationContext context)
        {
            if (string.IsNullOrWhiteSpace(context.Result.Query) || context.Result == null)
            {
                return(IntentProvider.GetDefaultResponse(context.AppId));
            }

            // gather data
            var intent         = IntentProvider.GetTopScoringIntent(context);
            var conversation   = context.GetCurrentConversation();
            var isConfident    = context.Result.TopScoringIntent.Score > ApiKeys.LuisIntentConfidenceThreshold;
            var hasValidIntent = intent != null && isConfident;
            var inConversation = conversation != null && !conversation.IsEnded;
            var requestedQuit  = hasValidIntent && intent.KeyName.Equals(context.QuitIntentName);

            // if the user is trying to end or finish a conversation
            if (inConversation && requestedQuit)
            {
                return(EndCurrentConversation(context));
            }

            // continue conversation
            if (inConversation)
            {
                return(HandleCurrentConversation(context));
            }

            // is a user frustrated or is their intention unclear
            var sentimentScore = context.Result.SentimentAnalysis?.score ?? 1;

            return((sentimentScore <= 0.4)
                ? IntentProvider.GetIntent(context.AppId, context.FrustratedIntentName)?.Respond(null, null, null) ?? IntentProvider.GetDefaultResponse(context.AppId)
                : IntentProvider.GetDefaultResponse(context.AppId));
        }
        /// <summary>
        /// tries to determine a value for the requested parameter from a number of possible locations; current response entities, current response, previously provided information (context), or previously provided entities
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public virtual string SearchUserValues(string paramName, IConversationContext context)
        {
            var c = context.GetCurrentConversation();

            var paramAlignment = new Dictionary <string, string> {
                { "Date", "builtin.datetimeV2.datetime" }
            };

            if (IsParamRequest(paramName, c)) // was the user responding to a specific request
            {
                return(context.Result.Query);
            }

            var entityType    = paramAlignment.ContainsKey(paramName) ? paramAlignment[paramName] : paramName;
            var currentEntity = context.Result?.Entities?.FirstOrDefault(x => x.Type.Equals(entityType))?.Entity;

            if (currentEntity != null) // check the current request entities
            {
                return(currentEntity);
            }

            if (c.Data.ContainsKey(paramName)) // check the context data
            {
                return(c.Data[paramName].DisplayName);
            }

            var initialEntity = c.Result?.Entities?.FirstOrDefault(x => x.Type.Equals(entityType))?.Entity;

            if (initialEntity != null) // check the initial request entities
            {
                return(initialEntity);
            }

            return(string.Empty);
        }
        /// <summary>
        /// Create a response to the user requesting a specific parameter
        /// </summary>
        /// <param name="param">the parameter details</param>
        /// <param name="c">the conversation it occurs in</param>
        /// <param name="parameters">context parameters</param>
        /// <param name="message"></param>
        /// <returns></returns>
        public virtual ConversationResponse RequestParam(IFieldParameter param, IConversationContext context, string message)
        {
            var c = context.GetCurrentConversation();

            c.Data[ReqParam] = new ParameterData {
                DisplayName = param.ParamName
            };

            if (string.IsNullOrWhiteSpace(message))
            {
                message = param.GetParameter("", context).Error;
            }

            var intentInput = param.GetInput(context.Parameters, c);

            return(ConversationResponseFactory.Create(c.Intent.KeyName, message, c.IsEnded, intentInput));
        }
        public IParameterResult GetParameter(string paramValue, IConversationContext context)
        {
            var conversation  = context.GetCurrentConversation();
            var hasParamValue = !string.IsNullOrWhiteSpace(paramValue);
            var dataExists    = conversation.Data.ContainsKey(ParamName);

            if (!dataExists)
            {
                conversation.Data[ParamName] = new ParameterData {
                    Value = new ListItem("", ""), IsIncomplete = true
                }
            }
            ;

            var data = (ListItem)conversation.Data[ParamName].Value;

            if (string.IsNullOrWhiteSpace(data.Text))
            {
                if (hasParamValue)
                {
                    hasParamValue = false;
                    data.Text     = paramValue;
                }
                else
                {
                    return(ResultFactory.GetFailure(FirstParamMessage));
                }
            }

            //if has first response then ask for second request
            if (string.IsNullOrWhiteSpace(data.Value))
            {
                if (hasParamValue)
                {
                    data.Value = paramValue;
                    conversation.Data[ParamName].IsIncomplete = false;
                }
                else
                {
                    return(ResultFactory.GetFailure(SecondParamMessage));
                }
            }

            return(ResultFactory.GetSuccess($"{data.Text} : {data.Value}", data));
        }
예제 #5
0
        public bool IsValid(IConversationContext context)
        {
            var conversation = context.GetCurrentConversation();

            var rootItem = (Item)conversation.Data[ItemKey].Value;
            var language = (Language)conversation.Data[LangKey].Value;
            var langItem = rootItem.Database.GetItem(rootItem.ID, language);

            var worflowId    = langItem.Fields[Sitecore.FieldIDs.Workflow].Value;
            var workflowItem = ID.IsID(worflowId)
                ? rootItem.Database.GetItem(new ID(worflowId))
                : null;

            var workflow = workflowItem != null
                ? rootItem.Database.WorkflowProvider.GetWorkflow(workflowItem)
                : null;

            return(workflow == null || workflow.GetState(rootItem).FinalState);
        }
        /// <summary>
        /// get a valid parameter object by checking for it in the previously retrieved data store or by finding it based on the information provided by the user
        /// </summary>
        /// <param name="paramName">the parameter to retrieve</param>
        /// <param name="context"></param>
        /// <returns></returns>
        public virtual IParameterResult LookupParam(IFieldParameter param, IConversationContext context)
        {
            var c = context.GetCurrentConversation();

            var storedValue = c.Data.ContainsKey(param.ParamName)
                ? c.Data[param.ParamName]
                : null;

            if (storedValue != null && !storedValue.IsIncomplete)
            {
                return(ResultFactory.GetSuccess(storedValue.DisplayName, storedValue.Value));
            }

            string value = SearchUserValues(param.ParamName, context);

            if (string.IsNullOrEmpty(value))
            {
                return(ResultFactory.GetFailure());
            }

            var paramResult = param.GetParameter(value, context);

            if (paramResult.HasFailed)
            {
                return(paramResult);
            }

            if (IsParamRequest(param.ParamName, c)) // clear any request for this property
            {
                c.Data.Remove(ReqParam);
            }

            c.Data[param.ParamName] = new ParameterData {
                DisplayName = paramResult.DisplayName, Value = paramResult.DataValue
            };
            return(ResultFactory.GetSuccess(paramResult.DisplayName, paramResult.DataValue));
        }
예제 #7
0
        public IParameterResult GetParameter(string paramValue, IConversationContext context)
        {
            var conversation  = context.GetCurrentConversation();
            var hasParamValue = string.IsNullOrWhiteSpace(paramValue);
            var dataExists    = conversation.Data.ContainsKey(DataKey);

            //find or setup temp storage
            var data = dataExists
                ? (Dictionary <string, string>)conversation.Data[DataKey].Value
                : new Dictionary <string, string>();

            if (!dataExists)
            {
                conversation.Data[DataKey] = new ParameterData {
                    Value = data
                }
            }
            ;

            var profileItem = (Item)conversation.Data[ProfileItemKey].Value;
            var keys        = ProfileService.GetProfileKeys(profileItem);

            if (!keys.Any())
            {
                conversation.IsEnded = true;
                return(ResultFactory.GetFailure("There are no keys on this profile"));
            }

            for (int i = 0; i < keys.Count; i++)
            {
                var k       = keys[i];
                var keyName = k.Fields["Name"].Value;
                if (data.ContainsKey(keyName))
                {
                    continue;
                }

                var minValue = ProfileService.GetMinValue(k);
                var maxValue = ProfileService.GetMaxValue(k);
                if (string.IsNullOrWhiteSpace(paramValue))
                {
                    return(ResultFactory.GetFailure(string.Format(ParamMessage, keyName, minValue, maxValue)));
                }

                int outInt = 0;
                if (!int.TryParse(paramValue, out outInt))
                {
                    return(ResultFactory.GetFailure("That's not a valid number."));
                }

                data[keyName] = paramValue;

                //if no next param them return
                var j = i + 1;
                if (j == keys.Count)
                {
                    continue;
                }

                var nextKey      = keys[j];
                var nextKeyName  = ProfileService.GetProfileName(nextKey);
                var nextMinValue = ProfileService.GetMinValue(nextKey);
                var nextMaxValue = ProfileService.GetMaxValue(nextKey);

                return(ResultFactory.GetFailure(string.Format(ParamMessage, nextKeyName, nextMinValue, nextMaxValue)));
            }

            //remove temp storage
            conversation.Data.Remove(DataKey);

            return(ResultFactory.GetSuccess(string.Join(", ", data.Values), data));
        }
        public virtual ConversationResponse HandleCurrentConversation(IConversationContext context)
        {
            var conversation = context.GetCurrentConversation();

            var clear = $"{context.ClearText} ";

            if (context.Result.Query.StartsWith(clear))
            {
                var clearParam = context.Result.Query.Replace(clear, "");
                if (conversation.Data.ContainsKey(clearParam))
                {
                    conversation.Data.Remove(clearParam);
                }
            }

            // save confirmation
            if (conversation.Intent.RequiresConfirmation &&
                conversation.Data.ContainsKey(ReqConfirm) &&
                context.Result.TopScoringIntent.Intent.Equals(context.YesIntentName, StringComparison.InvariantCultureIgnoreCase))
            {
                conversation.IsConfirmed = true;
                conversation.Data.Remove(ReqConfirm);
            }

            // check and request all parameters of a conversation
            foreach (IConversationParameter p in conversation.Intent.ConversationParameters)
            {
                var vParameter = p as IValidationParameter;
                if (vParameter != null && !vParameter.IsValid(context))
                {
                    context.GetCurrentConversation().IsEnded = true;
                    return(ConversationResponseFactory.Create(conversation.Intent.KeyName, vParameter.GetErrorMessage()));
                }

                var rParam = p as IFieldParameter;
                if (rParam == null)
                {
                    continue;
                }

                var parameterResult = LookupParam(rParam, context);
                if (!parameterResult.HasFailed)
                {
                    continue;
                }

                var isYesIntent = context.Result.TopScoringIntent.Intent.Equals(context.YesIntentName, StringComparison.InvariantCultureIgnoreCase);
                var isNoIntent  = context.Result.TopScoringIntent.Intent.Equals(context.NoIntentName, StringComparison.InvariantCultureIgnoreCase);

                //if response to first request is no then return
                if (rParam.IsOptional && !conversation.Data.ContainsKey(rParam.ParamName))
                {
                    if (!isNoIntent && !isYesIntent)
                    {
                        return(ConversationResponseFactory.Create(conversation.Intent.KeyName, $"Do you want to select a {rParam.ParamName}?", conversation.IsEnded, "yesorno"));
                    }

                    if (isNoIntent)
                    {
                        conversation.Data[rParam.ParamName] = new ParameterData {
                            Value = ""
                        };
                        context.Result.TopScoringIntent.Intent = "";
                        continue;
                    }
                }

                return(RequestParam(rParam, context, parameterResult.Error));
            }

            // confirm selected options with user
            if (conversation.Intent.RequiresConfirmation && !conversation.IsConfirmed)
            {
                conversation.Data[ReqConfirm] = new ParameterData {
                    DisplayName = "confirm"
                };
                return(ConversationResponseFactory.Create(conversation.Intent.KeyName, context.ConfirmText, conversation.IsEnded, "confirm", conversation.Data));
            }

            conversation.IsEnded = true;

            return(conversation.Intent.Respond(context.Result, context.Parameters, conversation));
        }
        public virtual ConversationResponse EndCurrentConversation(IConversationContext context)
        {
            context.GetCurrentConversation().IsEnded = true;

            return(IntentProvider.GetTopScoringIntent(context)?.Respond(null, null, null) ?? IntentProvider.GetDefaultResponse(context.AppId));
        }