Refactor streaming chat and message processing
- Updated NextAction execution to send loading message and create new contents - Disabled stream hook temporarily to simplify message handling - Modified HookDone to filter and parse tool call messages - Removed debug print statements and simplified message generation - Improved message content processing during stream chat
This commit is contained in:
parent
9c0ab4e0e1
commit
d69370551a
2 changed files with 76 additions and 24 deletions
|
|
@ -206,11 +206,19 @@ func (next *NextAction) Execute(c *gin.Context, ctx chatctx.Context, contents *c
|
|||
return fmt.Errorf("with history error: %s", err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("---messages ---")
|
||||
utils.Dump(messages)
|
||||
fmt.Println(`chatID: `, ctx.ChatID)
|
||||
// Create a new Text
|
||||
// Send loading message and mark as new
|
||||
msg := chatMessage.New().Map(map[string]interface{}{
|
||||
"new": true,
|
||||
"role": "assistant",
|
||||
"type": "loading",
|
||||
"props": map[string]interface{}{"placeholder": "Calling " + assistant.Name},
|
||||
})
|
||||
msg.Assistant(assistant.ID, assistant.Name, assistant.Avatar)
|
||||
msg.Write(c.Writer)
|
||||
newContents := chatMessage.NewContents()
|
||||
|
||||
return assistant.execute(c, ctx, messages, options, contents)
|
||||
return assistant.execute(c, ctx, messages, options, newContents)
|
||||
|
||||
case "exit":
|
||||
return nil
|
||||
|
|
@ -360,33 +368,39 @@ func (ast *Assistant) streamChat(
|
|||
}
|
||||
|
||||
// New message with the tails
|
||||
newMsg, err := chatMessage.NewString(tails, id)
|
||||
if err != nil {
|
||||
return
|
||||
if tails != "" {
|
||||
newMsg, err := chatMessage.NewString(tails, id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
messages = append(messages, *newMsg)
|
||||
}
|
||||
messages = append(messages, *newMsg)
|
||||
})
|
||||
|
||||
// Handle stream
|
||||
res, err := ast.HookStream(c, ctx, messages, msg, contents)
|
||||
if err == nil && res != nil {
|
||||
// The stream hook is not used, because there's no need to handle the stream output
|
||||
// if some thing need to be handled in future, we can use the stream hook again
|
||||
// ------------------------------------------------------------------------------
|
||||
// res, err := ast.HookStream(c, ctx, messages, msg, contents)
|
||||
// if err == nil && res != nil {
|
||||
|
||||
if res.Next != nil {
|
||||
err = res.Next.Execute(c, ctx, contents)
|
||||
if err != nil {
|
||||
chatMessage.New().Error(err.Error()).Done().Write(c.Writer)
|
||||
}
|
||||
// if 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
|
||||
}
|
||||
// done <- true
|
||||
// return 0 // break
|
||||
// }
|
||||
|
||||
if res.Silent {
|
||||
return 1 // continue
|
||||
}
|
||||
}
|
||||
// if res.Silent {
|
||||
// return 1 // continue
|
||||
// }
|
||||
// }
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
// Write the message to the client
|
||||
// Write the message to the stream
|
||||
output := chatMessage.New().Map(map[string]interface{}{
|
||||
"text": delta,
|
||||
"type": msg.Type,
|
||||
|
|
@ -414,6 +428,10 @@ func (ast *Assistant) streamChat(
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package assistant
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -138,7 +139,40 @@ func (ast *Assistant) HookDone(c *gin.Context, context chatctx.Context, input []
|
|||
// Create timeout context
|
||||
ctx := ast.createBackgroundContext()
|
||||
|
||||
v, err := ast.call(ctx, "Done", c, contents, context, input, contents.Data)
|
||||
// format the output
|
||||
// 1. Remove thinking message
|
||||
// 2. Parse the tool call message content
|
||||
output := []message.Data{}
|
||||
if contents != nil && contents.Data != nil {
|
||||
for _, data := range contents.Data {
|
||||
if data.Type == "think" {
|
||||
continue
|
||||
}
|
||||
|
||||
// parse the tool call message content
|
||||
if data.Type == "tool" && data.Props != nil {
|
||||
props := map[string]interface{}{}
|
||||
if text, ok := data.Props["text"].(string); ok {
|
||||
|
||||
// Remove <tool> and </tool> tags
|
||||
text = strings.ReplaceAll(text, "<tool>", "")
|
||||
text = strings.ReplaceAll(text, "</tool>", "")
|
||||
|
||||
// Parse the text into props
|
||||
err := jsoniter.UnmarshalFromString(text, &props)
|
||||
if err != nil {
|
||||
props["error"] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
output = append(output, message.Data{Type: "tool", Props: props})
|
||||
continue
|
||||
}
|
||||
output = append(output, data)
|
||||
}
|
||||
}
|
||||
|
||||
v, err := ast.call(ctx, "Done", c, contents, context, input, output)
|
||||
if err != nil {
|
||||
if err.Error() == HookErrorMethodNotFound {
|
||||
return nil, nil
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue