Implement assistant call functionality in Neo API
- Added a new endpoint for executing assistant calls via POST request, enhancing the API's capabilities. - Introduced the handleAssistantCall method to process incoming requests, validate parameters, and execute the assistant's script. - Updated the Assistant interface to include the Call method, allowing for dynamic method invocation based on the provided payload. - Enhanced error handling for missing parameters and invalid requests, improving the robustness of the assistant's API interactions. These changes significantly improve the Neo API assistant's functionality, enabling more interactive and dynamic assistant capabilities.
This commit is contained in:
parent
979d27b741
commit
1f9810c26c
3 changed files with 76 additions and 0 deletions
49
neo/api.go
49
neo/api.go
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/yaoapp/gou/connector"
|
||||
"github.com/yaoapp/gou/process"
|
||||
"github.com/yaoapp/yao/helper"
|
||||
"github.com/yaoapp/yao/neo/assistant"
|
||||
chatctx "github.com/yaoapp/yao/neo/context"
|
||||
"github.com/yaoapp/yao/neo/message"
|
||||
"github.com/yaoapp/yao/neo/store"
|
||||
|
|
@ -44,7 +45,9 @@ func (neo *DSL) API(router *gin.Engine, path string) error {
|
|||
router.OPTIONS(path+"/dangerous/clear_chats", neo.optionsHandler)
|
||||
router.OPTIONS(path+"/assistants", neo.optionsHandler)
|
||||
router.OPTIONS(path+"/assistants/:id", neo.optionsHandler)
|
||||
router.OPTIONS(path+"/assistants/:id/call", neo.optionsHandler)
|
||||
|
||||
// Chat endpoint
|
||||
// Chat endpoint
|
||||
// Example:
|
||||
// curl -X GET 'http://localhost:5099/api/__yao/neo?content=Hello&chat_id=chat_123&context=previous_context&token=xxx'
|
||||
|
|
@ -71,6 +74,12 @@ func (neo *DSL) API(router *gin.Engine, path string) error {
|
|||
// curl -X GET 'http://localhost:5099/api/__yao/neo/assistants/assistant_123?token=xxx'
|
||||
router.GET(path+"/assistants/:id", append(middlewares, neo.handleAssistantDetail)...)
|
||||
|
||||
// Execute assistant API example:
|
||||
// curl -X POST 'http://localhost:5099/api/__yao/neo/assistants/assistant_123/api' \
|
||||
// -H 'Content-Type: application/json' \
|
||||
// -d '{"name": "Test", "payload": {"name": "yao", "age": 18}}'
|
||||
router.POST(path+"/assistants/:id/call", append(middlewares, neo.handleAssistantCall)...)
|
||||
|
||||
// Create/Update assistant example:
|
||||
// curl -X POST 'http://localhost:5099/api/__yao/neo/assistants' \
|
||||
// -H 'Content-Type: application/json' \
|
||||
|
|
@ -938,6 +947,46 @@ func parseBoolValue(value string) *bool {
|
|||
}
|
||||
}
|
||||
|
||||
// handleAssistantAPI handles the assistant API
|
||||
func (neo *DSL) handleAssistantCall(c *gin.Context) {
|
||||
assistantID := c.Param("id")
|
||||
if assistantID == "" {
|
||||
c.JSON(400, gin.H{"message": "assistant id is required", "code": 400})
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
ast, err := assistant.Get(assistantID)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
|
||||
sid := c.GetString("__sid")
|
||||
if sid == "" {
|
||||
c.JSON(400, gin.H{"message": "sid is required", "code": 400})
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
|
||||
payload := assistant.APIPayload{Sid: sid}
|
||||
if err := c.BindJSON(&payload); err != nil {
|
||||
c.JSON(400, gin.H{"message": "invalid request body", "code": 400})
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
|
||||
result, err := ast.Call(c, payload)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
c.Done()
|
||||
}
|
||||
|
||||
// handleAssistantDetail handles getting a single assistant's details
|
||||
func (neo *DSL) handleAssistantDetail(c *gin.Context) {
|
||||
assistantID := c.Param("id")
|
||||
|
|
|
|||
|
|
@ -170,6 +170,25 @@ func (next *NextAction) Execute(c *gin.Context, ctx chatctx.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Call implements the call functionality
|
||||
func (ast *Assistant) Call(c *gin.Context, payload APIPayload) (interface{}, error) {
|
||||
scriptCtx, err := ast.Script.NewContext(payload.Sid, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer scriptCtx.Close()
|
||||
ctx := c.Request.Context()
|
||||
|
||||
method := fmt.Sprintf("%sAPI", payload.Name)
|
||||
|
||||
// Check if the method exists
|
||||
if !scriptCtx.Global().Has(method) {
|
||||
return nil, fmt.Errorf(HookErrorMethodNotFound)
|
||||
}
|
||||
|
||||
return scriptCtx.CallWith(ctx, method, payload.Payload)
|
||||
}
|
||||
|
||||
// handleChatStream manages the streaming chat interaction with the AI
|
||||
func (ast *Assistant) handleChatStream(c *gin.Context, ctx chatctx.Context, messages []chatMessage.Message, options map[string]interface{}, contents *chatMessage.Contents) error {
|
||||
clientBreak := make(chan bool, 1)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ type API interface {
|
|||
Download(ctx context.Context, fileID string) (*FileResponse, error)
|
||||
ReadBase64(ctx context.Context, fileID string) (string, error)
|
||||
Execute(c *gin.Context, ctx chatctx.Context, input string, options map[string]interface{}) error
|
||||
Call(c *gin.Context, payload APIPayload) (interface{}, error)
|
||||
}
|
||||
|
||||
// APIPayload the API payload
|
||||
type APIPayload struct {
|
||||
Sid string `json:"sid"`
|
||||
Name string `json:"name"`
|
||||
Payload map[string]interface{} `json:"payload"`
|
||||
}
|
||||
|
||||
// ResHookInit the response of the init hook
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue