Refactor chat history and message processing

- Added `Hidden` flag to `Message` struct for controlling message visibility
- Modified `saveChatHistory` to conditionally save messages based on hidden status
- Simplified stream chat processing by removing debug print statements
- Restructured message output and next action handling in stream chat
- Commented out unused process action execution method
This commit is contained in:
Max 2025-02-06 16:39:31 +08:00
parent d69370551a
commit dabba1a744
2 changed files with 56 additions and 76 deletions

View file

@ -9,8 +9,6 @@ import (
"github.com/gin-gonic/gin"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/utils"
chatctx "github.com/yaoapp/yao/neo/context"
chatMessage "github.com/yaoapp/yao/neo/message"
)
@ -115,35 +113,37 @@ func (ast *Assistant) execute(c *gin.Context, ctx chatctx.Context, input []chatM
func (next *NextAction) Execute(c *gin.Context, ctx chatctx.Context, contents *chatMessage.Contents) error {
switch next.Action {
case "process":
if next.Payload == nil {
return fmt.Errorf("payload is required")
}
// It's not used, because the process could be executed in the hook script
// It may remove in the future
// case "process":
// if next.Payload == nil {
// return fmt.Errorf("payload is required")
// }
name, ok := next.Payload["name"].(string)
if !ok {
return fmt.Errorf("process name should be string")
}
// name, ok := next.Payload["name"].(string)
// if !ok {
// return fmt.Errorf("process name should be string")
// }
args := []interface{}{}
if v, ok := next.Payload["args"].([]interface{}); ok {
args = v
}
// args := []interface{}{}
// if v, ok := next.Payload["args"].([]interface{}); ok {
// args = v
// }
// Add context and writer to args
args = append(args, ctx, c.Writer)
p, err := process.Of(name, args...)
if err != nil {
return fmt.Errorf("get process error: %s", err.Error())
}
// // Add context and writer to args
// args = append(args, ctx, c.Writer)
// p, err := process.Of(name, args...)
// if err != nil {
// return fmt.Errorf("get process error: %s", err.Error())
// }
err = p.Execute()
if err != nil {
return fmt.Errorf("execute process error: %s", err.Error())
}
defer p.Release()
// err = p.Execute()
// if err != nil {
// return fmt.Errorf("execute process error: %s", err.Error())
// }
// defer p.Release()
return nil
// return nil
case "assistant":
if next.Payload == nil {
@ -201,6 +201,7 @@ func (next *NextAction) Execute(c *gin.Context, ctx chatctx.Context, contents *c
options = v
}
input.Hidden = true // not show in the history
messages, err := assistant.withHistory(ctx, input)
if err != nil {
return fmt.Errorf("with history error: %s", err.Error())
@ -263,9 +264,6 @@ func (ast *Assistant) handleChatStream(c *gin.Context, ctx chatctx.Context, mess
if err != nil {
chatMessage.New().Error(err).Done().Write(c.Writer)
}
ast.saveChatHistory(ctx, messages, contents)
fmt.Printf("saveChatHistory %v\n", ctx.ChatID)
done <- true
}()
@ -418,30 +416,8 @@ func (ast *Assistant) streamChat(
// Complete the stream
if msg.IsDone {
// if value == "" {
// msg.Write(c.Writer)
// }
// Remove the last empty data
contents.RemoveLastEmpty()
res, hookErr := ast.HookDone(c, ctx, messages, contents)
if hookErr == nil && res != nil {
if res.Next != nil {
fmt.Println("---- Execute Next ---")
utils.Dump(res.Next)
fmt.Println("---- Execute Next end ---")
err := res.Next.Execute(c, ctx, contents)
if err != nil {
chatMessage.New().Error(err.Error()).Done().Write(c.Writer)
}
done <- true
return 0 // break
}
} else if delta != "" {
// Send the last message to the client
if delta != "" {
chatMessage.New().
Map(map[string]interface{}{
"assistant_id": ast.ID,
@ -455,22 +431,36 @@ func (ast *Assistant) streamChat(
Write(c.Writer)
}
// Hook execute error
// Remove the last empty data
contents.RemoveLastEmpty()
res, hookErr := ast.HookDone(c, ctx, messages, contents)
// Some error occurred in the hook, return the error
if hookErr != nil {
chatMessage.New().Error(hookErr.Error()).Done().Write(c.Writer)
done <- true
return 0 // break
}
msg := chatMessage.New().Done()
if res != nil && res.Output != nil {
msg = chatMessage.New().
Map(map[string]interface{}{
"text": res.Input,
"done": true,
})
// Save the chat history
ast.saveChatHistory(ctx, messages, contents)
// If the hook is successful, execute the next action
if res != nil && res.Next != nil {
err := res.Next.Execute(c, ctx, contents)
if err != nil {
chatMessage.New().Error(err.Error()).Done().Write(c.Writer)
}
done <- true
return 0 // break
}
msg.Write(c.Writer)
// The default output
output := chatMessage.New().Done()
if res != nil && res.Output != nil {
output = chatMessage.New().Map(map[string]interface{}{"text": res.Output, "done": true})
}
output.Write(c.Writer)
done <- true
return 0 // break
}
@ -516,20 +506,9 @@ func (ast *Assistant) saveChatHistory(ctx chatctx.Context, messages []chatMessag
},
}
// contents
fmt.Println("---contents ---")
if contents.Data != nil {
fmt.Println("---contents.Data ---")
for _, content := range contents.Data {
fmt.Println(content.Map())
}
fmt.Println("---contents.Data end ---")
}
fmt.Println("---contents end ---")
// Add mentions
if userMessage.Mentions != nil {
data[0]["mentions"] = userMessage.Mentions
// if the user message is hidden, just save the assistant message
if userMessage.Hidden {
data = []map[string]interface{}{data[1]}
}
storage.SaveHistory(ctx.Sid, data, ctx.ChatID, ctx.Map())

View file

@ -33,6 +33,7 @@ type Message struct {
Mentions []Mention `json:"menions,omitempty"` // Mentions for the message ( for user role = user )
Data map[string]interface{} `json:"-"` // data for the message
Pending bool `json:"-"` // pending for the message
Hidden bool `json:"hidden,omitempty"` // hidden for the message (not show in the UI and history)
}
// Mention represents a mention