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