Эх сурвалжийг харах

eliza-011 : Added placeholder replacement and version commands

Answer is now treated as a golang template and bot context - inc environment has been added.

Added 'version' to the personality which uses the above placeholder.

Added embeded version string from makefile
gremlin 4 жил өмнө
parent
commit
b8f0249f75
6 өөрчлөгдсөн 99 нэмэгдсэн , 58 устгасан
  1. 10 7
      bots/eliza.json
  2. 10 7
      bots/ivanka.json
  3. 49 12
      eliza/eliza.go
  4. 3 0
      infrastructure/version.go
  5. 25 30
      main.go
  6. 2 2
      makefile

+ 10 - 7
bots/eliza.json

@@ -1,20 +1,20 @@
 {
     "name": "Eliza",
-    "version": "v0.0.1",
+    "version": "v0.0.2",
     "commands": {
        "version":[""]
     },
     "introductions": [
-        "Hello, How are you feeling today?",
+        "Hello {{.Session.User}} ... How are you feeling today?",
         "How do you do. Are you seeking help today?",
-        "Please tell me what's been bothering you.",
-        "Is something troubling you?"
+        "Please tell me what's been bothering you {{.Session.User}}",
+        "Is something troubling you {{.Session.User}}?"
     ],
     "goodbyes": [
         "Farewell. It was lovely speaking with you.",
         "Thank you for talking with me today.",
         "Thank you, that will be $150. Have a good day!",
-        "Goodbye. This was nice, hopefully we do it again sometime.",
+        "Goodbye {{.Session.User}}. This was nice, hopefully we do it again sometime.",
         "Goodbye. I'm looking forward to our next session.",
         "Well.. I guess time is up, call back anytime!",
         "Maybe we could discuss this over more in our next session? Goodbye.",
@@ -37,14 +37,14 @@
             "I don't know -- why can't you %s?",
             "Have you really tried?"
         ],
-        "^eliza": [
+        "^{{.Session.User}}": [
             "That's the name, therapy is my game.",
             "Yes?",
             "That's me.",
             "Ah so you remember my name."
         ],
         "(.*) your name?": [
-            "My name is Eliza",
+            "My name is {{.Session.User}}",
             "I thought that would be self explanatory.",
             "....Look up."
         ],
@@ -311,6 +311,9 @@
             "Always here to help",
             "Anytime",
             "What else can I do to help you?"
+        ],
+        "version":[
+            "Chatbot '{{.Session.Bot}}' version {{.Session.BotVersion}}, Engine {{.EngineVersion}}"
         ]
     },
     "defaultResponses": [

+ 10 - 7
bots/ivanka.json

@@ -1,20 +1,20 @@
 {
     "name": "Ivanka",
-    "version": "v0.0.1",
+    "version": "v0.0.2",
     "commands": {
        "version":[""]
     },
     "introductions": [
-        "Hello, How are you feeling today?",
+        "Hello {{.Session.User}} ... How are you feeling today?",
         "How do you do. Are you seeking help today?",
-        "Please tell me what's been bothering you.",
-        "Is something troubling you?"
+        "Please tell me what's been bothering you {{.Session.User}}",
+        "Is something troubling you {{.Session.User}}?"
     ],
     "goodbyes": [
         "Farewell. It was lovely speaking with you.",
         "Thank you for talking with me today.",
         "Thank you, that will be $150. Have a good day!",
-        "Goodbye. This was nice, hopefully we do it again sometime.",
+        "Goodbye {{.Session.User}}. This was nice, hopefully we do it again sometime.",
         "Goodbye. I'm looking forward to our next session.",
         "Well.. I guess time is up, call back anytime!",
         "Maybe we could discuss this over more in our next session? Goodbye.",
@@ -37,14 +37,14 @@
             "I don't know -- why can't you %s?",
             "Have you really tried?"
         ],
-        "^Ivanka": [
+        "^{{.Session.Bot}}": [
             "That's the name, therapy is my game.",
             "Yes?",
             "That's me.",
             "Ah so you remember my name."
         ],
         "(.*) your name?": [
-            "My name is Ivanka",
+            "My name is {{.Session.Bot}}",
             "I thought that would be self explanatory.",
             "....Look up."
         ],
@@ -311,6 +311,9 @@
             "Always here to help",
             "Anytime",
             "What else can I do to help you?"
+        ],
+        "version":[
+            "Chatbot '{{.Session.Bot}}' version {{.Session.BotVersion}}, Engine {{.EngineVersion}}"
         ]
     },
     "defaultResponses": [

+ 49 - 12
eliza/eliza.go

@@ -4,7 +4,9 @@
 package eliza
 
 import (
+	"bytes"
 	"fmt"
+	"html/template"
 	"math/rand"
 	"regexp"
 	"strings"
@@ -15,27 +17,51 @@ type InteractiveBot interface {
 	ReplyTo(statement string) string
 }
 
-type BotPersonality struct {
+type Chatbot struct {
 	Personality *Personality
+	Context     *ChatbotContext
 }
 
-func NewBotPersonality(personality *Personality) *BotPersonality {
-	return &BotPersonality{personality}
+type ChatbotContext struct {
+	EngineVersion string
+	Session       SessionData
+}
+
+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"`
+}
+
+/***********************************************************************************************
+* This is stored as JSON in the cache (redis)
+ ***********************************************************************************************/
+type SessionData struct {
+	SessionID    string               `json:"sessionID" yaml:"sessionID"`
+	StartTime    string               `json:"startTime,omitempty" yaml:"startTime,omitempty"`
+	User         string               `json:"user,omitempty" yaml:"user,omitempty"`
+	Bot          string               `json:"bot,omitempty" yaml:"bot,omitempty"`
+	BotVersion   string               `json:"botVersion,omitempty" yaml:"botVersion,omitempty"`
+	Conversation []ChatbotInteraction `json:"conversation,omitempty" yaml:"conversation,omitempty"`
+}
+
+func NewBotPersonality(personality *Personality, context *ChatbotContext) *Chatbot {
+	return &Chatbot{personality, context}
 
 }
 
 // Greetings will return a random introductory sentence for ELIZA.
-func (p *BotPersonality) Greetings() string {
+func (p *Chatbot) Greetings() string {
 	return p.randChoice(p.Personality.Introductions)
 }
 
 // GoodbyeResponse will return a random goodbye sentence for ELIZA.
-func (p *BotPersonality) GoodbyeResponse() string {
+func (p *Chatbot) GoodbyeResponse() string {
 	return p.randChoice(p.Personality.Goodbyes)
 }
 
 // ReplyTo will construct a reply for a given statement using ELIZA's rules.
-func (p *BotPersonality) ReplyTo(statement string) string {
+func (p *Chatbot) ReplyTo(statement string) string {
 	// First, preprocess the statement for more effective matching
 	statement = p.preprocess(statement)
 
@@ -67,16 +93,16 @@ func (p *BotPersonality) 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 response
+			return p.replacePlaceHolders(response)
 		}
 	}
 
 	// If no patterns were matched, return a default response.
-	return p.randChoice(p.Personality.DefaultResponses)
+	return p.replacePlaceHolders(p.randChoice(p.Personality.DefaultResponses))
 }
 
 // IsQuitStatement returns if the statement is a quit statement
-func (p *BotPersonality) IsQuitStatement(statement string) bool {
+func (p *Chatbot) IsQuitStatement(statement string) bool {
 	statement = p.preprocess(statement)
 	for _, quitResponse := range p.Personality.QuitResponses {
 		if statement == quitResponse {
@@ -87,14 +113,14 @@ func (p *BotPersonality) IsQuitStatement(statement string) bool {
 }
 
 // preprocess will do some normalization on a statement for better regex matching
-func (p *BotPersonality) preprocess(statement string) string {
+func (p *Chatbot) preprocess(statement string) string {
 	statement = strings.TrimRight(statement, "\n.!")
 	statement = strings.ToLower(statement)
 	return statement
 }
 
 // reflect flips a few words in an input fragment (such as "I" -> "you").
-func (p *BotPersonality) reflect(fragment string) string {
+func (p *Chatbot) reflect(fragment string) string {
 	words := strings.Split(fragment, " ")
 	for i, word := range words {
 		if reflectedWord, ok := p.Personality.ReflectedWords[word]; ok {
@@ -105,7 +131,7 @@ func (p *BotPersonality) reflect(fragment string) string {
 }
 
 // randChoice returns a random element in an (string) array.
-func (p *BotPersonality) randChoice(list []string) string {
+func (p *Chatbot) randChoice(list []string) string {
 	// Added for truly random generation of numbers with seeds
 	if len(list) == 0 {
 		return ""
@@ -114,3 +140,14 @@ func (p *BotPersonality) randChoice(list []string) string {
 	randIndex := rand.Intn(len(list))
 	return list[randIndex]
 }
+
+/**
+* Replaces conversation templates (names etc) in reply with
+ */
+func (p *Chatbot) replacePlaceHolders(answer string) string {
+	var tBuffer bytes.Buffer
+	t := template.Must(template.New("answer").Parse(answer))
+	t.Execute(&tBuffer, p.Context)
+
+	return tBuffer.String()
+}

+ 3 - 0
infrastructure/version.go

@@ -0,0 +1,3 @@
+package infrastructure
+
+var Version string = "unknown"

+ 25 - 30
main.go

@@ -14,6 +14,7 @@ import (
 
 	"git.riomhaire.com/gremlin/elizaservice/eliza"
 	"git.riomhaire.com/gremlin/elizaservice/facades/cache"
+	"git.riomhaire.com/gremlin/elizaservice/infrastructure"
 	"github.com/gofrs/uuid"
 	"github.com/jaffee/commandeer"
 
@@ -33,23 +34,6 @@ var bots embed.FS
 var cacheManager cache.BotCache
 var cacheTTL int
 
-type BotInteraction 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"`
-}
-
-/***********************************************************************************************
-* This is stored as JSON in the cache (redis)
- ***********************************************************************************************/
-type SessionData struct {
-	SessionID    string           `json:"sessionID" yaml:"sessionID"`
-	StartTime    string           `json:"startTime,omitempty" yaml:"startTime,omitempty"`
-	User         string           `json:"user,omitempty" yaml:"user,omitempty"`
-	Bot          string           `json:"bot,omitempty" yaml:"bot,omitempty"`
-	Conversation []BotInteraction `json:"conversation,omitempty" yaml:"conversation,omitempty"`
-}
-
 /***********************************************************************************************
 *
  ***********************************************************************************************/
@@ -75,25 +59,29 @@ func NewMain() *Main {
 /********************************
 This appends to session in cache latest info
 *********************************/
-func addToConversation(sessionID, bot, user, question, answer string) {
-	sessionData := SessionData{}
+func storeConversation(sessionID string, sessionData eliza.SessionData) {
+
+	// Save it as json
+	j, _ := json.Marshal(sessionData)
+	cacheManager.Store(sessionID, string(j), cacheTTL)
+}
+
+/********************************
+This retrieves the context from the cache
+*********************************/
+func retrieveConversation(sessionID, bot, botversion, user string) (sessionData eliza.SessionData) {
 	// Lookup session
 	jsonValue, found, _ := cacheManager.Retrieve(sessionID, false)
 
 	if !found {
-		sessionData = SessionData{SessionID: sessionID, Bot: bot, User: user, StartTime: time.Now().UTC().String(), Conversation: make([]BotInteraction, 0)}
+		sessionData = eliza.SessionData{SessionID: sessionID, Bot: bot, BotVersion: botversion, User: user, StartTime: time.Now().UTC().String(), Conversation: make([]eliza.ChatbotInteraction, 0)}
 	}
 	if found {
 		if err := json.Unmarshal([]byte(jsonValue), &sessionData); err != nil {
-			sessionData = SessionData{SessionID: sessionID, Bot: bot, User: user, StartTime: time.Now().UTC().String(), Conversation: make([]BotInteraction, 0)}
+			sessionData = eliza.SessionData{SessionID: sessionID, Bot: bot, BotVersion: botversion, User: user, StartTime: time.Now().UTC().String(), Conversation: make([]eliza.ChatbotInteraction, 0)}
 		}
 	}
-	// OK addToConversation
-	botInteraction := BotInteraction{time.Now().UTC().String(), question, answer}
-	sessionData.Conversation = append(sessionData.Conversation, botInteraction)
-	// Save it as json
-	j, _ := json.Marshal(sessionData)
-	cacheManager.Store(sessionID, string(j), cacheTTL)
+	return
 }
 
 /***********************************************************************************************
@@ -150,16 +138,23 @@ func chantboInteractiontEndpoint(c echo.Context) error {
 	if err != nil {
 		return c.String(http.StatusOK, err.Error())
 	}
+	// Restore Conversation Context
+	sessionData := retrieveConversation(sessionID, botname, personality.Version, user)
 
 	// Return Eliza's response's so long as the user doesn't give a quit statement
-	character := eliza.NewBotPersonality(&personality)
+	chatboxContext := eliza.ChatbotContext{infrastructure.Version, sessionData}
+	character := eliza.NewBotPersonality(&personality, &chatboxContext)
 	answer := character.ReplyTo(question)
 
 	msg := fmt.Sprintf("Bot [%s %s] Session ID [%s] Question [%s] Answer [%s]", botname, personality.Version, sessionID, question, answer)
 	fmt.Println(msg)
 
 	// update cache
-	addToConversation(sessionID, botname, user, question, answer)
+	// OK addToConversation
+	botInteraction := eliza.ChatbotInteraction{time.Now().UTC().String(), question, answer}
+	sessionData.Conversation = append(sessionData.Conversation, botInteraction)
+
+	storeConversation(sessionID, sessionData)
 
 	// Return Eliza's answer
 	return c.String(http.StatusOK, answer)
@@ -218,7 +213,7 @@ func (m *Main) Run() error {
 ██╔══╝  ██║     ██║ ███╔╝  ██╔══██║
 ███████╗███████╗██║███████╗██║  ██║
 ╚══════╝╚══════╝╚═╝╚══════╝╚═╝  ╚═╝`)
-
+	fmt.Println("Application Version : ", infrastructure.Version)
 	// Create Cache Manager (redis)
 	cacheManager = cache.NewRedisCache(m.Cache)
 	cacheTTL = m.CacheTTL

+ 2 - 2
makefile

@@ -9,7 +9,7 @@ dependencies:
 build: dependencies
 	@echo Compiling Apps
 	@echo   --- eliza-server $(V)
-	@go build -o eliza-server git.riomhaire.com/gremlin/elizaservice
+	@go build -o eliza-server -ldflags="-s -w -X git.riomhaire.com/gremlin/elizaservice/infrastructure.Version=$(V)" git.riomhaire.com/gremlin/elizaservice
 	@upx  -9 eliza-server
 	@cp eliza-server ${GOPATH}/bin
 	@echo Done Compiling Apps
@@ -17,7 +17,7 @@ build: dependencies
 build-arm: dependencies
 	@echo Compiling Apps
 	@echo   --- eliza-server arm version
-	@GOOS=linux GOARCH=arm GOARM=5  go build -o eliza-server-arm git.riomhaire.com/gremlin/elizaservice
+	@GOOS=linux GOARCH=arm GOARM=5  go build -o eliza-server-arm  -ldflags="-s -w -X git.riomhaire.com/gremlin/elizaservice/infrastructure.Version=$(V)" git.riomhaire.com/gremlin/elizaservice
 	@upx  -9 eliza-server-arm
 	@echo Done Compiling Apps