123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- package eliza
- import (
- "bytes"
- "fmt"
- "html/template"
- "math/rand"
- "regexp"
- "strings"
- "time"
- )
- func NewBotPersonality(personality *Personality, context *ChatbotContext) *Chatbot {
- return &Chatbot{personality, context}
- }
- func NewChatbotInteraction(question, patterngroup, rawanswer, answer string) ChatbotInteraction {
- return ChatbotInteraction{Time: time.Now().UTC().String(), Question: question, PatternGroup: patterngroup, RawAnswer: rawanswer, Answer: answer}
- }
- func NewChatbotInteractionWithPattern(question, patterngroup, pattern, rawanswer, answer string) ChatbotInteraction {
- return ChatbotInteraction{Time: time.Now().UTC().String(), Question: question, PatternGroup: patterngroup, Pattern: pattern, RawAnswer: rawanswer, Answer: answer}
- }
- func (p *Chatbot) ReplyTo(statement string) ChatbotInteraction {
-
- statement = p.preprocess(statement)
- var rawResponse string
-
- if p.IsQuitStatement(statement) {
- rawResponse = p.GoodbyeResponse()
- return NewChatbotInteraction(statement, "QuitResponses", rawResponse, rawResponse)
- }
-
-
- for _, similarQuestionResponse := range p.Personality.Psychobabble {
- for _, questionPattern := range similarQuestionResponse.SimilarQuestions {
- re := regexp.MustCompile(questionPattern)
- matches := re.FindStringSubmatch(statement)
-
- if len(matches) > 0 {
-
-
- var fragment string
- if len(matches) > 1 {
- fragment = p.reflect(matches[1])
- }
-
-
- response := p.randChoice(similarQuestionResponse.Responses)
- if strings.Contains(response, "%s") {
- response = fmt.Sprintf(response, fragment)
- }
-
- return NewChatbotInteractionWithPattern(statement, "Psychobabble", questionPattern, response, p.replacePlaceHolders(response))
- }
- }
- }
-
- rawResponse = p.randChoice(p.Personality.DefaultResponses)
- return NewChatbotInteraction(statement, "DefaultResponses", rawResponse, p.replacePlaceHolders(rawResponse))
- }
- func (p *Chatbot) Greetings() string {
- return p.randChoice(p.Personality.Introductions)
- }
- func (p *Chatbot) GoodbyeResponse() string {
- return p.randChoice(p.Personality.Goodbyes)
- }
- func (p *Chatbot) IsQuitStatement(statement string) bool {
- statement = p.preprocess(statement)
- for _, quitResponse := range p.Personality.QuitResponses {
- if statement == quitResponse {
- return true
- }
- }
- return false
- }
- func (p *Chatbot) preprocess(statement string) string {
- statement = strings.TrimRight(statement, "\n.!")
- statement = strings.ToLower(statement)
- return statement
- }
- func (p *Chatbot) reflect(fragment string) string {
- words := strings.Split(fragment, " ")
- for i, word := range words {
- if reflectedWord, ok := p.Personality.ReflectedWords[word]; ok {
- words[i] = reflectedWord
- }
- }
- return strings.Join(words, " ")
- }
- func (p *Chatbot) randChoice(list []string) string {
-
- if len(list) == 0 {
- return ""
- }
- rand.Seed(time.Now().UnixNano())
- maxAttempts := 2 * len(list)
-
-
- previousResponseHash := make(map[uint32]bool)
- for _, r := range p.Context.Session.Conversation {
- previousResponseHash[hash(r.RawAnswer)] = true
- }
- var candidate string
- for i := 1; i <= maxAttempts; i++ {
- randIndex := rand.Intn(len(list))
- candidate = list[randIndex]
- h := hash(candidate)
- _, known := previousResponseHash[h]
-
-
- if !known {
- return candidate
- }
- }
-
- return candidate
- }
- func (p *Chatbot) replacePlaceHolders(answer string) string {
- var tBuffer bytes.Buffer
- 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()
- }
|