Refactor Assistant methods and context handling for improved functionality
- Updated the Stream method to return a structured response, including create, done, and completion hooks. - Introduced new methods for managing message history and building LLM requests, enhancing modularity. - Refactored the Script type to utilize a new hook structure, improving code organization. - Removed the obsolete hooks file to streamline the codebase. - Enhanced context types with additional fields for better integration with LLM models.
This commit is contained in:
parent
27d4cd9555
commit
9c97035cc6
15 changed files with 197 additions and 42 deletions
|
|
@ -1,9 +1,14 @@
|
|||
package assistant
|
||||
|
||||
import "github.com/yaoapp/yao/agent/context"
|
||||
import (
|
||||
"github.com/yaoapp/yao/agent/context"
|
||||
"github.com/yaoapp/yao/agent/llm"
|
||||
)
|
||||
|
||||
// Stream stream the agent
|
||||
func (ast *Assistant) Stream(ctx *context.Context, messages []context.Message, handler context.StreamFunc) error {
|
||||
func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Message, handler context.StreamFunc) (*context.Response, error) {
|
||||
|
||||
var err error
|
||||
|
||||
// Initialize stack and auto-handle completion/failure/restore
|
||||
_, traceID, done := context.EnterStack(ctx, ast.ID, ctx.Referer)
|
||||
|
|
@ -11,23 +16,85 @@ func (ast *Assistant) Stream(ctx *context.Context, messages []context.Message, h
|
|||
|
||||
_ = traceID // traceID is available for trace logging
|
||||
|
||||
// Full input messages with chat history
|
||||
fullMessages, err := ast.WithHistory(ctx, inputMessages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Request Create hook ( Optional )
|
||||
var createResponse *context.ResponseHookCreate
|
||||
if ast.Script != nil {
|
||||
var err error
|
||||
createResponse, err = ast.Script.Create(ctx, fullMessages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
_ = createResponse // createResponse is available for further processing
|
||||
|
||||
var completionOptions *llm.CompletionOptions // default is nil
|
||||
|
||||
// LLM Call Stream ( Optional )
|
||||
var completionMessages []context.Message
|
||||
var completionResponse *context.ResponseCompletion
|
||||
if ast.Prompts != nil || ast.MCP != nil {
|
||||
llm, err := llm.New(ast.GetConnector(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build the LLM request
|
||||
completionMessages, completionOptions, err = ast.BuildLLMRequest(ctx, inputMessages, createResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call the LLM Completion Stream
|
||||
completionResponse, err = llm.Stream(ctx, completionMessages, completionOptions, handler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Request MCP hook ( Optional )
|
||||
var mcpResponse *context.ResponseHookMCP
|
||||
if ast.MCP != nil {
|
||||
_ = mcpResponse // mcpResponse is available for further processing
|
||||
|
||||
// MCP Execution Loop
|
||||
}
|
||||
|
||||
// Request Done hook ( Optional )
|
||||
var doneResponse *context.ResponseHookDone
|
||||
if ast.Script != nil {
|
||||
var err error
|
||||
doneResponse, err = ast.Script.Done(ctx, fullMessages, completionResponse, mcpResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
_ = doneResponse // doneResponse is available for further processing
|
||||
|
||||
return &context.Response{Create: createResponse, Done: doneResponse, Completion: completionResponse}, nil
|
||||
}
|
||||
|
||||
// Run run the agent
|
||||
func (ast *Assistant) Run(ctx *context.Context, messages []context.Message) (*context.Response, error) {
|
||||
|
||||
// Initialize stack and auto-handle completion/failure/restore
|
||||
_, traceID, done := context.EnterStack(ctx, ast.ID, ctx.Referer)
|
||||
defer done()
|
||||
|
||||
_ = traceID // traceID is available for trace logging
|
||||
|
||||
return &context.Response{}, nil
|
||||
// GetConnector get the connector from the context
|
||||
func (ast *Assistant) GetConnector(ctx *context.Context) string {
|
||||
if ctx.Connector != "" {
|
||||
return ctx.Connector
|
||||
}
|
||||
return ast.Connector
|
||||
}
|
||||
|
||||
// BuildLLMRequest build the LLM request
|
||||
func (ast *Assistant) BuildLLMRequest(ctx *context.Context, messages []context.Message, createResponse *context.ResponseHookCreate) ([]context.Message, *llm.CompletionOptions, error) {
|
||||
return messages, nil, nil
|
||||
}
|
||||
|
||||
// WithHistory with the history messages
|
||||
func (ast *Assistant) WithHistory(ctx *context.Context, messages []context.Message) ([]context.Message, error) {
|
||||
return messages, nil
|
||||
}
|
||||
|
|
|
|||
8
agent/assistant/hook/create.go
Normal file
8
agent/assistant/hook/create.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package hook
|
||||
|
||||
import "github.com/yaoapp/yao/agent/context"
|
||||
|
||||
// Create create a new assistant
|
||||
func (s *Script) Create(ctx *context.Context, messages []context.Message) (*context.ResponseHookCreate, error) {
|
||||
return &context.ResponseHookCreate{}, nil
|
||||
}
|
||||
10
agent/assistant/hook/done.go
Normal file
10
agent/assistant/hook/done.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package hook
|
||||
|
||||
import (
|
||||
"github.com/yaoapp/yao/agent/context"
|
||||
)
|
||||
|
||||
// Done done hook
|
||||
func (s *Script) Done(ctx *context.Context, inputMessages []context.Message, completionResponse *context.ResponseCompletion, mcpResponse *context.ResponseHookMCP) (*context.ResponseHookDone, error) {
|
||||
return &context.ResponseHookDone{}, nil
|
||||
}
|
||||
8
agent/assistant/hook/failback.go
Normal file
8
agent/assistant/hook/failback.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package hook
|
||||
|
||||
import "github.com/yaoapp/yao/agent/context"
|
||||
|
||||
// Failback failback hook
|
||||
func (s *Script) Failback(ctx *context.Context, inputMessages []context.Message, completionResponse *context.ResponseCompletion) (*context.ResponseHookFailback, error) {
|
||||
return &context.ResponseHookFailback{}, nil
|
||||
}
|
||||
1
agent/assistant/hook/hook.go
Normal file
1
agent/assistant/hook/hook.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package hook
|
||||
8
agent/assistant/hook/mcp.go
Normal file
8
agent/assistant/hook/mcp.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package hook
|
||||
|
||||
import "github.com/yaoapp/yao/agent/context"
|
||||
|
||||
// MCP MCP hook
|
||||
func (s *Script) MCP(ctx *context.Context, messages []context.Message) (*context.ResponseHookMCP, error) {
|
||||
return &context.ResponseHookMCP{}, nil
|
||||
}
|
||||
1
agent/assistant/hook/script.go
Normal file
1
agent/assistant/hook/script.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package hook
|
||||
10
agent/assistant/hook/types.go
Normal file
10
agent/assistant/hook/types.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package hook
|
||||
|
||||
import (
|
||||
v8 "github.com/yaoapp/gou/runtime/v8"
|
||||
)
|
||||
|
||||
// Script the script hook align
|
||||
type Script struct {
|
||||
*v8.Script
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
package hooks
|
||||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/yaoapp/gou/application"
|
||||
"github.com/yaoapp/gou/fs"
|
||||
v8 "github.com/yaoapp/gou/runtime/v8"
|
||||
"github.com/yaoapp/yao/agent/assistant/hook"
|
||||
"github.com/yaoapp/yao/agent/i18n"
|
||||
store "github.com/yaoapp/yao/agent/store/types"
|
||||
agentvision "github.com/yaoapp/yao/agent/vision"
|
||||
|
|
@ -106,9 +107,7 @@ func LoadBuiltIn() error {
|
|||
loaded.Put(assistant)
|
||||
|
||||
// Remove the built-in assistant from the store
|
||||
if _, ok := deletedBuiltIn[assistant.ID]; ok {
|
||||
delete(deletedBuiltIn, assistant.ID)
|
||||
}
|
||||
delete(deletedBuiltIn, assistant.ID)
|
||||
}
|
||||
|
||||
// Remove deleted built-in assistants
|
||||
|
|
@ -290,16 +289,16 @@ func LoadPath(path string) (*Assistant, error) {
|
|||
data["updated_at"] = max(updatedAt, ts)
|
||||
}
|
||||
|
||||
// load tools
|
||||
toolsfile := filepath.Join(path, "tools.yao")
|
||||
if has, _ := app.Exists(toolsfile); has {
|
||||
tools, ts, err := loadTools(toolsfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data["tools"] = tools
|
||||
updatedAt = max(updatedAt, ts)
|
||||
}
|
||||
// load tools, deprecated, use mcp instead
|
||||
// toolsfile := filepath.Join(path, "tools.yao")
|
||||
// if has, _ := app.Exists(toolsfile); has {
|
||||
// tools, ts, err := loadTools(toolsfile)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// data["tools"] = tools
|
||||
// updatedAt = max(updatedAt, ts)
|
||||
// }
|
||||
|
||||
// i18ns
|
||||
locales, err := i18n.GetLocales(path)
|
||||
|
|
@ -430,6 +429,9 @@ func loadMap(data map[string]interface{}) (*Assistant, error) {
|
|||
}
|
||||
assistant.Tags = tags
|
||||
|
||||
case string:
|
||||
assistant.Tags = []string{vv}
|
||||
|
||||
case interface{}:
|
||||
raw, err := jsoniter.Marshal(vv)
|
||||
if err != nil {
|
||||
|
|
@ -442,8 +444,6 @@ func loadMap(data map[string]interface{}) (*Assistant, error) {
|
|||
}
|
||||
assistant.Tags = tags
|
||||
|
||||
case string:
|
||||
assistant.Tags = []string{vv}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -571,9 +571,11 @@ func loadMap(data map[string]interface{}) (*Assistant, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assistant.Script = script
|
||||
case *v8.Script:
|
||||
assistant.Script = &hook.Script{Script: script}
|
||||
case *hook.Script:
|
||||
assistant.Script = v
|
||||
case *v8.Script:
|
||||
assistant.Script = &hook.Script{Script: v}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -641,7 +643,7 @@ func loadPrompts(file string, root string) (string, int64, error) {
|
|||
return string(prompts), ts.UnixNano(), nil
|
||||
}
|
||||
|
||||
func loadScript(file string, root string) (*v8.Script, int64, error) {
|
||||
func loadScript(file string, root string) (*hook.Script, int64, error) {
|
||||
|
||||
app, err := fs.Get("app")
|
||||
if err != nil {
|
||||
|
|
@ -658,7 +660,7 @@ func loadScript(file string, root string) (*v8.Script, int64, error) {
|
|||
return nil, 0, err
|
||||
}
|
||||
|
||||
return script, ts.UnixNano(), nil
|
||||
return &hook.Script{Script: script}, ts.UnixNano(), nil
|
||||
}
|
||||
|
||||
func loadScriptSource(source string, file string) (*v8.Script, error) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"io"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
v8 "github.com/yaoapp/gou/runtime/v8"
|
||||
"github.com/yaoapp/yao/agent/assistant/hook"
|
||||
chatctx "github.com/yaoapp/yao/agent/context"
|
||||
"github.com/yaoapp/yao/agent/message"
|
||||
store "github.com/yaoapp/yao/agent/store/types"
|
||||
|
|
@ -96,16 +96,16 @@ type QueryParam struct {
|
|||
type Assistant struct {
|
||||
store.AssistantModel
|
||||
Search *SearchOption `json:"search,omitempty" yaml:"search,omitempty"` // Whether this assistant supports search
|
||||
Script *v8.Script `json:"-" yaml:"-"` // Assistant Script
|
||||
Script *hook.Script `json:"-" yaml:"-"` // Assistant Script
|
||||
|
||||
// Internal
|
||||
// ===============================
|
||||
openai *api.OpenAI // OpenAI API
|
||||
search bool // Whether this assistant supports search
|
||||
vision bool // Whether this assistant supports vision
|
||||
toolCalls bool // Whether this assistant supports tool_calls
|
||||
initHook bool // Whether this assistant has an init hook
|
||||
runtimeTools []Tool // Converted tools for business logic (OpenAI format)
|
||||
openai *api.OpenAI // OpenAI API
|
||||
search bool // Whether this assistant supports search
|
||||
vision bool // Whether this assistant supports vision
|
||||
// toolCalls bool // Whether this assistant supports tool_calls
|
||||
initHook bool // Whether this assistant has an init hook
|
||||
runtimeTools []Tool // Converted tools for business logic (OpenAI format)
|
||||
}
|
||||
|
||||
// ConnectorSetting the connector setting
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ type Context struct {
|
|||
ChatID string `json:"chat_id,omitempty"` // Chat ID, use to select chat
|
||||
AssistantID string `json:"assistant_id,omitempty"` // Assistant ID, use to select assistant
|
||||
Sid string `json:"sid" yaml:"-"` // Session ID (Deprecated, use Authorized instead)
|
||||
Connector string `json:"connector,omitempty"` // Connector, use to select the connector of the LLM Model, Default is Assistant.Connector
|
||||
Search *bool `json:"search,omitempty"` // Search mode, default is true
|
||||
|
||||
// Arguments for call
|
||||
Args []interface{} `json:"args,omitempty"` // Arguments for call, it will be used to pass data to the call
|
||||
|
|
@ -181,7 +183,28 @@ type Stack struct {
|
|||
|
||||
// Response the response
|
||||
// 100% compatible with the OpenAI API
|
||||
type Response struct{}
|
||||
type Response struct {
|
||||
Create *ResponseHookCreate `json:"create,omitempty"`
|
||||
MCP *ResponseHookMCP `json:"mcp,omitempty"`
|
||||
Done *ResponseHookDone `json:"done,omitempty"`
|
||||
Failback *ResponseHookFailback `json:"failback,omitempty"`
|
||||
Completion *ResponseCompletion `json:"completion,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseHookCreate the response of the create hook
|
||||
type ResponseHookCreate struct{}
|
||||
|
||||
// ResponseHookDone the response of the done hook
|
||||
type ResponseHookDone struct{}
|
||||
|
||||
// ResponseHookMCP the response of the mcp hook
|
||||
type ResponseHookMCP struct{}
|
||||
|
||||
// ResponseHookFailback the response of the failback hook
|
||||
type ResponseHookFailback struct{}
|
||||
|
||||
// ResponseCompletion the response of the completion
|
||||
type ResponseCompletion struct{}
|
||||
|
||||
// Message Structure ( OpenAI Chat Completion Input Message Structure, https://platform.openai.com/docs/api-reference/chat/create#chat/create-messages )
|
||||
// ===============================
|
||||
|
|
|
|||
9
agent/llm/interfaces.go
Normal file
9
agent/llm/interfaces.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package llm
|
||||
|
||||
import "github.com/yaoapp/yao/agent/context"
|
||||
|
||||
// LLM the LLM interface
|
||||
type LLM interface {
|
||||
Stream(ctx *context.Context, messages []context.Message, options *CompletionOptions, handler context.StreamFunc) (*context.ResponseCompletion, error)
|
||||
Post(ctx *context.Context, messages []context.Message, options *CompletionOptions) (*context.ResponseCompletion, error)
|
||||
}
|
||||
|
|
@ -1 +1,6 @@
|
|||
package llm
|
||||
|
||||
// New create a new LLM instance
|
||||
func New(connector string) (LLM, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
4
agent/llm/types.go
Normal file
4
agent/llm/types.go
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
package llm
|
||||
|
||||
// CompletionOptions the completion request
|
||||
type CompletionOptions struct{}
|
||||
Loading…
Add table
Reference in a new issue