mirror of
https://github.com/mudler/LocalAI.git
synced 2025-06-24 03:35:00 +00:00
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
parent
9a34fc8c66
commit
ec137888ba
7 changed files with 164 additions and 55 deletions
|
@ -1,9 +1,11 @@
|
|||
package gallery
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/mudler/LocalAI/core/config"
|
||||
"github.com/mudler/LocalAI/core/system"
|
||||
|
@ -13,11 +15,48 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
aliasFile = "alias"
|
||||
metaFile = "meta"
|
||||
runFile = "run.sh"
|
||||
metadataFile = "metadata.json"
|
||||
runFile = "run.sh"
|
||||
)
|
||||
|
||||
// readBackendMetadata reads the metadata JSON file for a backend
|
||||
func readBackendMetadata(backendPath string) (*BackendMetadata, error) {
|
||||
metadataPath := filepath.Join(backendPath, metadataFile)
|
||||
|
||||
// If metadata file doesn't exist, return nil (for backward compatibility)
|
||||
if _, err := os.Stat(metadataPath); os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(metadataPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read metadata file %q: %v", metadataPath, err)
|
||||
}
|
||||
|
||||
var metadata BackendMetadata
|
||||
if err := json.Unmarshal(data, &metadata); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal metadata file %q: %v", metadataPath, err)
|
||||
}
|
||||
|
||||
return &metadata, nil
|
||||
}
|
||||
|
||||
// writeBackendMetadata writes the metadata JSON file for a backend
|
||||
func writeBackendMetadata(backendPath string, metadata *BackendMetadata) error {
|
||||
metadataPath := filepath.Join(backendPath, metadataFile)
|
||||
|
||||
data, err := json.MarshalIndent(metadata, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal metadata: %v", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(metadataPath, data, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write metadata file %q: %v", metadataPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findBestBackendFromMeta(backend *GalleryBackend, systemState *system.SystemState, backends GalleryElements[*GalleryBackend]) *GalleryBackend {
|
||||
realBackend := backend.CapabilitiesMap[systemState.GPUVendor]
|
||||
if realBackend == "" {
|
||||
|
@ -63,10 +102,16 @@ func InstallBackendFromGallery(galleries []config.Gallery, systemState *system.S
|
|||
return fmt.Errorf("failed to create meta backend path %q: %v", metaBackendPath, err)
|
||||
}
|
||||
|
||||
// Then, let's create an meta file to point to the best backend
|
||||
metaFile := filepath.Join(metaBackendPath, metaFile)
|
||||
if err := os.WriteFile(metaFile, []byte(bestBackend.Name), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write meta file %q: %v", metaFile, err)
|
||||
// Create metadata for the meta backend
|
||||
metaMetadata := &BackendMetadata{
|
||||
MetaBackendFor: bestBackend.Name,
|
||||
Name: name,
|
||||
GalleryURL: backend.Gallery.URL,
|
||||
InstalledAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
if err := writeBackendMetadata(metaBackendPath, metaMetadata); err != nil {
|
||||
return fmt.Errorf("failed to write metadata for meta backend %q: %v", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -102,12 +147,19 @@ func InstallBackend(basePath string, config *GalleryBackend, downloadStatus func
|
|||
return fmt.Errorf("failed to extract image %q: %v", config.URI, err)
|
||||
}
|
||||
|
||||
// Create metadata for the backend
|
||||
metadata := &BackendMetadata{
|
||||
Name: name,
|
||||
GalleryURL: config.Gallery.URL,
|
||||
InstalledAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
if config.Alias != "" {
|
||||
// Write an alias file inside
|
||||
aliasFile := filepath.Join(backendPath, aliasFile)
|
||||
if err := os.WriteFile(aliasFile, []byte(config.Alias), 0644); err != nil {
|
||||
return fmt.Errorf("failed to write alias file %q: %v", aliasFile, err)
|
||||
}
|
||||
metadata.Alias = config.Alias
|
||||
}
|
||||
|
||||
if err := writeBackendMetadata(backendPath, metadata); err != nil {
|
||||
return fmt.Errorf("failed to write metadata for backend %q: %v", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -124,37 +176,39 @@ func DeleteBackendFromSystem(basePath string, name string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
foundBackend := false
|
||||
|
||||
for _, backend := range backends {
|
||||
if backend.IsDir() {
|
||||
aliasFile := filepath.Join(basePath, backend.Name(), aliasFile)
|
||||
alias, err := os.ReadFile(aliasFile)
|
||||
metadata, err := readBackendMetadata(filepath.Join(basePath, backend.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if string(alias) == name {
|
||||
if metadata != nil && metadata.Alias == name {
|
||||
backendDirectory = filepath.Join(basePath, backend.Name())
|
||||
foundBackend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if backendDirectory == "" {
|
||||
// If no backend found, return successfully (idempotent behavior)
|
||||
if !foundBackend {
|
||||
return fmt.Errorf("no backend found with name %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a meta, delete also associated backend
|
||||
metaFile := filepath.Join(backendDirectory, metaFile)
|
||||
if _, err := os.Stat(metaFile); err == nil {
|
||||
meta, err := os.ReadFile(metaFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
metaBackendDirectory := filepath.Join(basePath, string(meta))
|
||||
// If it's a meta backend, delete also associated backend
|
||||
metadata, err := readBackendMetadata(backendDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if metadata != nil && metadata.MetaBackendFor != "" {
|
||||
metaBackendDirectory := filepath.Join(basePath, metadata.MetaBackendFor)
|
||||
log.Debug().Str("backendDirectory", metaBackendDirectory).Msg("Deleting meta backend")
|
||||
if _, err := os.Stat(metaBackendDirectory); os.IsNotExist(err) {
|
||||
return fmt.Errorf("meta backend %q not found", string(meta))
|
||||
return fmt.Errorf("meta backend %q not found", metadata.MetaBackendFor)
|
||||
}
|
||||
os.RemoveAll(metaBackendDirectory)
|
||||
}
|
||||
|
@ -175,14 +229,13 @@ func ListSystemBackends(basePath string) (map[string]string, error) {
|
|||
runFile := filepath.Join(basePath, backend.Name(), runFile)
|
||||
backendsNames[backend.Name()] = runFile
|
||||
|
||||
aliasFile := filepath.Join(basePath, backend.Name(), aliasFile)
|
||||
if _, err := os.Stat(aliasFile); err == nil {
|
||||
// read the alias file, and use it as key
|
||||
alias, err := os.ReadFile(aliasFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
backendsNames[string(alias)] = runFile
|
||||
// Check for alias in metadata
|
||||
metadata, err := readBackendMetadata(filepath.Join(basePath, backend.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if metadata != nil && metadata.Alias != "" {
|
||||
backendsNames[metadata.Alias] = runFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue