mirror of
https://github.com/mudler/LocalAI.git
synced 2025-05-28 06:25:00 +00:00
feat(oci): support OCI images and Ollama models (#2628)
* Support specifying oci:// and ollama:// for model URLs Fixes: https://github.com/mudler/LocalAI/issues/2527 Fixes: https://github.com/mudler/LocalAI/issues/1028 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Lower watcher warnings Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Allow to install ollama models from CLI Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fixup tests Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Do not keep file ownership Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Skip test on darwin Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
parent
e265a618d9
commit
f569237a50
19 changed files with 638 additions and 97 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
cliContext "github.com/go-skynet/LocalAI/core/cli/context"
|
||||
|
||||
"github.com/go-skynet/LocalAI/pkg/downloader"
|
||||
"github.com/go-skynet/LocalAI/pkg/gallery"
|
||||
"github.com/go-skynet/LocalAI/pkg/startup"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -79,13 +80,15 @@ func (mi *ModelsInstall) Run(ctx *cliContext.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
model := gallery.FindModel(models, modelName, mi.ModelsPath)
|
||||
if model == nil {
|
||||
log.Error().Str("model", modelName).Msg("model not found")
|
||||
return err
|
||||
}
|
||||
if !downloader.LooksLikeOCI(modelName) {
|
||||
model := gallery.FindModel(models, modelName, mi.ModelsPath)
|
||||
if model == nil {
|
||||
log.Error().Str("model", modelName).Msg("model not found")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Str("model", modelName).Str("license", model.License).Msg("installing model")
|
||||
log.Info().Str("model", modelName).Str("license", model.License).Msg("installing model")
|
||||
}
|
||||
err = startup.InstallModels(galleries, "", mi.ModelsPath, progressCallback, modelName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -74,7 +74,7 @@ func getModelStatus(url string) (response map[string]interface{}) {
|
|||
|
||||
func getModels(url string) (response []gallery.GalleryModel) {
|
||||
// TODO: No tests currently seem to exercise file:// urls. Fix?
|
||||
downloader.GetURI(url, "", func(url string, i []byte) error {
|
||||
downloader.DownloadAndUnmarshal(url, "", func(url string, i []byte) error {
|
||||
// Unmarshal YAML data into a struct
|
||||
return json.Unmarshal(i, &response)
|
||||
})
|
||||
|
|
|
@ -116,7 +116,7 @@ func (c *configFileHandler) Watch() error {
|
|||
// Add a path.
|
||||
err = c.watcher.Add(c.appConfig.DynamicConfigsDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to establish watch on the LocalAI Configuration Directory: %+v", err)
|
||||
return fmt.Errorf("unable to create a watcher on the configuration directory: %+v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -142,17 +142,37 @@ func Startup(opts ...config.AppOption) (*config.BackendConfigLoader, *model.Mode
|
|||
}
|
||||
|
||||
// Watch the configuration directory
|
||||
// If the directory does not exist, we don't watch it
|
||||
configHandler := newConfigFileHandler(options)
|
||||
err = configHandler.Watch()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error establishing configuration directory watcher")
|
||||
}
|
||||
startWatcher(options)
|
||||
|
||||
log.Info().Msg("core/startup process completed!")
|
||||
return cl, ml, options, nil
|
||||
}
|
||||
|
||||
func startWatcher(options *config.ApplicationConfig) {
|
||||
if options.DynamicConfigsDir == "" {
|
||||
// No need to start the watcher if the directory is not set
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := os.Stat(options.DynamicConfigsDir); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// We try to create the directory if it does not exist and was specified
|
||||
if err := os.MkdirAll(options.DynamicConfigsDir, 0700); err != nil {
|
||||
log.Error().Err(err).Msg("failed creating DynamicConfigsDir")
|
||||
}
|
||||
} else {
|
||||
// something else happened, we log the error and don't start the watcher
|
||||
log.Error().Err(err).Msg("failed to read DynamicConfigsDir, watcher will not be started")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
configHandler := newConfigFileHandler(options)
|
||||
if err := configHandler.Watch(); err != nil {
|
||||
log.Error().Err(err).Msg("failed creating watcher")
|
||||
}
|
||||
}
|
||||
|
||||
// In Lieu of a proper DI framework, this function wires up the Application manually.
|
||||
// This is in core/startup rather than core/state.go to keep package references clean!
|
||||
func createApplication(appConfig *config.ApplicationConfig) *core.Application {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue