From cb35f871db295ee8f2b80aed8fa7ce281b64cc36 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Thu, 11 Apr 2024 00:20:49 +0200 Subject: [PATCH] Split main --- example/webui/app.go | 155 +++++++++++++++++++++++++++ example/webui/elements.go | 11 +- example/webui/main.go | 217 +------------------------------------- example/webui/routes.go | 76 +++++++++++++ 4 files changed, 242 insertions(+), 217 deletions(-) create mode 100644 example/webui/app.go create mode 100644 example/webui/routes.go diff --git a/example/webui/app.go b/example/webui/app.go new file mode 100644 index 0000000..7ee03ec --- /dev/null +++ b/example/webui/app.go @@ -0,0 +1,155 @@ +package main + +import ( + "fmt" + "net/http" + + . "github.com/mudler/local-agent-framework/agent" + + "github.com/donseba/go-htmx" + fiber "github.com/gofiber/fiber/v2" +) + +type ( + App struct { + htmx *htmx.HTMX + pool *AgentPool + } +) + +func (a *App) KnowledgeBase(db *InMemoryDatabase) func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) error { + payload := struct { + URL string `form:"url"` + ChunkSize int `form:"chunk_size"` + }{} + + if err := c.BodyParser(&payload); err != nil { + return err + } + + website := payload.URL + if website == "" { + return fmt.Errorf("please enter a URL") + } + chunkSize := defaultChunkSize + if payload.ChunkSize > 0 { + chunkSize = payload.ChunkSize + } + + go WebsiteToKB(website, chunkSize, db) + + return c.Redirect("/knowledgebase") + } +} + +func (a *App) Notify(pool *AgentPool) func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) error { + payload := struct { + Message string `form:"message"` + }{} + + if err := c.BodyParser(&payload); err != nil { + return err + } + + query := payload.Message + if query == "" { + _, _ = c.Write([]byte("Please enter a message.")) + return nil + } + + agent := pool.GetAgent(c.Params("name")) + agent.Ask( + WithText(query), + ) + _, _ = c.Write([]byte("Message sent")) + + return nil + } +} + +func (a *App) Delete(pool *AgentPool) func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) error { + if err := pool.Remove(c.Params("name")); err != nil { + fmt.Println("Error removing agent", err) + return c.Status(http.StatusInternalServerError).SendString(err.Error()) + } + return c.Redirect("/agents") + } +} + +func (a *App) Create(pool *AgentPool) func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) error { + config := AgentConfig{} + if err := c.BodyParser(&config); err != nil { + return err + } + + fmt.Printf("Agent configuration: %+v\n", config) + + if config.Name == "" { + c.Status(http.StatusBadRequest).SendString("Name is required") + return nil + } + if err := pool.CreateAgent(config.Name, &config); err != nil { + c.Status(http.StatusInternalServerError).SendString(err.Error()) + return nil + } + return c.Redirect("/agents") + } +} + +func (a *App) Chat(pool *AgentPool) func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) error { + payload := struct { + Message string `json:"message"` + }{} + + if err := c.BodyParser(&payload); err != nil { + return err + } + agentName := c.Params("name") + manager := pool.GetManager(agentName) + + query := payload.Message + if query == "" { + _, _ = c.Write([]byte("Please enter a message.")) + return nil + } + manager.Send( + NewMessage( + chatDiv(query, "gray"), + ).WithEvent("messages")) + + go func() { + agent := pool.GetAgent(agentName) + if agent == nil { + fmt.Println("Agent not found in pool", c.Params("name")) + return + } + res := agent.Ask( + WithText(query), + ) + fmt.Println("response is", res.Response) + manager.Send( + NewMessage( + chatDiv(res.Response, "blue"), + ).WithEvent("messages")) + manager.Send( + NewMessage( + disabledElement("inputMessage", false), // show again the input + ).WithEvent("message_status")) + + //result := `done` + // _, _ = w.Write([]byte(result)) + }() + + manager.Send( + NewMessage( + loader() + disabledElement("inputMessage", true), + ).WithEvent("message_status")) + + return nil + } +} diff --git a/example/webui/elements.go b/example/webui/elements.go index a0cfbd6..7bc363f 100644 --- a/example/webui/elements.go +++ b/example/webui/elements.go @@ -1,6 +1,9 @@ package main -import "fmt" +import ( + "fmt" + "strings" +) // TODO: switch to https://github.com/chasefleming/elem-go @@ -19,3 +22,9 @@ func disabledElement(id string, disabled bool) string { return `` } + +func htmlIfy(s string) string { + s = strings.TrimSpace(s) + s = strings.ReplaceAll(s, "\n", "
") + return s +} diff --git a/example/webui/main.go b/example/webui/main.go index efdf2aa..3848735 100644 --- a/example/webui/main.go +++ b/example/webui/main.go @@ -4,10 +4,8 @@ import ( "embed" "fmt" "log" - "math/rand" "net/http" "os" - "strings" "github.com/donseba/go-htmx" fiber "github.com/gofiber/fiber/v2" @@ -18,13 +16,6 @@ import ( "github.com/mudler/local-agent-framework/llm/rag" ) -type ( - App struct { - htmx *htmx.HTMX - pool *AgentPool - } -) - var testModel = os.Getenv("TEST_MODEL") var apiURL = os.Getenv("API_URL") var apiKey = os.Getenv("API_KEY") @@ -42,12 +33,6 @@ func init() { } } -func htmlIfy(s string) string { - s = strings.TrimSpace(s) - s = strings.ReplaceAll(s, "\n", "
") - return s -} - //go:embed views/* var viewsfs embed.FS @@ -108,207 +93,7 @@ func main() { Views: engine, }) - // Serve static files - webapp.Static("/", "./public") - - webapp.Get("/", func(c *fiber.Ctx) error { - return c.Render("views/index", fiber.Map{ - "Agents": pool.List(), - }) - }) - - webapp.Get("/agents", func(c *fiber.Ctx) error { - return c.Render("views/agents", fiber.Map{ - "Agents": pool.List(), - }) - }) - - webapp.Get("/create", func(c *fiber.Ctx) error { - return c.Render("views/create", fiber.Map{ - "Title": "Hello, World!", - "Actions": AvailableActions, - "Connectors": AvailableConnectors, - }) - }) - - webapp.Get("/knowledgebase", func(c *fiber.Ctx) error { - return c.Render("views/knowledgebase", fiber.Map{ - "Title": "Hello, World!", - "KnowledgebaseItemsCount": len(db.Database), - }) - }) - - // Define a route for the GET method on the root path '/' - webapp.Get("/sse/:name", func(c *fiber.Ctx) error { - - m := pool.GetManager(c.Params("name")) - if m == nil { - return c.SendStatus(404) - } - - m.Handle(c, NewClient(randStringRunes(10))) - return nil - }) - - webapp.Get("/notify/:name", app.Notify(pool)) - webapp.Post("/chat/:name", app.Chat(pool)) - webapp.Post("/create", app.Create(pool)) - webapp.Get("/delete/:name", app.Delete(pool)) - webapp.Post("/knowledgebase", app.KnowledgeBase(db)) - - webapp.Get("/talk/:name", func(c *fiber.Ctx) error { - return c.Render("chat.html", fiber.Map{ - // "Character": agent.Character, - "Name": c.Params("name"), - }) - }) + RegisterRoutes(webapp, pool, db, app) log.Fatal(webapp.Listen(":3000")) } - -func (a *App) KnowledgeBase(db *InMemoryDatabase) func(c *fiber.Ctx) error { - return func(c *fiber.Ctx) error { - payload := struct { - URL string `form:"url"` - ChunkSize int `form:"chunk_size"` - }{} - - if err := c.BodyParser(&payload); err != nil { - return err - } - - website := payload.URL - if website == "" { - return fmt.Errorf("please enter a URL") - } - chunkSize := defaultChunkSize - if payload.ChunkSize > 0 { - chunkSize = payload.ChunkSize - } - - go WebsiteToKB(website, chunkSize, db) - - return c.Redirect("/knowledgebase") - } -} - -func (a *App) Notify(pool *AgentPool) func(c *fiber.Ctx) error { - return func(c *fiber.Ctx) error { - payload := struct { - Message string `form:"message"` - }{} - - if err := c.BodyParser(&payload); err != nil { - return err - } - - query := payload.Message - if query == "" { - _, _ = c.Write([]byte("Please enter a message.")) - return nil - } - - agent := pool.GetAgent(c.Params("name")) - agent.Ask( - WithText(query), - ) - _, _ = c.Write([]byte("Message sent")) - - return nil - } -} - -func (a *App) Delete(pool *AgentPool) func(c *fiber.Ctx) error { - return func(c *fiber.Ctx) error { - if err := pool.Remove(c.Params("name")); err != nil { - fmt.Println("Error removing agent", err) - return c.Status(http.StatusInternalServerError).SendString(err.Error()) - } - return c.Redirect("/agents") - } -} - -func (a *App) Create(pool *AgentPool) func(c *fiber.Ctx) error { - return func(c *fiber.Ctx) error { - config := AgentConfig{} - if err := c.BodyParser(&config); err != nil { - return err - } - - fmt.Printf("Agent configuration: %+v\n", config) - - if config.Name == "" { - c.Status(http.StatusBadRequest).SendString("Name is required") - return nil - } - if err := pool.CreateAgent(config.Name, &config); err != nil { - c.Status(http.StatusInternalServerError).SendString(err.Error()) - return nil - } - return c.Redirect("/agents") - } -} - -func (a *App) Chat(pool *AgentPool) func(c *fiber.Ctx) error { - return func(c *fiber.Ctx) error { - payload := struct { - Message string `json:"message"` - }{} - - if err := c.BodyParser(&payload); err != nil { - return err - } - agentName := c.Params("name") - manager := pool.GetManager(agentName) - - query := payload.Message - if query == "" { - _, _ = c.Write([]byte("Please enter a message.")) - return nil - } - manager.Send( - NewMessage( - chatDiv(query, "gray"), - ).WithEvent("messages")) - - go func() { - agent := pool.GetAgent(agentName) - if agent == nil { - fmt.Println("Agent not found in pool", c.Params("name")) - return - } - res := agent.Ask( - WithText(query), - ) - fmt.Println("response is", res.Response) - manager.Send( - NewMessage( - chatDiv(res.Response, "blue"), - ).WithEvent("messages")) - manager.Send( - NewMessage( - disabledElement("inputMessage", false), // show again the input - ).WithEvent("message_status")) - - //result := `done` - // _, _ = w.Write([]byte(result)) - }() - - manager.Send( - NewMessage( - loader() + disabledElement("inputMessage", true), - ).WithEvent("message_status")) - - return nil - } -} - -var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -func randStringRunes(n int) string { - b := make([]rune, n) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] - } - return string(b) -} diff --git a/example/webui/routes.go b/example/webui/routes.go new file mode 100644 index 0000000..0dda837 --- /dev/null +++ b/example/webui/routes.go @@ -0,0 +1,76 @@ +package main + +import ( + "math/rand" + + fiber "github.com/gofiber/fiber/v2" +) + +func RegisterRoutes(webapp *fiber.App, pool *AgentPool, db *InMemoryDatabase, app *App) { + + // Serve static files + webapp.Static("/", "./public") + + webapp.Get("/", func(c *fiber.Ctx) error { + return c.Render("views/index", fiber.Map{ + "Agents": pool.List(), + }) + }) + + webapp.Get("/agents", func(c *fiber.Ctx) error { + return c.Render("views/agents", fiber.Map{ + "Agents": pool.List(), + }) + }) + + webapp.Get("/create", func(c *fiber.Ctx) error { + return c.Render("views/create", fiber.Map{ + "Title": "Hello, World!", + "Actions": AvailableActions, + "Connectors": AvailableConnectors, + }) + }) + + webapp.Get("/knowledgebase", func(c *fiber.Ctx) error { + return c.Render("views/knowledgebase", fiber.Map{ + "Title": "Hello, World!", + "KnowledgebaseItemsCount": len(db.Database), + }) + }) + + // Define a route for the GET method on the root path '/' + webapp.Get("/sse/:name", func(c *fiber.Ctx) error { + + m := pool.GetManager(c.Params("name")) + if m == nil { + return c.SendStatus(404) + } + + m.Handle(c, NewClient(randStringRunes(10))) + return nil + }) + + webapp.Get("/notify/:name", app.Notify(pool)) + webapp.Post("/chat/:name", app.Chat(pool)) + webapp.Post("/create", app.Create(pool)) + webapp.Get("/delete/:name", app.Delete(pool)) + webapp.Post("/knowledgebase", app.KnowledgeBase(db)) + + webapp.Get("/talk/:name", func(c *fiber.Ctx) error { + return c.Render("chat.html", fiber.Map{ + // "Character": agent.Character, + "Name": c.Params("name"), + }) + }) + +} + +var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func randStringRunes(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +}