public InputRecognizer(string text, string ruleId, string inputId, string condition, Dictionary <string, Synonym> synonyms, List <InputReplacement> alInputReplacements) { this.inputReplacements = alInputReplacements; System.Text.RegularExpressions.Regex regexVarsEq = new Regex(@"\[.+?=.+?\]"); System.Text.RegularExpressions.Regex regexVars = new Regex(@"\[.*?\]"); System.Text.RegularExpressions.Regex regexSyns = new Regex(@"\(.*?\)"); string textReplaced = regexVarsEq.Replace(text, "xx"); textReplaced = regexVars.Replace(textReplaced, "x"); textReplaced = regexSyns.Replace(textReplaced, "x"); textReplaced = textReplaced.Replace("*", ""); this.length = textReplaced.Length; text = TextToolbox.ReplaceSynonyms(text, synonyms); //do this last because replacements haven't been applied to synonyms text = TextToolbox.ReplaceOnInput(text, alInputReplacements, out this.bIsCapture); string pattern = TextToolbox.TextToPattern(text); this.regex = new Regex(pattern, /*RegexOptions.Compiled | */ RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); //TODO: Does the IgnoreCase Work? //regex.IsMatch("x"); this.ruleId = ruleId; this.inputId = inputId; this.condition = condition; if (InputRecognizer.random == null) { InputRecognizer.random = new Random(); } }
}//ReplaceOnInput(string text, List<InputReplacement> replacements) public static string ReplaceSynonyms(string input, Dictionary <string, Synonym> synonyms) { int start = input.IndexOf("("); int end; while (start != -1) { end = TextToolbox.FindNextMatchingChar(input, start); if (end != -1) { string synonymName = input.Substring(start + 1, end - start - 1).Trim().ToLower(); if (synonyms.ContainsKey(synonymName)) { input = input.Substring(0, start + 1) + ((Synonym)synonyms[synonymName]).GetPhrases() + input.Substring(end); } else { input = input.Substring(0, start) + "(" + synonymName + ")" + input.Substring(end + 1); } start = input.IndexOf("(", start + 1); } else //there's an error with this input, it won't compile { //TODO: log an error somewhere? return(""); } } return(input); }//replaceSynonyms(string input, Dictionary<string, Synonym> synonymGroups)
}//replaceSynonyms(string input, Dictionary<string, Synonym> synonymGroups) public static string ReplaceOutputSynonyms(string text, Dictionary <string, Synonym> synonyms) { int start = text.IndexOf("("); int end; while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string synonymName = text.Substring(start + 1, end - start - 1).Trim().ToLower(); if (synonyms.ContainsKey(synonymName) && !TextToolbox.IsInCommand(text, start, end - start)) { Synonym syn = ((Synonym)synonyms[synonymName]); if (syn.Phrases.Count > 0) { Random rand = new Random(); int pick = rand.Next(syn.Phrases.Count); if (end == text.Length - 1) //the end is the end { text = text.Substring(0, start) + ((Phrase)syn.Phrases[pick]).Text; } else { text = text.Substring(0, start) + ((Phrase)syn.Phrases[pick]).Text + text.Substring(end + 1); } } else { text = text.Substring(0, start + 1) + synonymName + text.Substring(end); } } start = text.IndexOf("(", start + 1); } else { //TODO: log an error somewhere? return(text); } } else //it's escaped \(.. { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf("(", start); } } } //while return(text); }//replaceSynonyms(string input, Dictionary<string, Synonym> synonymGroups)
/// <summary> /// Uses given InputReplacements to change text /// </summary> /// <param name="text">change text</param> /// <param name="inputReplacements">list of Replacements</param> /// <returns>resulting replaced text</returns> public static string ReplaceOnInput(string text, List <InputReplacement> replacements, out bool bIsCapture) { StringBuilder sb = new StringBuilder(); if (text.IndexOf("[") == -1) { bIsCapture = false; if (replacements.Count > 0) { int depth = 0; for (int i = 0; i < text.Length; i++) { bool replaced = false; if (text[i] == '[') { depth++; } else if (text[i] == ']') { depth--; } else if (depth == 0) { foreach (InputReplacement ir in replacements) { if (i < text.Length - ir.TextToFind.Length + 1 && ir.TextToFind == text.Substring(i, ir.TextToFind.Length)) { replaced = true; sb.Append(ir.TextToInput); i += ir.TextToFind.Length - 1; break; //can only replace with one thing } } //foreach(InputReplacement repl in inputReplacements) } if (!replaced) { sb.Append(text[i]); } } //for(int i = 0; i < text.Length; i++) } else //if we don't have any input replacements, just do the default (remove accents) { //TODO: add if(prefs.useDefaultInputReplacements) sb.Append(TextToolbox.ApplyDefaultInputReplacements(text)); } } else { bIsCapture = true; sb.Append(text); //if it is a capture, we won't replace anything } return(sb.ToString()); }//ReplaceOnInput(string text, List<InputReplacement> replacements)
public static int FindNextUnescapedChar(string text, char ch, int start) { for (int i = start; i < text.Length; i++) { if (text[i] == ch && !TextToolbox.IsEscaped(text, i)) { return(i); } } return(-1); }
public static string ApplyDefaultInputReplacements(string text) { //ÀÁÂÃÄÅàáâãäåÆæÇçÈÉÊËèéêëÌÍÎÏìíîïÑñÒÓÔÕÖòóôõöÙÚÛÜùúûüÝýÿ.!?,"':; StringBuilder sb = new StringBuilder(text); List <InputReplacement> alDefaultInputReplacements = TextToolbox.GetDefaultInputReplacements(); foreach (InputReplacement ir in alDefaultInputReplacements) { sb.Replace(ir.TextToFind, ir.TextToInput); } return(sb.ToString()); } //ApplyDefaultInputReplacements(string text)
} //doTextReplacements(string text) public string DoAgentTextReplacements(string text) { foreach (Replacement r in this.replacements) { if (r.TextToFind != null && r.TextToFind != "") { int pos = text.IndexOf(r.TextToFind); while (pos != -1) { if (!TextToolbox.IsInCommand(text, pos, r.TextToFind.Length)) { if (pos + r.TextToFind.Length < text.Length - 1) { text = text.Substring(0, pos) + r.TextForAgent + text.Substring(pos + r.TextToFind.Length); } else { text = text.Substring(0, pos) + r.TextForAgent; } } if (pos < text.Length - 1) { pos = text.IndexOf(r.TextToFind, pos + 1); } else { pos = -1; } } //while } //if } //foreach return(text); } //doAgentTextReplacements(string text)
public string GetNewOutputId() { return(TextToolbox.GetNewId()); }
public string GetNewRuleId() { return(TextToolbox.GetNewId()); }
} //ApplyDefaultInputReplacements(string text) public static int FindNextUnexcapedChar(string text, char ch) { return(TextToolbox.FindNextUnescapedChar(text, ch, 0)); }
}//replaceSynonyms(string input, Dictionary<string, Synonym> synonymGroups) public static string ReplaceVars(string text, Hashtable vars) { int start = text.IndexOf("["); int end; while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string varName = TextToolbox.ReplaceVars(text.Substring(start + 1, end - start - 1), vars); string varDefaultValue = ""; if (varName.IndexOf(':') != -1) { varDefaultValue = varName.Substring(varName.IndexOf(':') + 1).Trim(); varName = varName.Substring(0, varName.IndexOf(':')).Trim(); } varName = varName.Replace(" ", "_"); string varValue = (string)vars[varName.ToLower()]; if (varValue == null) { varValue = varDefaultValue; } if (end == text.Length - 1) //var runs to the end { text = text.Substring(0, start) + varValue; start = -1; } else { text = text.Substring(0, start) + varValue + text.Substring(end + 1); start = text.IndexOf("[", start + varValue.Length); } } else //there's an error with this input, it won't compile { //TODO: log an error somewhere? return(""); } } else // [ is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf("[", start); } } } //while we have more [vars] string embCmd = "<mem.get "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string name = text.Substring(start + embCmd.Length, end - start - embCmd.Length); string left = ""; if (start > 0) { left = text.Substring(0, start); } string right = ""; if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + vars[name.ToLower()] + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.get name>s embCmd = "<mem.set "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string nameValue = text.Substring(start + embCmd.Length, end - start - embCmd.Length); string left = ""; string right = ""; string[] cmdArgs = TextToolbox.splitOnFirstUnquotedSpace(nameValue); if (cmdArgs.Length > 1) { string name = cmdArgs[0]; //remove quotes if they are there if (name.Length > 1 && name[0] == '"') { name = name.Substring(1); } if (name.Length > 2 && name[name.Length - 1] == '"') { name = name.Substring(0, name.Length - 1); } string val = cmdArgs[1]; vars[name.ToLower()] = val; } if (start > 0) { left = text.Substring(0, start); } if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.set name>s embCmd = "<mem.del "; start = text.IndexOf(embCmd); while (start != -1) { if (!TextToolbox.IsEscaped(text, start)) { end = TextToolbox.FindNextMatchingChar(text, start); if (end != -1) { string name = text.Substring(start + embCmd.Length, end - start - embCmd.Length); vars.Remove(name.Trim().ToLower()); string left = ""; string right = ""; if (start > 0) { left = text.Substring(0, start); } if (end + 1 != text.Length) { right = text.Substring(end + 1); } text = left + right; } start = text.IndexOf(embCmd); } else // < is escaped { //remove the '\' text = text.Remove(start - 1, 1); //find the next start if (start >= text.Length - 1) //the old start is now at the end { start = -1; } else { start = text.IndexOf(embCmd, start); } } } //while we have more <mem.set name>s return(text); } //ReplaceVars(string text, Hashtable vars)
} //outputs2Class() private string outputToCode(string text) { if (text == null) { return(""); } StringBuilder sb = new StringBuilder(); string uncode = ""; string code = ""; //break the text apart into text and code sections //test needs to be written to Console.Out //and code needs to be written as is while (text != "") { int openTagPos = text.IndexOf(this.openTag); while (openTagPos != -1 && TextToolbox.IsEscaped(text, openTagPos)) { text = text.Remove(openTagPos - 1, 1); openTagPos = text.IndexOf(this.openTag, openTagPos); } if (openTagPos != 0) //we have uncode to process { if (openTagPos == -1) //it's all uncode { uncode = text; text = ""; } else //it's uncode + code { uncode = text.Substring(0, openTagPos); text = text.Substring(openTagPos); } sb.Append("Console.Write(\""); sb.Append(this.escape(uncode)); sb.Append("\");\r\n"); } else //we have code to process (open is at the beginning) { int closeTagPos = text.IndexOf(this.closeTag); while (closeTagPos != -1 && TextToolbox.IsEscaped(text, closeTagPos)) { text = text.Remove(closeTagPos - 1, 1); closeTagPos = text.IndexOf(this.closeTag, closeTagPos); } if (closeTagPos == -1) { closeTagPos = text.Length; } code = text.Substring(this.openTag.Length, closeTagPos - this.openTag.Length).Trim(); if (code != "") { sb.Append(code); } if (closeTagPos + this.closeTag.Length < text.Length) { text = text.Substring(closeTagPos + this.closeTag.Length); } else { text = ""; } } } //while(text != "") return(sb.ToString()); } //outputToCode(string text)
/* * Accessor Methods */ public string GetNewSynoymId() { return(TextToolbox.GetNewId()); }
/* * Accessor Methods */ public string GetNewPhraseId() { return(TextToolbox.GetNewId()); }
}//compileRules(string parentId, List<Rule> rules) public Reply GetReply(string input, string lastfired, Hashtable vars, string prependOutput) { List <Match> matches = new List <Match>(); //do replacements, strip áccents is done in ReplaceOnInput if there are no input replacements string inputReplaced = TextToolbox.ReplaceOnInput(input, this.inputReplacements); //search the children and virtual children (links) of lastfired rule if (this.inputs.ContainsKey(lastfired)) { foreach (InputRecognizer ir in this.inputs[lastfired]) { //if the input recognizer is a capture, use the original input Match match = ir.Matches((ir.IsCapture ? input : inputReplaced), vars, this.csToolbox); if (match.ConfidenceFactor != 0.0) { //copy shortTermMemory vars to inputVars Hashtable inputVars = new Hashtable(); foreach (object key in vars.Keys) { inputVars[key] = vars[key]; } //captures the variables and adds them to the inputVars object ir.CaptureVars(input, inputVars); matches.Add(match); } } } if (matches.Count == 0 && this.inputs.ContainsKey("_root")) { //search all of the primaries foreach (InputRecognizer ir in this.inputs["_root"]) { //if the input recognizer is a capture, use the original input Match match = ir.Matches((ir.IsCapture ? input : inputReplaced), vars, this.csToolbox); if (match.ConfidenceFactor != 0.0) { //copy shortTermMemory vars to inputVars Hashtable inputVars = new Hashtable(); foreach (object key in vars.Keys) { inputVars[key] = vars[key]; } //captures the variables and adds them to the inputVars object ir.CaptureVars(input, inputVars); matches.Add(match); } } } if (matches.Count == 0) { return(null); } matches.Sort(); Match matchBest = (Match)matches[0]; //use the matching vars, but maintain the original object so that it persists vars.Clone(); foreach (object key in matchBest.Vars.Keys) { vars[key] = matchBest.Vars[key]; } //increment the usage count on the chosed InputRecognizer matchBest.InputRecognizer.IncUsageCount(); string ruleId = matchBest.InputRecognizer.RuleId; if (!this.outputs.ContainsKey(ruleId) || this.outputs[ruleId].Count == 0) { Reply noOutputFoundReply = new Reply("Rule contains no outputs.", "", "", ruleId, 0, this.knowledgeBaseItem); if (this.csToolbox.StandardNoOutputFoundDefined) { string noOutputFoundText = this.csToolbox.ExecuteOnNoOutputFound(vars, noOutputFoundReply); noOutputFoundReply.Text += this.DoTextReplacements(noOutputFoundText); noOutputFoundReply.AgentText += this.DoAgentTextReplacements(noOutputFoundText); } return(noOutputFoundReply); } List <Output> alOutputs = new List <Output>(); if (this.outputs.ContainsKey(ruleId)) { alOutputs = new List <Output>(this.outputs[ruleId]); } bool trueNonEmptyOutputConditionFound = false; //filter out outputs with false conditions for (int i = 0; i < alOutputs.Count; i++) { Output o = (Output)alOutputs[i]; if (!this.csToolbox.ExecuteCondition(o.Id, vars)) { alOutputs.RemoveAt(i); i--; } else if (o.Condition != null && o.Condition != "") { trueNonEmptyOutputConditionFound = true; } } if (alOutputs.Count == 0)//all outputs were removed { Reply noOutputFoundReply = new Reply("No true output found.", "", "", ruleId, 0, this.knowledgeBaseItem); if (this.csToolbox.StandardNoOutputFoundDefined) { string noOutputFoundText = this.csToolbox.ExecuteOnNoOutputFound(vars, noOutputFoundReply); noOutputFoundReply.Text += this.DoTextReplacements(noOutputFoundText); noOutputFoundReply.AgentText += this.DoAgentTextReplacements(noOutputFoundText); } return(noOutputFoundReply); } //filter out outputs with no conditions if there is an output which has a true condition if (trueNonEmptyOutputConditionFound) { for (int i = 0; i < alOutputs.Count; i++) { Output o = (Output)alOutputs[i]; if (o.Condition == null || o.Condition == "") { alOutputs.RemoveAt(i); i--; } } } //choose an output at random Output outputChosen = null; for (int i = 0; i < alOutputs.Count; i++) //the try again loop { outputChosen = ((Output)alOutputs[random.Next(alOutputs.Count)]); if (!this.recentOutputsByRule.ContainsKey(ruleId) || !this.recentOutputsByRule[ruleId].Contains(outputChosen.Id)) { break; } } //update the recent list for this rule if (alOutputs.Count > 1) { if (!this.recentOutputsByRule.ContainsKey(ruleId)) { this.recentOutputsByRule[ruleId] = new List <string>(alOutputs.Count - 1); } List <string> recent = this.recentOutputsByRule[ruleId]; int index = recent.IndexOf(outputChosen.Id); if (index != -1) { recent.RemoveAt(index); } else if (recent.Count == alOutputs.Count - 1) { recent.RemoveAt(0); } recent.Add(outputChosen.Id); } //replace vars and output synonyms string outputChosenText = prependOutput + outputChosen.Text; if (this.csToolbox.OutputExists(outputChosen.Id)) { outputChosenText = this.csToolbox.ExecuteOutput(outputChosen.Id, vars); } outputChosenText = TextToolbox.ReplaceVars(outputChosenText, vars); outputChosenText = TextToolbox.ReplaceOutputSynonyms(outputChosenText, this.synonyms); //execute c# code in the command field string outputChosenCmd = outputChosen.Cmd; if (this.csToolbox.OutputExists(outputChosen.Id + "_cmd")) { outputChosenCmd = this.csToolbox.ExecuteOutput(outputChosen.Id + "_cmd", vars); } string outputText = this.DoTextReplacements(outputChosenText); string agentText = this.DoAgentTextReplacements(outputChosenText); string outputCmd = TextToolbox.ReplaceVars(outputChosenCmd, vars); return(new Reply(outputText, agentText, outputCmd, matchBest.InputRecognizer.RuleId, matchBest.ConfidenceFactor, this.knowledgeBaseItem)); } //GetReply(string input, string lastfired)