feat(backends): add system backend, refactor (#6059)

- Add a system backend path
- Refactor and consolidate system information in system state
- Use system state in all the components to figure out the system paths
  to used whenever needed
- Refactor BackendConfig -> ModelConfig. This was otherway misleading as
  now we do have a backend configuration which is not the model config.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-08-14 19:38:26 +02:00
committed by GitHub
parent 253b7537dc
commit 089efe05fd
85 changed files with 999 additions and 652 deletions

View File

@@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/mudler/LocalAI/pkg/system"
"github.com/mudler/LocalAI/pkg/utils"
"github.com/rs/zerolog/log"
@@ -28,9 +29,9 @@ type ModelLoader struct {
externalBackends map[string]string
}
func NewModelLoader(modelPath string, singleActiveBackend bool) *ModelLoader {
func NewModelLoader(system *system.SystemState, singleActiveBackend bool) *ModelLoader {
nml := &ModelLoader{
ModelPath: modelPath,
ModelPath: system.Model.ModelsPath,
models: make(map[string]*Model),
singletonMode: singleActiveBackend,
externalBackends: make(map[string]string),

View File

@@ -6,6 +6,7 @@ import (
"path/filepath"
"github.com/mudler/LocalAI/pkg/model"
"github.com/mudler/LocalAI/pkg/system"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
@@ -21,7 +22,12 @@ var _ = Describe("ModelLoader", func() {
// Setup the model loader with a test directory
modelPath = "/tmp/test_model_path"
os.Mkdir(modelPath, 0755)
modelLoader = model.NewModelLoader(modelPath, false)
systemState, err := system.GetSystemState(
system.WithModelPath(modelPath),
)
Expect(err).ToNot(HaveOccurred())
modelLoader = model.NewModelLoader(systemState, false)
})
AfterEach(func() {

View File

@@ -6,16 +6,9 @@ import (
"strings"
"github.com/jaypipes/ghw/pkg/gpu"
"github.com/mudler/LocalAI/pkg/xsysinfo"
"github.com/rs/zerolog/log"
)
type SystemState struct {
GPUVendor string
gpus []*gpu.GraphicsCard
VRAM uint64
}
const (
defaultCapability = "default"
nvidiaL4T = "nvidia-l4t"
@@ -103,22 +96,6 @@ func (s *SystemState) getSystemCapabilities() string {
return s.GPUVendor
}
func GetSystemState() (*SystemState, error) {
// Detection is best-effort here, we don't want to fail if it fails
gpus, _ := xsysinfo.GPUs()
log.Debug().Any("gpus", gpus).Msg("GPUs")
gpuVendor, _ := detectGPUVendor(gpus)
log.Debug().Str("gpuVendor", gpuVendor).Msg("GPU vendor")
vram, _ := xsysinfo.TotalAvailableVRAM()
log.Debug().Any("vram", vram).Msg("Total available VRAM")
return &SystemState{
GPUVendor: gpuVendor,
gpus: gpus,
VRAM: vram,
}, nil
}
func detectGPUVendor(gpus []*gpu.GraphicsCard) (string, error) {
for _, gpu := range gpus {
if gpu.DeviceInfo != nil {

61
pkg/system/state.go Normal file
View File

@@ -0,0 +1,61 @@
package system
import (
"github.com/jaypipes/ghw/pkg/gpu"
"github.com/mudler/LocalAI/pkg/xsysinfo"
"github.com/rs/zerolog/log"
)
type Backend struct {
BackendsPath string
BackendsSystemPath string
}
type Model struct {
ModelsPath string
}
type SystemState struct {
GPUVendor string
Backend Backend
Model Model
gpus []*gpu.GraphicsCard
VRAM uint64
}
type SystemStateOptions func(*SystemState)
func WithBackendPath(path string) SystemStateOptions {
return func(s *SystemState) {
s.Backend.BackendsPath = path
}
}
func WithBackendSystemPath(path string) SystemStateOptions {
return func(s *SystemState) {
s.Backend.BackendsSystemPath = path
}
}
func WithModelPath(path string) SystemStateOptions {
return func(s *SystemState) {
s.Model.ModelsPath = path
}
}
func GetSystemState(opts ...SystemStateOptions) (*SystemState, error) {
state := &SystemState{}
for _, opt := range opts {
opt(state)
}
// Detection is best-effort here, we don't want to fail if it fails
state.gpus, _ = xsysinfo.GPUs()
log.Debug().Any("gpus", state.gpus).Msg("GPUs")
state.GPUVendor, _ = detectGPUVendor(state.gpus)
log.Debug().Str("gpuVendor", state.GPUVendor).Msg("GPU vendor")
state.VRAM, _ = xsysinfo.TotalAvailableVRAM()
log.Debug().Any("vram", state.VRAM).Msg("Total available VRAM")
return state, nil
}