mirror of
https://github.com/mudler/LocalAI.git
synced 2026-05-01 15:50:46 -05:00
feat(backends install): allow to specify name and alias during manual installation (#5971)
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
GitHub
parent
240b790f29
commit
05757e2738
@@ -59,8 +59,10 @@ func New(opts ...config.AppOption) (*Application, error) {
|
||||
log.Error().Err(err).Msg("error installing models")
|
||||
}
|
||||
|
||||
if err := coreStartup.InstallExternalBackends(options.BackendGalleries, options.BackendsPath, nil, options.ExternalBackends...); err != nil {
|
||||
log.Error().Err(err).Msg("error installing external backends")
|
||||
for _, backend := range options.ExternalBackends {
|
||||
if err := coreStartup.InstallExternalBackends(options.BackendGalleries, options.BackendsPath, nil, backend, "", ""); err != nil {
|
||||
log.Error().Err(err).Msg("error installing external backend")
|
||||
}
|
||||
}
|
||||
|
||||
configLoaderOpts := options.ToConfigLoaderOptions()
|
||||
|
||||
+19
-19
@@ -23,7 +23,9 @@ type BackendsList struct {
|
||||
}
|
||||
|
||||
type BackendsInstall struct {
|
||||
BackendArgs []string `arg:"" optional:"" name:"backends" help:"Backend configuration URLs to load"`
|
||||
BackendArgs string `arg:"" optional:"" name:"backend" help:"Backend configuration URL to load"`
|
||||
Name string `arg:"" optional:"" name:"name" help:"Name of the backend"`
|
||||
Alias string `arg:"" optional:"" name:"alias" help:"Alias of the backend"`
|
||||
|
||||
BackendsCMDFlags `embed:""`
|
||||
}
|
||||
@@ -66,27 +68,25 @@ func (bi *BackendsInstall) Run(ctx *cliContext.Context) error {
|
||||
log.Error().Err(err).Msg("unable to load galleries")
|
||||
}
|
||||
|
||||
for _, backendName := range bi.BackendArgs {
|
||||
|
||||
progressBar := progressbar.NewOptions(
|
||||
1000,
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("downloading backend %s", backendName)),
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
err := startup.InstallExternalBackends(galleries, bi.BackendsPath, progressCallback, backendName)
|
||||
progressBar := progressbar.NewOptions(
|
||||
1000,
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("downloading backend %s", bi.BackendArgs)),
|
||||
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 {
|
||||
return err
|
||||
log.Error().Err(err).Str("filename", fileName).Int("value", v).Msg("error while updating progress bar")
|
||||
}
|
||||
}
|
||||
|
||||
err := startup.InstallExternalBackends(galleries, bi.BackendsPath, progressCallback, bi.BackendArgs, bi.Name, bi.Alias)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package startup
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -13,49 +12,68 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func InstallExternalBackends(galleries []config.Gallery, backendPath string, downloadStatus func(string, string, string, float64), backends ...string) error {
|
||||
var errs error
|
||||
func InstallExternalBackends(galleries []config.Gallery, backendPath string, downloadStatus func(string, string, string, float64), backend, name, alias string) error {
|
||||
systemState, err := system.GetSystemState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get system state: %w", err)
|
||||
}
|
||||
for _, backend := range backends {
|
||||
uri := downloader.URI(backend)
|
||||
switch {
|
||||
case uri.LooksLikeDir():
|
||||
name := filepath.Base(backend)
|
||||
log.Info().Str("backend", backend).Str("name", name).Msg("Installing backend from path")
|
||||
if err := gallery.InstallBackend(backendPath, &gallery.GalleryBackend{
|
||||
Metadata: gallery.Metadata{
|
||||
Name: name,
|
||||
},
|
||||
URI: backend,
|
||||
}, downloadStatus); err != nil {
|
||||
errs = errors.Join(err, fmt.Errorf("error installing backend %s", backend))
|
||||
}
|
||||
case uri.LooksLikeOCI():
|
||||
name, err := uri.FilenameFromUrl()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get filename from URL: %w", err)
|
||||
}
|
||||
// strip extension if any
|
||||
name = strings.TrimSuffix(name, filepath.Ext(name))
|
||||
uri := downloader.URI(backend)
|
||||
switch {
|
||||
case uri.LooksLikeDir():
|
||||
if name == "" { // infer it from the path
|
||||
name = filepath.Base(backend)
|
||||
}
|
||||
log.Info().Str("backend", backend).Str("name", name).Msg("Installing backend from path")
|
||||
if err := gallery.InstallBackend(backendPath, &gallery.GalleryBackend{
|
||||
Metadata: gallery.Metadata{
|
||||
Name: name,
|
||||
},
|
||||
Alias: alias,
|
||||
URI: backend,
|
||||
}, downloadStatus); err != nil {
|
||||
return fmt.Errorf("error installing backend %s: %w", backend, err)
|
||||
}
|
||||
case uri.LooksLikeOCI() && !uri.LooksLikeOCIFile():
|
||||
if name == "" {
|
||||
return fmt.Errorf("specifying a name is required for OCI images")
|
||||
}
|
||||
log.Info().Str("backend", backend).Str("name", name).Msg("Installing backend from OCI image")
|
||||
if err := gallery.InstallBackend(backendPath, &gallery.GalleryBackend{
|
||||
Metadata: gallery.Metadata{
|
||||
Name: name,
|
||||
},
|
||||
Alias: alias,
|
||||
URI: backend,
|
||||
}, downloadStatus); err != nil {
|
||||
return fmt.Errorf("error installing backend %s: %w", backend, err)
|
||||
}
|
||||
case uri.LooksLikeOCIFile():
|
||||
name, err := uri.FilenameFromUrl()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get filename from URL: %w", err)
|
||||
}
|
||||
// strip extension if any
|
||||
name = strings.TrimSuffix(name, filepath.Ext(name))
|
||||
|
||||
log.Info().Str("backend", backend).Str("name", name).Msg("Installing backend from OCI image")
|
||||
if err := gallery.InstallBackend(backendPath, &gallery.GalleryBackend{
|
||||
Metadata: gallery.Metadata{
|
||||
Name: name,
|
||||
},
|
||||
URI: backend,
|
||||
}, downloadStatus); err != nil {
|
||||
errs = errors.Join(err, fmt.Errorf("error installing backend %s", backend))
|
||||
}
|
||||
default:
|
||||
err := gallery.InstallBackendFromGallery(galleries, systemState, backend, backendPath, downloadStatus, true)
|
||||
if err != nil {
|
||||
errs = errors.Join(err, fmt.Errorf("error installing backend %s", backend))
|
||||
}
|
||||
log.Info().Str("backend", backend).Str("name", name).Msg("Installing backend from OCI image")
|
||||
if err := gallery.InstallBackend(backendPath, &gallery.GalleryBackend{
|
||||
Metadata: gallery.Metadata{
|
||||
Name: name,
|
||||
},
|
||||
Alias: alias,
|
||||
URI: backend,
|
||||
}, downloadStatus); err != nil {
|
||||
return fmt.Errorf("error installing backend %s: %w", backend, err)
|
||||
}
|
||||
default:
|
||||
if name != "" || alias != "" {
|
||||
return fmt.Errorf("specifying a name or alias is not supported for this backend")
|
||||
}
|
||||
err := gallery.InstallBackendFromGallery(galleries, systemState, backend, backendPath, downloadStatus, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error installing backend %s: %w", backend, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+16
-12
@@ -98,19 +98,19 @@ func (uri URI) DownloadWithAuthorizationAndCallback(basePath string, authorizati
|
||||
}
|
||||
|
||||
func (u URI) FilenameFromUrl() (string, error) {
|
||||
f, err := filenameFromUrl(string(u))
|
||||
if err != nil || f == "" {
|
||||
f = utils.MD5(string(u))
|
||||
if strings.HasSuffix(string(u), ".yaml") || strings.HasSuffix(string(u), ".yml") {
|
||||
f = f + ".yaml"
|
||||
}
|
||||
err = nil
|
||||
if f := filenameFromUrl(string(u)); f != "" {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
return f, err
|
||||
f := utils.MD5(string(u))
|
||||
if strings.HasSuffix(string(u), ".yaml") || strings.HasSuffix(string(u), ".yml") {
|
||||
f = f + ".yaml"
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func filenameFromUrl(urlstr string) (string, error) {
|
||||
func filenameFromUrl(urlstr string) string {
|
||||
// strip anything after @
|
||||
if strings.Contains(urlstr, "@") {
|
||||
urlstr = strings.Split(urlstr, "@")[0]
|
||||
@@ -118,13 +118,13 @@ func filenameFromUrl(urlstr string) (string, error) {
|
||||
|
||||
u, err := url.Parse(urlstr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error due to parsing url: %w", err)
|
||||
return ""
|
||||
}
|
||||
x, err := url.QueryUnescape(u.EscapedPath())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error due to escaping: %w", err)
|
||||
return ""
|
||||
}
|
||||
return filepath.Base(x), nil
|
||||
return filepath.Base(x)
|
||||
}
|
||||
|
||||
func (u URI) LooksLikeURL() bool {
|
||||
@@ -158,6 +158,10 @@ func (s URI) LooksLikeOCI() bool {
|
||||
strings.HasPrefix(string(s), "docker.io")
|
||||
}
|
||||
|
||||
func (s URI) LooksLikeOCIFile() bool {
|
||||
return strings.HasPrefix(string(s), OCIFilePrefix)
|
||||
}
|
||||
|
||||
func (s URI) ResolveURL() string {
|
||||
switch {
|
||||
case strings.HasPrefix(string(s), GithubURI2):
|
||||
|
||||
Reference in New Issue
Block a user