public override async Task <ParseResult> ParseAsync(ChatState chatState, Chat_ParseField chatParseField, ChatMessage message) { var preFlowName = chatParseField.GetProperty("preFlowName"); var preStepId = chatParseField.GetProperty("preStepId"); var postFlowName = chatParseField.GetProperty("postFlowName"); var postStepId = chatParseField.GetProperty("postStepId"); if (String.IsNullOrEmpty(preFlowName) || String.IsNullOrEmpty(preStepId) || String.IsNullOrEmpty(postFlowName) || String.IsNullOrEmpty(postStepId)) { throw new ApplicationException("Parse: Missing rule data for IntentGateway Parser."); } message.Classifications = await ClassifyText(message.CorrectedUserInput, preFlowName, preStepId, postFlowName, postStepId, chatState.SessionData.IsSmsChannel); chatState.UpdateLastClassification(message.Classifications); if (!message.Classifications.IsSuccessful) { return(ParseResult.Failed); } // We don't want common chat intent's here. var intent = chatState.LastClassification.GetBestResult().Intent; if (intent != null && intent.StartsWith("commonchat-")) { return(ParseResult.Failed); } return(ParseResult.CreateSuccess(message.Classifications.GetBestResult().Result)); }
public override async Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { string agentName = state.GlobalAnswers.GetFieldAnswer <string>(ChatStandardField.AgentName); (var names, var tokens) = await GetNamesAndTokens(message.UserInput, agentName); if (tokens == null) { logger.Error("Network: Failed to call text parser service."); return(ParseResult.Failed); } // If we didnt detect any names, and the user entered only 2 or 3 words (possible names), // and no look behind (to cut down on false positives), we retry with "My name is " prepended // since the NLP is better at picking up names in a sentence. if ((names.Count == 0) && (tokens.Count <= 3) && (!chatParseField.CheckPreviousMessages)) { (names, tokens) = await GetNamesAndTokens("My name is " + message.UserInput, agentName); } names.AddRange(GetUndetectedNames(message.UserInput)); // Add our test name if detected if (message.UserInput.ToUpper().Contains(TestName.ToUpper())) { names.AddRange(TestName.Split(' ')); } if (names.Count > 0) { return(ParseResult.CreateSuccess(names.Distinct().ToArray())); } return(ParseResult.Failed); }
KinesisParseEventContent CreateParseEventContent(ChatModel chatModel, Chat_ParseField field, bool success, bool searchMode) { var step = chatModel.CurrentState.Steps.LastOrDefault(); var lastMessage = chatModel.CurrentState.GetLastMessage(); var properties = new Dictionary <string, object>(); var interactionId = log4net.LogicalThreadContext.Properties["interactionId"] as string; AddStandardProperties(chatModel.CurrentState.SessionData, properties); return(new KinesisParseEventContent() { Chat_id = chatModel.ChatId, Interaction_id = interactionId, Session_id = chatModel.SessionLogId, Session_date = DateTime.UtcNow.ToString("o"), Variable_name = field?.FieldName, FlowStep = new ChatStepId(step), Chat_text = filterService.FilterUserData(chatModel.CurrentState, lastMessage.UserInput), Chat_corrected_text = filterService.FilterUserData(chatModel.CurrentState, lastMessage.CorrectedUserInput), Bot_text = filterService.FilterUserData(chatModel.CurrentState, lastMessage.BotQuestionsText), Success = success, SearchMode = searchMode, Properties = properties }); }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { if (result.Success) { string[] names = result.Answer as string[]; var variables = GetChatVariables(state, flowStep, chatParseField.VarScope); // Set subvariables for first and last name if (names.Length > 0) { variables[$"{chatParseField.FieldName}_First"] = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(names[0]); CheckIfAnswerHasPII(state, PIIType, names[0], PIIMask); } if (names.Length > 1) { variables[$"{chatParseField.FieldName}_Last"] = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(names.Last()); CheckIfAnswerHasPII(state, PIIType, names[1], PIIMask); } // TODO: Use parse dependencies to join them properly. They will be marked as "compound". variables[chatParseField.FieldName] = String.Join(" ", names); } }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { string text = GetTextSource(chatParseField, message); // Shortcut for common case where flow tries to take all user input. // .* regex means all characters EXCEPT newlines. But the flow wants all including newlines // so running regex to collect all data doesn't make sense. So we just set the variable to everything. if (chatParseField.RuleData == ".*") { return(Task.FromResult(ParseResult.CreateSuccess(text))); } string regex = chatParseField?.GetProperty("Regex") ?? chatParseField.RuleData; try { var match = Regex.Match(text, regex, RegexOptions.IgnoreCase, ChatConfiguration.RegexTimeout); if (match.Success) { if (String.IsNullOrEmpty(chatParseField.Answer)) { return(Task.FromResult(ParseResult.CreateSuccess(match.Value))); } return(Task.FromResult(ParseResult.CreateSuccess(chatParseField.Answer))); } } catch (RegexMatchTimeoutException) { logger.ErrorFormat("Regex timed out. {0}", regex); } return(Task.FromResult(ParseResult.Failed)); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var tokens = TextClassificationService.Tokenize(message.UserInput); // HTC One and iPhone match words quite easily var cleanedTokens = (from t in tokens where t != "phone" && t != "phones" && t != "phone's" && t != "the" && t != "tone" select t.ToLower()).ToArray(); (string matchedText, int matchedIndex, float ratio) = MatchService.FindMatch(cleanedTokens, 1, 4, deviceCatalog.MatchCharacters); var device = deviceCatalog.MakeModelList[matchedIndex]; var deviceMatch = new DeviceMatchResult { Id = device.Id, Make = device.Make, Model = device.Model, DisplayName = device.DisplayName, IsUncommon = device.IsUncommon, Ratio = ratio }; double minConfidence = ChatConfiguration.MinimumDeviceConfidence; if (device.IsUncommon) { minConfidence = ChatConfiguration.MinimumUncommonDeviceConfidence; } if (deviceMatch.Ratio > minConfidence) { return(Task.FromResult(ParseResult.CreateSuccess(deviceMatch))); } return(Task.FromResult(ParseResult.Failed)); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var matches = Regex.Matches(message.UserInput, @"\d+") .Cast <Match>() .Select(m => m.Value) .ToArray(); if (matches.Length == 0) { return(Task.FromResult(ParseResult.Failed)); } var setting = chatParseField?.GetProperty("AllowedValues"); if (String.IsNullOrEmpty(setting)) { return(Task.FromResult(ParseResult.CreateSuccess(int.Parse(matches[0])))); } var allowedValues = setting.Split(',', ' '); var foundValue = allowedValues.Where(b => matches.Any(a => b.Contains(a))).FirstOrDefault(); if (foundValue == null) { return(Task.FromResult(ParseResult.Failed)); } return(Task.FromResult(ParseResult.CreateSuccess(int.Parse(foundValue)))); }
public async Task SendClassificationEvent(ChatModel chat, Chat_ParseField field, bool success, bool searchMode, ClassificationResults classification) { var content = CreateParseEventContent(chat, field, success, searchMode); var bestResult = classification.GetBestResult(); if (bestResult != null) { content.Source = bestResult.Source; content.Result = bestResult.Intent; content.ResultData = bestResult.Result; content.ResultProbability = bestResult.Probability; } content.Classifications = (from c in classification.AllResults select new KinesisClassification { Model_source = c.Source, Model_prediction = c.Intent, Model_score = c.Probability, Model_rawResponse = c.RawResponse }).ToArray(); await InternalSendKinesisParseEvent("classification", "intent_classifier", chat, content); }
public override async Task <ParseResult> ParseAsync(ChatState chatState, Chat_ParseField chatParseField, ChatMessage message) { int timezoneOffset = chatState.GetUserTimeZoneOffset(); if (message.LuisDateOutput == null) { message.LuisDateOutput = await luisService.Parse(message.UserInput, timezoneOffset); } var assumeFuture = false; if (bool.TryParse(chatParseField?.GetProperty("AssumeFuture"), out bool test)) { assumeFuture = test; } var results = ExtractDateResults(chatState, message.LuisDateOutput, assumeFuture); if ((results == null) || (results.Length == 0)) { logger.InfoFormat("Parse: luis date parser got nothing. - {0}", (message.LuisDateOutput != null) ? JsonConvert.SerializeObject(message.LuisDateOutput) : "null"); return(ParseResult.Failed); } if (version == 1) { return(ProcessAsV1Date(message, timezoneOffset, results)); } return(ParseResult.CreateSuccess(results)); }
public virtual void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { if (result.Success) { GetChatVariables(state, flowStep, chatParseField.VarScope)[chatParseField.FieldName] = result.Answer; CheckIfAnswerHasPII(state, chatParseField, result.Answer.ToString(), PIIMask); } }
public virtual string GetTextSource(Chat_ParseField chatParseField, ChatMessage chatMessage) { if (chatParseField.SourceData == ChatSource.CorrectedInput) { return(chatMessage.CorrectedUserInput?.Trim()); } return(chatMessage.UserInput?.Trim()); }
private void UpdateV1State(ChatState state, Chat_ParseField chatParseField, ParseResult result, ChatVariables variables) { DateTime date = (DateTime)result.Answer; int offset = state.GetUserTimeZoneOffset(); variables[chatParseField.FieldName] = date.AddHours(offset).ToShortDateString(); variables[chatParseField.FieldName + "_Date"] = date; CheckIfAnswerHasPII(state, chatParseField, date.ToString(), PIIMask); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { string text = GetTextSource(chatParseField, message); if (Regex.IsMatch(text, DontKnowRegex, RegexOptions.IgnoreCase)) { return(Task.FromResult(ParseResultDontKnow)); } return(Task.FromResult(ParseResult.Failed)); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var match = Regex.Match(GetTextSource(chatParseField, message), ZipCodeRegex); if (match.Success) { return(Task.FromResult(ParseResult.CreateSuccess(match.Captures[0].Value))); } return(Task.FromResult(ParseResult.Failed)); }
public override async Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var output = await addressParseService.Parse(chatId, state, GetTextSource(chatParseField, message)); if (output?.addresses?.Length > 0) { return(ParseResult.CreateSuccess(output.addresses)); } return(ParseResult.Failed); }
protected virtual void CheckIfAnswerHasPII(ChatState state, Chat_ParseField chatParseField, string answer, string mask) { var piiType = chatParseField.PIIType; if (piiType == PIIType.None) { piiType = PIIType; } CheckIfAnswerHasPII(state, piiType, answer, mask); }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { if (result.Success) { var variables = GetChatVariables(state, flowStep, chatParseField.VarScope); var intents = result.Answer as string[]; variables[chatParseField.FieldName] = intents[0]; variables[chatParseField.FieldName + "List"] = intents; } }
private void CheckIfDatesHavePII(ChatState state, Chat_ParseField chatParseField, ParseResult parseResult) { DateTimeParseResult[] results = (DateTimeParseResult[])parseResult.Answer; foreach (var result in results) { if (result.DateTime.HasValue) { CheckIfAnswerHasPII(state, chatParseField, result.DateTime.Value.ToShortDateString(), PIIMask); } } }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { foreach (var provider in BackupProviders.ProviderNames) { if (BackupProviders.IsMatch(message.CorrectedUserInput, provider)) { return(Task.FromResult(ParseResult.CreateSuccess(provider))); } } return(Task.FromResult(ParseResult.Failed)); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { // Check both corrected and original input, since our spell checker can't handle at&t properly. var result = Match(message.CorrectedUserInput); if (result.Success) { return(Task.FromResult(result)); } return(Task.FromResult(Match(message.UserInput))); }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { var variables = GetChatVariables(state, flowStep, chatParseField.VarScope); if (result.Success) { variables[chatParseField.FieldName] = result.Answer; CheckIfAnswerHasPII(state, PIIType, result.Answer.ToString(), PIIMask); } if (!String.IsNullOrEmpty(foundPartial)) { variables[$"{chatParseField.FieldName}_Try"] = foundPartial + ".com"; } }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var(text, index, ratio) = MatchService.FindMatch(message.UserInput.ToLower(), 1, MaxTokenMatch, colorCatalog.ColorCodeChars); if (ratio < ChatConfiguration.MinimumColorMatchRatio) { return(Task.FromResult(ParseResult.Failed)); } var color = colorCatalog.Colors[index]; return(Task.FromResult(ParseResult.CreateSuccess(new ColorResult { Name = color.name, Ratio = ratio }))); }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { base.UpdateState(state, flowStep, chatParseField, result); if (result.Success) { var addresses = result.Answer as AddressPart[]; CheckIfAnswerHasPII(state, PIIType, addresses[0].address1, "ADDRESS"); CheckIfAnswerHasPII(state, PIIType, addresses[0].address2, "ADDRESS"); CheckIfAnswerHasPII(state, PIIType, addresses[0].city, "CITY"); CheckIfAnswerHasPII(state, PIIType, addresses[0].region, "STATE"); CheckIfAnswerHasPII(state, PIIType, addresses[0].postalCode, "ZIPCODE"); } }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { if (String.Compare(message.CorrectedUserInput, "view solution", true) == 0) { return(Task.FromResult(ParseResult.CreateSuccess("viewedSolution"))); } else if (Regex.IsMatch(message.CorrectedUserInput, ContinueRegex, RegexOptions.IgnoreCase)) { return(Task.FromResult(ParseResultYes)); } else if (Regex.IsMatch(message.CorrectedUserInput, YesNoParser.NoRegex, RegexOptions.IgnoreCase)) { return(Task.FromResult(ParseResultNo)); } return(Task.FromResult(ParseResult.Failed)); }
public override async Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { if (message.LuisDamageClassifierOutput == null) { message.LuisDamageClassifierOutput = await luisService.Parse(message.CorrectedUserInput, 0); } string[] intents = message.LuisDamageClassifierOutput.GetIntents(ChatConfiguration.MinLuisConfidenceRatio); if (intents?.Length > 0) { return(ParseResult.CreateSuccess(intents)); } // AVA-997: Always use None if we didn't parse anything. return(ParseResultNoneList); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var matches = Regex.Matches(GetTextSource(chatParseField, message), AppNamesRegex, RegexOptions.IgnoreCase); if (matches.Count > 0) { string[] apps = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { apps[i] = matches[i].Value; } return(Task.FromResult(ParseResult.CreateSuccess(apps))); } return(Task.FromResult(ParseResult.Failed)); }
public override Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { var matches = Regex.Matches(message.CorrectedUserInput, BluetoothDeviceNoRegex, RegexOptions.IgnoreCase); if (matches.Count > 0) { string[] apps = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { apps[i] = matches[i].Value; } return(Task.FromResult(ParseResult.CreateSuccess(apps))); } return(Task.FromResult(ParseResult.Failed)); }
public override async Task <ParseResult> ParseAsync(ChatState state, Chat_ParseField chatParseField, ChatMessage message) { int matchThreshold = ChatConfiguration.FuzzyNameMatchThreshold; if (!String.IsNullOrEmpty(chatParseField.RuleData)) { matchThreshold = Convert.ToInt32(chatParseField.RuleData); } FuzzyMatchParserData[] possibleMatches = await GetPossibleMatches(state, chatFlowStep, chatParseField); if (UtilityMethods.IsNullOrEmpty(possibleMatches)) { logger.WarnFormat("Parse: Invalid field data for fuzzy match. {0} - {1}", chatParseField.FieldName, chatParseField.SourceData); return(ParseResult.Failed); } // Get list of test values for API var testVals = possibleMatches.Select(x => x.text).ToArray(); var response = await fuzzyMatchService.Match(GetTextSource(chatParseField, message), testVals); if (response == null) { logger.Error("Network: Failed to call fuzzy match service."); return(ParseResult.Failed); } if (response.Output?.Length > 0) { IEnumerable <FuzzyMatchParserResult> matches = FindMatches(matchThreshold, possibleMatches, response); if (matches.Count() > 0) { return(ParseResult.CreateSuccess(matches.First())); } } else { logger.Debug("Parse: No fuzzy matches found."); } // Always return true that we processed the text even if we didnt find a matching name. return(ParseResult.CreateSuccess(null)); }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult parseResult) { if (!parseResult.Success) { return; } var variables = GetChatVariables(state, flowStep, chatParseField.VarScope); if (version == 1) { UpdateV1State(state, chatParseField, parseResult, variables); return; } CheckIfDatesHavePII(state, chatParseField, parseResult); variables[chatParseField.FieldName] = parseResult.Answer; }
public override void UpdateState(ChatState state, ChatFlowStep flowStep, Chat_ParseField chatParseField, ParseResult result) { var variables = GetChatVariables(state, flowStep, chatParseField.VarScope); if (result.Success && (result.Answer is FuzzyMatchParserResult answer)) { // Convert back to Dictionary for proper formatting, and script access var x = JsonConvert.SerializeObject(answer); variables[chatParseField.FieldName + "_MatchInfo"] = JsonConvert.DeserializeObject <Dictionary <string, object> >(x); variables[chatParseField.FieldName] = true; // Send both user's input and matched input as PII. CheckIfAnswerHasPII(state, chatParseField, answer.match.ToString(), PIIMask); CheckIfAnswerHasPII(state, chatParseField, answer.text.ToString(), PIIMask); } else { variables[chatParseField.FieldName] = false; } }