This commit is contained in:
Ettore Di Giacinto
2024-04-08 00:35:14 +02:00
parent dbfc596333
commit 7adcce78be
8 changed files with 262 additions and 172 deletions

View File

@@ -4,8 +4,11 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
. "github.com/mudler/local-agent-framework/agent"
"github.com/mudler/local-agent-framework/external"
)
type ConnectorConfig struct {
@@ -16,13 +19,11 @@ type ConnectorConfig struct {
type ActionsConfig string
type AgentConfig struct {
Connector []ConnectorConfig `json:"connector"`
Actions []ActionsConfig `json:"actions"`
StateFile string `json:"state_file"`
CharacterFile string `json:"character_file"`
Connector []ConnectorConfig `json:"connector"`
Actions []ActionsConfig `json:"actions"`
// This is what needs to be part of ActionsConfig
APIURL string `json:"api_url"`
Model string `json:"model"`
Name string `json:"name"`
HUD bool `json:"hud"`
Debug bool `json:"debug"`
StandaloneJob bool `json:"standalone_job"`
@@ -32,35 +33,47 @@ type AgentConfig struct {
}
type AgentPool struct {
file string
pool AgentPoolData
agents map[string]*Agent
managers map[string]Manager
file string
pooldir string
pool AgentPoolData
agents map[string]*Agent
managers map[string]Manager
apiURL, model string
}
type AgentPoolData map[string]AgentConfig
func NewAgentPool(file string) (*AgentPool, error) {
func NewAgentPool(model, apiURL, directory string) (*AgentPool, error) {
// if file exists, try to load an existing pool.
// if file does not exist, create a new pool.
if _, err := os.Stat(file); err != nil {
poolfile := filepath.Join(directory, "pool.json")
if _, err := os.Stat(poolfile); err != nil {
// file does not exist, create a new pool
return &AgentPool{
file: file,
agents: make(map[string]*Agent),
pool: make(map[string]AgentConfig),
file: poolfile,
pooldir: directory,
apiURL: apiURL,
model: model,
agents: make(map[string]*Agent),
pool: make(map[string]AgentConfig),
managers: make(map[string]Manager),
}, nil
}
poolData, err := loadPoolFromFile(file)
poolData, err := loadPoolFromFile(poolfile)
if err != nil {
return nil, err
}
return &AgentPool{
file: file,
agents: make(map[string]*Agent),
pool: *poolData,
file: poolfile,
apiURL: apiURL,
pooldir: directory,
model: model,
agents: make(map[string]*Agent),
managers: make(map[string]Manager),
pool: *poolData,
}, nil
}
@@ -91,16 +104,48 @@ func (a *AgentPool) List() []string {
return agents
}
func (a *AgentConfig) availableActions() []Action {
actions := []Action{}
if len(a.Actions) == 0 {
// Return search as default
return []Action{external.NewSearch(3)}
}
for _, action := range a.Actions {
switch action {
case "search":
actions = append(actions, external.NewSearch(3))
}
}
return actions
}
func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error {
manager := NewManager(5)
model := a.model
if config.Model != "" {
model = config.Model
}
if config.PeriodicRuns == "" {
config.PeriodicRuns = "10m"
}
fmt.Println("Creating agent", name)
fmt.Println("Model", model)
fmt.Println("API URL", a.apiURL)
actions := config.availableActions()
opts := []Option{
WithModel(config.Model),
WithLLMAPIURL(config.APIURL),
WithModel(model),
WithLLMAPIURL(a.apiURL),
WithPeriodicRuns(config.PeriodicRuns),
WithStateFile(config.StateFile),
WithCharacterFile(config.StateFile),
WithActions(
actions...,
),
WithStateFile(filepath.Join(a.pooldir, fmt.Sprintf("%s.state.json", name))),
WithCharacterFile(filepath.Join(a.pooldir, fmt.Sprintf("%s.character.json", name))),
WithAgentReasoningCallback(func(state ActionCurrentState) bool {
sseManager.Send(
fmt.Println("Reasoning", state.Reasoning)
manager.Send(
NewMessage(
fmt.Sprintf(`Thinking: %s`, htmlIfy(state.Reasoning)),
).WithEvent("status"),
@@ -108,6 +153,8 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
return true
}),
WithAgentResultCallback(func(state ActionState) {
fmt.Println("Reasoning", state.Reasoning)
text := fmt.Sprintf(`Reasoning: %s
Action taken: %+v
Parameters: %+v
@@ -116,7 +163,7 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
state.ActionCurrentState.Action.Definition().Name,
state.ActionCurrentState.Params,
state.Result)
sseManager.Send(
manager.Send(
NewMessage(
htmlIfy(
text,
@@ -141,6 +188,9 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
opts = append(opts, WithRandomIdentity())
}
}
fmt.Println("Starting agent", name)
fmt.Printf("Config %+v\n", config)
agent, err := New(opts...)
if err != nil {
return err
@@ -155,6 +205,15 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
}
}()
go func() {
for {
time.Sleep(1 * time.Second) // Send a message every seconds
manager.Send(NewMessage(
htmlIfy(agent.State().String()),
).WithEvent("hud"))
}
}()
return nil
}