|
@@ -33,9 +33,11 @@ type ChatbotContext struct {
|
|
|
|
|
|
// ChatbotInteraction defines a individual question/answer interaction with a caller
|
|
|
type ChatbotInteraction struct {
|
|
|
- Time string `json:"time,omitempty" yaml:"time,omitempty"`
|
|
|
- Question string `json:"question,omitempty" yaml:"question,omitempty"`
|
|
|
- Answer string `json:"answer,omitempty" yaml:"answer,omitempty"`
|
|
|
+ Time string `json:"time,omitempty" yaml:"time,omitempty"`
|
|
|
+ Question string `json:"question,omitempty" yaml:"question,omitempty"`
|
|
|
+ PatternGroup string `json:"patternGroup,omitempty" yaml:"patternGroup,omitempty"`
|
|
|
+ Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
|
|
+ Answer string `json:"answer,omitempty" yaml:"answer,omitempty"`
|
|
|
}
|
|
|
|
|
|
// SessionData defines information about the current bot and its interaction within a specific session
|
|
@@ -54,37 +56,34 @@ func NewBotPersonality(personality *Personality, context *ChatbotContext) *Chatb
|
|
|
|
|
|
}
|
|
|
|
|
|
-// Greetings will return a random introductory sentence for ELIZA.
|
|
|
-func (p *Chatbot) Greetings() string {
|
|
|
- return p.randChoice(p.Personality.Introductions)
|
|
|
+func NewChatbotInteraction(question, patterngroup, answer string) ChatbotInteraction {
|
|
|
+ return ChatbotInteraction{Time: time.Now().UTC().String(), Question: question, PatternGroup: patterngroup, Answer: answer}
|
|
|
}
|
|
|
|
|
|
-// GoodbyeResponse will return a random goodbye sentence for ELIZA.
|
|
|
-func (p *Chatbot) GoodbyeResponse() string {
|
|
|
- return p.randChoice(p.Personality.Goodbyes)
|
|
|
+func NewChatbotInteractionWithPattern(question, patterngroup, pattern, answer string) ChatbotInteraction {
|
|
|
+ return ChatbotInteraction{Time: time.Now().UTC().String(), Question: question, PatternGroup: patterngroup, Pattern: pattern, Answer: answer}
|
|
|
}
|
|
|
|
|
|
// ReplyTo will construct a reply for a given statement using ELIZA's rules.
|
|
|
-func (p *Chatbot) ReplyTo(statement string) string {
|
|
|
+func (p *Chatbot) ReplyTo(statement string) ChatbotInteraction {
|
|
|
// First, preprocess the statement for more effective matching
|
|
|
statement = p.preprocess(statement)
|
|
|
|
|
|
// Then, we check if this is a quit statement
|
|
|
if p.IsQuitStatement(statement) {
|
|
|
- return p.GoodbyeResponse()
|
|
|
+ return NewChatbotInteraction(statement, "QuitResponses", p.GoodbyeResponse())
|
|
|
}
|
|
|
|
|
|
// Next, we try to match the statement to a statement that ELIZA can
|
|
|
// recognize, and construct a pre-determined, appropriate response.
|
|
|
for _, similarQuestionResponse := range p.Personality.Psychobabble {
|
|
|
- for _, question := range similarQuestionResponse.SimilarQuestions {
|
|
|
- re := regexp.MustCompile(question)
|
|
|
+ for _, questionPattern := range similarQuestionResponse.SimilarQuestions {
|
|
|
+ re := regexp.MustCompile(questionPattern)
|
|
|
matches := re.FindStringSubmatch(statement)
|
|
|
|
|
|
// If the statement matched any recognizable statements.
|
|
|
if len(matches) > 0 {
|
|
|
- // If we matched a regex group in parentheses, get the first match.
|
|
|
- // The matched regex group will match a "fragment" that will form
|
|
|
+ // If we matched a regex group in parentheses, get the first match. The matched regex group will match a "fragment" that will form
|
|
|
// part of the response, for added realism.
|
|
|
var fragment string
|
|
|
if len(matches) > 1 {
|
|
@@ -98,13 +97,23 @@ func (p *Chatbot) ReplyTo(statement string) string {
|
|
|
response = fmt.Sprintf(response, fragment)
|
|
|
}
|
|
|
// fmt.Printf("For Statement \"%s\" got a hit with pattern \"%s\" Responded With \"%s\"\n", statement, pattern, response)
|
|
|
- return p.replacePlaceHolders(response)
|
|
|
+ return NewChatbotInteractionWithPattern(statement, "Psychobabble", questionPattern, p.replacePlaceHolders(response))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// If no patterns were matched, return a default response.
|
|
|
- return p.replacePlaceHolders(p.randChoice(p.Personality.DefaultResponses))
|
|
|
+ return NewChatbotInteraction(statement, "DefaultResponses", p.replacePlaceHolders(p.randChoice(p.Personality.DefaultResponses)))
|
|
|
+}
|
|
|
+
|
|
|
+// Greetings will return a random introductory sentence for ELIZA.
|
|
|
+func (p *Chatbot) Greetings() string {
|
|
|
+ return p.randChoice(p.Personality.Introductions)
|
|
|
+}
|
|
|
+
|
|
|
+// GoodbyeResponse will return a random goodbye sentence for ELIZA.
|
|
|
+func (p *Chatbot) GoodbyeResponse() string {
|
|
|
+ return p.randChoice(p.Personality.Goodbyes)
|
|
|
}
|
|
|
|
|
|
// IsQuitStatement returns if the statement is a quit statement
|
|
@@ -152,7 +161,16 @@ func (p *Chatbot) randChoice(list []string) string {
|
|
|
*/
|
|
|
func (p *Chatbot) replacePlaceHolders(answer string) string {
|
|
|
var tBuffer bytes.Buffer
|
|
|
- t := template.Must(template.New("answer").Parse(answer))
|
|
|
+ funcsMap := template.FuncMap{
|
|
|
+ "dayOfWeek": dayOfWeek,
|
|
|
+ "fullDate": date,
|
|
|
+ "year": year,
|
|
|
+ }
|
|
|
+
|
|
|
+ rawTemplate := template.New("answer")
|
|
|
+ tmpl := rawTemplate.Funcs(funcsMap)
|
|
|
+
|
|
|
+ t, _ := tmpl.Parse(answer)
|
|
|
t.Execute(&tBuffer, p.Context)
|
|
|
|
|
|
return tBuffer.String()
|