From cf86ebf9feeee10bbf0cada6d2fea0e61c804b88 Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Sat, 9 Sep 2023 15:05:18 +0800 Subject: [PATCH] update anonymous api context memory --- api/anonymous.go | 40 +++++++++++++++++++++------- api/card.go | 3 ++- app/src/conversation/anonymous.ts | 7 ++++- app/src/conversation/conversation.ts | 15 +++++++---- utils/encrypt.go | 5 ++++ 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/api/anonymous.go b/api/anonymous.go index cb0b63f..87da97e 100644 --- a/api/anonymous.go +++ b/api/anonymous.go @@ -13,8 +13,9 @@ import ( ) type AnonymousRequestBody struct { - Message string `json:"message" required:"true"` - Web bool `json:"web"` + Message string `json:"message" required:"true"` + Web bool `json:"web"` + History []types.ChatGPTMessage `json:"history"` } type AnonymousResponseCache struct { @@ -58,27 +59,45 @@ func TestKey(key string) bool { return res.(map[string]interface{})["choices"] != nil } -func GetAnonymousResponse(message string, web bool) (string, string, error) { +func GetAnonymousResponse(message []types.ChatGPTMessage, web bool) (string, string, error) { if !web { - resp, err := GetChatGPTResponse([]types.ChatGPTMessage{{Role: "user", Content: message}}, 1000) + resp, err := GetChatGPTResponse(message, 1000) return "", resp, err } - keyword, source := ChatWithWeb([]types.ChatGPTMessage{{Role: "user", Content: message}}, false) + keyword, source := ChatWithWeb(message, false) resp, err := GetChatGPTResponse(source, 1000) return keyword, resp, err } -func GetAnonymousResponseWithCache(c *gin.Context, message string, web bool) (string, string, error) { +func GetSegmentMessage(data []types.ChatGPTMessage, length int) []types.ChatGPTMessage { + if len(data) <= length { + return data + } + return data[len(data)-length:] +} + +func GetAnonymousMessage(message string, history []types.ChatGPTMessage) []types.ChatGPTMessage { + return append( + GetSegmentMessage(history, 5), + types.ChatGPTMessage{ + Role: "user", + Content: strings.TrimSpace(message), + }) +} + +func GetAnonymousResponseWithCache(c *gin.Context, message string, web bool, history []types.ChatGPTMessage) (string, string, error) { + segment := GetAnonymousMessage(message, history) + hash := utils.Md5Encrypt(utils.ToJson(segment)) cache := c.MustGet("cache").(*redis.Client) - res, err := cache.Get(c, fmt.Sprintf(":chatgpt-%v:%s", web, message)).Result() + res, err := cache.Get(c, fmt.Sprintf(":chatgpt-%v:%s", web, hash)).Result() form := utils.UnmarshalJson[AnonymousResponseCache](res) if err != nil || len(res) == 0 || res == "{}" || form.Message == "" { - key, res, err := GetAnonymousResponse(message, web) + key, res, err := GetAnonymousResponse(segment, web) if err != nil { return "", "There was something wrong...", err } - cache.Set(c, fmt.Sprintf(":chatgpt-%v:%s", web, message), utils.ToJson(AnonymousResponseCache{ + cache.Set(c, fmt.Sprintf(":chatgpt-%v:%s", web, hash), utils.ToJson(AnonymousResponseCache{ Keyword: key, Message: res, }), time.Hour*48) @@ -108,7 +127,8 @@ func AnonymousAPI(c *gin.Context) { }) return } - key, res, err := GetAnonymousResponseWithCache(c, message, body.Web) + + key, res, err := GetAnonymousResponseWithCache(c, message, body.Web, body.History) if err != nil { c.JSON(http.StatusOK, gin.H{ "status": false, diff --git a/api/card.go b/api/card.go index f1560d8..747e20f 100644 --- a/api/card.go +++ b/api/card.go @@ -1,6 +1,7 @@ package api import ( + "chat/types" "github.com/gin-gonic/gin" "github.com/russross/blackfriday/v2" "net/http" @@ -57,7 +58,7 @@ func CardAPI(c *gin.Context) { return } - key, res, err := GetAnonymousResponseWithCache(c, message, body.Web) + key, res, err := GetAnonymousResponseWithCache(c, message, body.Web, []types.ChatGPTMessage{}) if err != nil { res = "There was something wrong..." } diff --git a/app/src/conversation/anonymous.ts b/app/src/conversation/anonymous.ts index 3327160..1d2c1ba 100644 --- a/app/src/conversation/anonymous.ts +++ b/app/src/conversation/anonymous.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import { Message } from "./types"; export type AnonymousResponse = { status: boolean; @@ -14,9 +15,13 @@ export type AnonymousProps = { export async function requestAnonymous( t: any, props: AnonymousProps, + history?: Message[], ): Promise { try { - const response = await axios.post("/anonymous", props); + const response = await axios.post("/anonymous", { + history, + ...props, + }); return response.data as AnonymousResponse; } catch (error) { console.debug(error); diff --git a/app/src/conversation/conversation.ts b/app/src/conversation/conversation.ts index 8d4af87..3764829 100644 --- a/app/src/conversation/conversation.ts +++ b/app/src/conversation/conversation.ts @@ -110,9 +110,13 @@ export class Conversation { }; } + public getSegmentData(length: number): Message[] { + return this.data.slice(this.data.length - length); + } + public sendAnonymous(t: any, props: AnonymousProps): void { this.end = false; - requestAnonymous(t, props).then((response) => { + requestAnonymous(t, props, this.getSegmentData(5)).then((response) => { this.addMessage({ content: response.message, role: "assistant", @@ -133,15 +137,16 @@ export class Conversation { public sendMessage(t: any, auth: boolean, props: SendMessageProps): boolean { if (!this.end) return false; - this.addMessage({ - content: props.message, - role: "user", - }); auth ? this.sendAuthenticated(t, props as AuthenticatedProps) : this.sendAnonymous(t, props as AnonymousProps); + this.addMessage({ + content: props.message, + role: "user", + }); + return true; } } diff --git a/utils/encrypt.go b/utils/encrypt.go index 52b1693..3566421 100644 --- a/utils/encrypt.go +++ b/utils/encrypt.go @@ -14,6 +14,11 @@ func Sha2Encrypt(raw string) string { return hex.EncodeToString(hash[:]) } +func Md5Encrypt(raw string) string { + hash := sha256.Sum256([]byte(raw)) + return hex.EncodeToString(hash[:]) +} + func AES256Encrypt(key string, data string) (string, error) { text := []byte(data) block, err := aes.NewCipher([]byte(key))