feat(cli): allow to install backends from OCI tar files (#5816)

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-07-09 18:19:51 +02:00
committed by GitHub
parent 34171fcf94
commit ec206cc67c
4 changed files with 62 additions and 71 deletions
+3 -54
View File
@@ -8,7 +8,6 @@ import (
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/gallery"
"github.com/mudler/LocalAI/pkg/downloader"
"github.com/mudler/LocalAI/pkg/startup"
"github.com/rs/zerolog/log"
"github.com/schollz/progressbar/v3"
@@ -23,12 +22,6 @@ type BackendsList struct {
BackendsCMDFlags `embed:""`
}
type BackendsInstallSingle struct {
InstallArgs []string `arg:"" optional:"" name:"backend" help:"Backend images to install"`
BackendsCMDFlags `embed:""`
}
type BackendsInstall struct {
BackendArgs []string `arg:"" optional:"" name:"backends" help:"Backend configuration URLs to load"`
@@ -42,36 +35,9 @@ type BackendsUninstall struct {
}
type BackendsCMD struct {
List BackendsList `cmd:"" help:"List the backends available in your galleries" default:"withargs"`
Install BackendsInstall `cmd:"" help:"Install a backend from the gallery"`
InstallSingle BackendsInstallSingle `cmd:"" help:"Install a single backend from the gallery"`
Uninstall BackendsUninstall `cmd:"" help:"Uninstall a backend"`
}
func (bi *BackendsInstallSingle) Run(ctx *cliContext.Context) error {
for _, backend := range bi.InstallArgs {
progressBar := progressbar.NewOptions(
1000,
progressbar.OptionSetDescription(fmt.Sprintf("downloading backend %s", backend)),
progressbar.OptionShowBytes(false),
progressbar.OptionClearOnFinish(),
)
progressCallback := func(fileName string, current string, total string, percentage float64) {
v := int(percentage * 10)
err := progressBar.Set(v)
if err != nil {
log.Error().Err(err).Str("filename", fileName).Int("value", v).Msg("error while updating progress bar")
}
}
if err := gallery.InstallBackend(bi.BackendsPath, &gallery.GalleryBackend{
URI: backend,
}, progressCallback); err != nil {
return err
}
}
return nil
List BackendsList `cmd:"" help:"List the backends available in your galleries" default:"withargs"`
Install BackendsInstall `cmd:"" help:"Install a backend from the gallery"`
Uninstall BackendsUninstall `cmd:"" help:"Uninstall a backend"`
}
func (bl *BackendsList) Run(ctx *cliContext.Context) error {
@@ -116,23 +82,6 @@ func (bi *BackendsInstall) Run(ctx *cliContext.Context) error {
}
}
backendURI := downloader.URI(backendName)
if !backendURI.LooksLikeOCI() {
backends, err := gallery.AvailableBackends(galleries, bi.BackendsPath)
if err != nil {
return err
}
backend := gallery.FindGalleryElement(backends, backendName, bi.BackendsPath)
if backend == nil {
log.Error().Str("backend", backendName).Msg("backend not found")
return fmt.Errorf("backend not found: %s", backendName)
}
log.Info().Str("backend", backendName).Str("license", backend.License).Msg("installing backend")
}
err := startup.InstallExternalBackends(galleries, bi.BackendsPath, progressCallback, backendName)
if err != nil {
return err
+7 -11
View File
@@ -9,8 +9,8 @@ import (
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/system"
"github.com/mudler/LocalAI/pkg/downloader"
"github.com/mudler/LocalAI/pkg/model"
"github.com/mudler/LocalAI/pkg/oci"
"github.com/rs/zerolog/log"
)
@@ -151,19 +151,15 @@ func InstallBackend(basePath string, config *GalleryBackend, downloadStatus func
}
name := config.Name
img, err := oci.GetImage(config.URI, "", nil, nil)
if err != nil {
return fmt.Errorf("failed to get image %q: %v", config.URI, err)
}
backendPath := filepath.Join(basePath, name)
if err := os.MkdirAll(backendPath, 0750); err != nil {
return fmt.Errorf("failed to create backend path %q: %v", backendPath, err)
err = os.MkdirAll(backendPath, 0750)
if err != nil {
return fmt.Errorf("failed to create base path: %v", err)
}
if err := oci.ExtractOCIImage(img, config.URI, backendPath, downloadStatus); err != nil {
return fmt.Errorf("failed to extract image %q: %v", config.URI, err)
uri := downloader.URI(config.URI)
if err := uri.DownloadFile(backendPath, "", 1, 1, downloadStatus); err != nil {
return fmt.Errorf("failed to download backend %q: %v", config.URI, err)
}
// Create metadata for the backend