mirror of
https://github.com/mudler/LocalAI.git
synced 2025-05-31 07:54:59 +00:00
feat(gallery): support model deletion (#2173)
* feat(gallery): op now supports deletion of models Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Wire things with WebUI(WIP) Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * minor improvements Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
parent
a24cd4fda0
commit
e8d44447ad
12 changed files with 294 additions and 36 deletions
|
@ -1,6 +1,7 @@
|
|||
package gallery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -184,3 +185,48 @@ func getGalleryModels(gallery Gallery, basePath string) ([]*GalleryModel, error)
|
|||
}
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func DeleteModelFromSystem(basePath string, name string, additionalFiles []string) error {
|
||||
// os.PathSeparator is not allowed in model names. Replace them with "__" to avoid conflicts with file paths.
|
||||
name = strings.ReplaceAll(name, string(os.PathSeparator), "__")
|
||||
|
||||
configFile := filepath.Join(basePath, fmt.Sprintf("%s.yaml", name))
|
||||
|
||||
galleryFile := filepath.Join(basePath, galleryFileName(name))
|
||||
|
||||
var err error
|
||||
// Delete all the files associated to the model
|
||||
// read the model config
|
||||
galleryconfig, err := ReadConfigFile(galleryFile)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("failed to read gallery file %s", configFile)
|
||||
}
|
||||
|
||||
// Remove additional files
|
||||
if galleryconfig != nil {
|
||||
for _, f := range galleryconfig.Files {
|
||||
fullPath := filepath.Join(basePath, f.Filename)
|
||||
log.Debug().Msgf("Removing file %s", fullPath)
|
||||
if e := os.Remove(fullPath); e != nil {
|
||||
err = errors.Join(err, fmt.Errorf("failed to remove file %s: %w", f.Filename, e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range additionalFiles {
|
||||
fullPath := filepath.Join(filepath.Join(basePath, f))
|
||||
log.Debug().Msgf("Removing additional file %s", fullPath)
|
||||
if e := os.Remove(fullPath); e != nil {
|
||||
err = errors.Join(err, fmt.Errorf("failed to remove file %s: %w", f, e))
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Removing model config file %s", configFile)
|
||||
|
||||
// Delete the model config file
|
||||
if e := os.Remove(configFile); e != nil {
|
||||
err = errors.Join(err, fmt.Errorf("failed to remove file %s: %w", configFile, e))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package gallery_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
@ -11,3 +12,9 @@ func TestGallery(t *testing.T) {
|
|||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Gallery test suite")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
if os.Getenv("FIXTURES") == "" {
|
||||
Fail("FIXTURES env var not set")
|
||||
}
|
||||
})
|
||||
|
|
|
@ -178,5 +178,20 @@ func InstallModel(basePath, nameOverride string, config *Config, configOverrides
|
|||
log.Debug().Msgf("Written config file %s", configFilePath)
|
||||
}
|
||||
|
||||
return nil
|
||||
// Save the model gallery file for further reference
|
||||
modelFile := filepath.Join(basePath, galleryFileName(name))
|
||||
data, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Written gallery file %s", modelFile)
|
||||
|
||||
return os.WriteFile(modelFile, data, 0600)
|
||||
|
||||
//return nil
|
||||
}
|
||||
|
||||
func galleryFileName(name string) string {
|
||||
return "._gallery_" + name + ".yaml"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package gallery_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -11,6 +12,7 @@ import (
|
|||
)
|
||||
|
||||
var _ = Describe("Model test", func() {
|
||||
|
||||
Context("Downloading", func() {
|
||||
It("applies model correctly", func() {
|
||||
tempdir, err := os.MkdirTemp("", "test")
|
||||
|
@ -80,6 +82,19 @@ var _ = Describe("Model test", func() {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(models)).To(Equal(1))
|
||||
Expect(models[0].Installed).To(BeTrue())
|
||||
|
||||
// delete
|
||||
err = DeleteModelFromSystem(tempdir, "bert", []string{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
models, err = AvailableGalleryModels(galleries, tempdir)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(models)).To(Equal(1))
|
||||
Expect(models[0].Installed).To(BeFalse())
|
||||
|
||||
_, err = os.Stat(filepath.Join(tempdir, "bert.yaml"))
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(errors.Is(err, os.ErrNotExist)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("renames model correctly", func() {
|
||||
|
|
|
@ -4,12 +4,14 @@ type GalleryOp struct {
|
|||
Id string
|
||||
GalleryName string
|
||||
ConfigURL string
|
||||
Delete bool
|
||||
|
||||
Req GalleryModel
|
||||
Galleries []Gallery
|
||||
}
|
||||
|
||||
type GalleryOpStatus struct {
|
||||
Deletion bool `json:"deletion"` // Deletion is true if the operation is a deletion
|
||||
FileName string `json:"file_name"`
|
||||
Error error `json:"error"`
|
||||
Processed bool `json:"processed"`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue