Enhance Neo API assistant with new action execution capabilities

- Introduced a new Execute method for handling next actions in the Assistant struct, allowing for dynamic execution of various actions such as "process" and "assistant".
- Improved error handling by validating payloads and providing meaningful error messages for missing or incorrect data.
- Streamlined the flow of next actions in the Execute method, enhancing the assistant's ability to manage complex interactions and responses.
- Updated the streamChat method to utilize the new Execute method, improving the handling of next actions during chat streaming.

These changes enhance the robustness and maintainability of the Neo API, paving the way for more flexible and powerful assistant functionalities.
This commit is contained in:
Max 2025-01-14 16:13:14 +08:00
parent 627328b279
commit 860bfd1d0d

View file

@ -8,6 +8,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/yaoapp/gou/fs" "github.com/yaoapp/gou/fs"
"github.com/yaoapp/gou/process"
chatctx "github.com/yaoapp/yao/neo/context" chatctx "github.com/yaoapp/yao/neo/context"
"github.com/yaoapp/yao/neo/message" "github.com/yaoapp/yao/neo/message"
chatMessage "github.com/yaoapp/yao/neo/message" chatMessage "github.com/yaoapp/yao/neo/message"
@ -69,11 +70,7 @@ func (ast *Assistant) Execute(c *gin.Context, ctx chatctx.Context, input string,
// Handle next action // Handle next action
if res.Next != nil { if res.Next != nil {
switch res.Next.Action { return res.Next.Execute(c, ctx)
case "exit":
return nil
// Add other actions here if needed
}
} }
// Update options if provided // Update options if provided
@ -90,6 +87,78 @@ func (ast *Assistant) Execute(c *gin.Context, ctx chatctx.Context, input string,
return ast.handleChatStream(c, ctx, messages, options) return ast.handleChatStream(c, ctx, messages, options)
} }
// Execute the next action
func (next *NextAction) Execute(c *gin.Context, ctx chatctx.Context) error {
switch next.Action {
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")
}
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())
}
err = p.Execute()
if err != nil {
return fmt.Errorf("execute process error: %s", err.Error())
}
defer p.Release()
return nil
case "assistant":
if next.Payload == nil {
return fmt.Errorf("payload is required")
}
// Get assistant id
id, ok := next.Payload["assistant_id"].(string)
if !ok {
return fmt.Errorf("assistant id should be string")
}
// Get assistant
assistant, err := Get(id)
if err != nil {
return fmt.Errorf("get assistant error: %s", err.Error())
}
// Input
input, ok := next.Payload["input"].(string)
if !ok {
return fmt.Errorf("input should be string")
}
// Options
options := map[string]interface{}{}
if v, ok := next.Payload["options"].(map[string]interface{}); ok {
options = v
}
return assistant.Execute(c, ctx, input, options)
case "exit":
return nil
default:
return fmt.Errorf("unknown action: %s", next.Action)
}
}
// handleChatStream manages the streaming chat interaction with the AI // handleChatStream manages the streaming chat interaction with the AI
func (ast *Assistant) handleChatStream(c *gin.Context, ctx chatctx.Context, messages []message.Message, options map[string]interface{}) error { func (ast *Assistant) handleChatStream(c *gin.Context, ctx chatctx.Context, messages []message.Message, options map[string]interface{}) error {
clientBreak := make(chan bool, 1) clientBreak := make(chan bool, 1)
@ -156,10 +225,17 @@ func (ast *Assistant) streamChat(c *gin.Context, ctx chatctx.Context, messages [
if res.Output != "" { if res.Output != "" {
value = res.Output value = res.Output
} }
if res.Next != nil && res.Next.Action == "exit" {
if res.Next != nil {
err = res.Next.Execute(c, ctx)
if err != nil {
chatMessage.New().Error(err.Error()).Done().Write(c.Writer)
}
done <- true done <- true
return 0 // break return 0 // break
} }
if res.Silent { if res.Silent {
return 1 // continue return 1 // continue
} }
@ -190,10 +266,16 @@ func (ast *Assistant) streamChat(c *gin.Context, ctx chatctx.Context, messages [
}). }).
Write(c.Writer) Write(c.Writer)
} }
if res.Next != nil && res.Next.Action == "exit" {
if res.Next != nil {
err := res.Next.Execute(c, ctx)
if err != nil {
chatMessage.New().Error(err.Error()).Done().Write(c.Writer)
}
done <- true done <- true
return 0 // break return 0 // break
} }
} else if value != "" { } else if value != "" {
chatMessage.New(). chatMessage.New().
Map(map[string]interface{}{ Map(map[string]interface{}{