diff --git a/core/gallery/gallery.go b/core/gallery/gallery.go index 3a60e618a327..a3a1d9090cf7 100644 --- a/core/gallery/gallery.go +++ b/core/gallery/gallery.go @@ -114,7 +114,7 @@ func FindModel(models []*GalleryModel, name string, basePath string) *GalleryMod // List available models // Models galleries are a list of yaml files that are hosted on a remote server (for example github). // Each yaml file contains a list of models that can be downloaded and optionally overrides to define a new model setting. -func AvailableGalleryModels(galleries []config.Gallery, basePath string) ([]*GalleryModel, error) { +func AvailableGalleryModels(galleries []config.Gallery, basePath string) (GalleryModels, error) { var models []*GalleryModel // Get models from galleries diff --git a/core/gallery/request.go b/core/gallery/request.go index 72d078a18bf0..5e7308fd8fe8 100644 --- a/core/gallery/request.go +++ b/core/gallery/request.go @@ -62,3 +62,15 @@ func (gm GalleryModels) FindByName(name string) *GalleryModel { } return nil } + +func (gm GalleryModels) Paginate(pageNum int, itemsNum int) GalleryModels { + start := (pageNum - 1) * itemsNum + end := start + itemsNum + if start > len(gm) { + start = len(gm) + } + if end > len(gm) { + end = len(gm) + } + return gm[start:end] +} diff --git a/core/http/routes/ui.go b/core/http/routes/ui.go index 350d0914f2ac..7fb6adfcc567 100644 --- a/core/http/routes/ui.go +++ b/core/http/routes/ui.go @@ -3,7 +3,9 @@ package routes import ( "fmt" "html/template" + "math" "sort" + "strconv" "strings" "github.com/mudler/LocalAI/core/config" @@ -126,6 +128,8 @@ func RegisterUIRoutes(app *fiber.App, // Show the Models page (all models) app.Get("/browse", func(c *fiber.Ctx) error { term := c.Query("term") + page := c.Query("page") + items := c.Query("items") models, _ := gallery.AvailableGalleryModels(appConfig.Galleries, appConfig.ModelPath) @@ -164,6 +168,54 @@ func RegisterUIRoutes(app *fiber.App, // "ApplicationConfig": appConfig, } + if page == "" { + page = "1" + } + + if page != "" { + log.Debug().Msgf("page : %+v\n", page) + // return a subset of the models + pageNum, err := strconv.Atoi(page) + if err != nil { + return c.Status(fiber.StatusBadRequest).SendString("Invalid page number") + } + + if pageNum == 0 { + return c.Render("views/models", summary) + } + + itemsNum, err := strconv.Atoi(items) + if err != nil { + itemsNum = 21 + } + + totalPages := int(math.Ceil(float64(len(models)) / float64(itemsNum))) + + models = models.Paginate(pageNum, itemsNum) + + log.Debug().Msgf("number of models : %+v\n", len(models)) + prevPage := pageNum - 1 + nextPage := pageNum + 1 + if prevPage < 1 { + prevPage = 1 + } + if nextPage > totalPages { + nextPage = totalPages + } + if prevPage != pageNum { + summary["PrevPage"] = prevPage + } + summary["NextPage"] = nextPage + summary["TotalPages"] = totalPages + summary["CurrentPage"] = pageNum + summary["Models"] = template.HTML(elements.ListModels(models, processingModels, galleryService)) + + log.Debug().Msgf("totalPages : %+v\n", totalPages) + log.Debug().Msgf("prevPage : %+v\n", prevPage) + log.Debug().Msgf("nextPage : %+v\n", nextPage) + log.Debug().Msgf("CurrentPage : %+v\n", pageNum) + } + // Render index return c.Render("views/models", summary) }) @@ -171,6 +223,9 @@ func RegisterUIRoutes(app *fiber.App, // Show the models, filtered from the user input // https://htmx.org/examples/active-search/ app.Post("/browse/search/models", func(c *fiber.Ctx) error { + page := c.Query("page") + items := c.Query("items") + form := struct { Search string `form:"search"` }{} @@ -180,7 +235,26 @@ func RegisterUIRoutes(app *fiber.App, models, _ := gallery.AvailableGalleryModels(appConfig.Galleries, appConfig.ModelPath) - return c.SendString(elements.ListModels(gallery.GalleryModels(models).Search(form.Search), processingModels, galleryService)) + if page != "" { + // return a subset of the models + pageNum, err := strconv.Atoi(page) + if err != nil { + return c.Status(fiber.StatusBadRequest).SendString("Invalid page number") + } + + itemsNum, err := strconv.Atoi(items) + if err != nil { + itemsNum = 21 + } + + models = models.Paginate(pageNum, itemsNum) + } + + if form.Search != "" { + models = models.Search(form.Search) + } + + return c.SendString(elements.ListModels(models, processingModels, galleryService)) }) /* diff --git a/core/http/views/models.html b/core/http/views/models.html index 8bb049b66e31..9d1e857859f7 100644 --- a/core/http/views/models.html +++ b/core/http/views/models.html @@ -75,9 +75,37 @@

Filter by type:

hx-indicator=".htmx-indicator">
{{.Models}}
+ +
+
+ + + +
- {{template "views/partials/footer" .}}