Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/application/distributed.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type DistributedServices struct {
FileStager nodes.FileStager
ModelAdapter *nodes.ModelRouterAdapter
Unloader *nodes.RemoteUnloaderAdapter
ModelCleanup *nodes.ModelCleanupService

shutdownOnce sync.Once
}
Expand Down Expand Up @@ -346,8 +347,10 @@ func initDistributed(cfg *config.ApplicationConfig, authDB *gorm.DB, configLoade
if configLoader != nil {
conflictResolver = configLoader
}
modelCleanup := nodes.NewModelCleanupService(registry, remoteUnloader)
router := nodes.NewSmartRouter(registry, nodes.SmartRouterOptions{
Unloader: remoteUnloader,
ModelCleanup: modelCleanup,
FileStager: fileStager,
GalleriesJSON: routerGalleriesJSON,
AuthToken: routerAuthToken,
Expand Down Expand Up @@ -437,6 +440,7 @@ func initDistributed(cfg *config.ApplicationConfig, authDB *gorm.DB, configLoade
FileStager: fileStager,
ModelAdapter: modelAdapter,
Unloader: remoteUnloader,
ModelCleanup: modelCleanup,
}, nil
}

Expand Down
5 changes: 4 additions & 1 deletion core/application/startup.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ func New(opts ...config.AppOption) (*Application, error) {
if distSvc.Reconciler != nil {
go distSvc.Reconciler.Run(options.Context)
}
go distSvc.ModelCleanup.Run(options.Context)
// In distributed mode, MCP CI jobs are executed by agent workers (not the frontend)
// because the frontend can't create MCP sessions (e.g., stdio servers using docker).
// The dispatcher still subscribes to jobs.new for persistence (result/progress subs)
Expand Down Expand Up @@ -370,13 +371,15 @@ func New(opts ...config.AppOption) (*Application, error) {
gs := application.galleryService
sys := options.SystemState
cfgLoaderOpts := options.ToConfigLoaderOptions()
modelRevisionLifecycle := modeladmin.NewDistributedModelRevisionLifecycle(distSvc.Registry, distSvc.ModelCleanup)
gs.SetModelRevisionLifecycle(modelRevisionLifecycle)
gs.OnModelsChanged = func(evt messaging.CacheInvalidateEvent) {
// ApplyRemoteChange honors the op: a "delete" prunes the element
// (a reload-from-path is additive and cannot drop it), anything
// else reloads from disk; a named element's running instance is
// shut down so the new config takes effect. The originating
// replica reloads inline and never depends on this path.
if err := modeladmin.ApplyRemoteChange(application.ModelConfigLoader(), application.modelLoader, sys.Model.ModelsPath, evt, cfgLoaderOpts...); err != nil {
if err := modeladmin.ApplyRemoteChange(options.Context, application.ModelConfigLoader(), sys.Model.ModelsPath, evt, modelRevisionLifecycle, cfgLoaderOpts...); err != nil {
xlog.Warn("Failed to apply peer model config change", "error", err)
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/backend/ctx_propagation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
"github.com/mudler/LocalAI/core/backend"
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/schema"
pbproto "github.com/mudler/LocalAI/pkg/grpc/proto"
"github.com/mudler/LocalAI/pkg/distributedhdr"
pbproto "github.com/mudler/LocalAI/pkg/grpc/proto"
"github.com/mudler/LocalAI/pkg/model"
"github.com/mudler/LocalAI/pkg/system"

Expand All @@ -41,7 +41,7 @@ import (
func newCapturingLoader() (*model.ModelLoader, *atomic.Value, func() context.Context) {
loader := model.NewModelLoader(&system.SystemState{})
var captured atomic.Value
loader.SetModelRouter(func(ctx context.Context, _ string, _, _, _ string, _ *pbproto.ModelOptions, _ bool) (*model.Model, error) {
loader.SetModelRouter(func(ctx context.Context, _ string, _, _, _, _ string, _ *pbproto.ModelOptions, _ bool) (*model.Model, error) {
captured.Store(ctx)
// Return an error so the backend short-circuits before trying to
// dial gRPC. We only care about the context-arrival contract.
Expand Down
2 changes: 1 addition & 1 deletion core/backend/model_identity_modalities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (r *recordingBackend) VoiceEmbed(_ context.Context, in *pb.VoiceEmbedReques
// backend, so every helper below reaches it through the real Load path.
func newRecordingLoader(rec *recordingBackend) *model.ModelLoader {
loader := model.NewModelLoader(&system.SystemState{})
loader.SetModelRouter(func(_ context.Context, id string, _, _, _ string, _ *pb.ModelOptions, _ bool) (*model.Model, error) {
loader.SetModelRouter(func(_ context.Context, id string, _, _, _, _ string, _ *pb.ModelOptions, _ bool) (*model.Model, error) {
return model.NewModelWithClient(id, "test://recording", rec), nil
})
return loader
Expand Down
5 changes: 5 additions & 0 deletions core/backend/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ func ModelOptions(c config.ModelConfig, so *config.ApplicationConfig, opts ...mo
model.WithContext(so.Context),
model.WithModelID(c.ModelID()),
}
if revision, err := config.ModelConfigRevision(&c); err == nil {
defOpts = append(defOpts, model.WithConfigRevision(revision))
} else {
xlog.Warn("Failed to compute model configuration revision", "model", c.ModelID(), "error", err)
}
managedPrimary := len(c.Artifacts) > 0 && c.Artifacts[0].Resolved != nil
if managedPrimary {
defOpts = append(defOpts, model.WithModelFile(c.ModelFileName()))
Expand Down
1 change: 1 addition & 0 deletions core/config/application_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ func (o *ApplicationConfig) ToConfigLoaderOptions() []ConfigLoaderOption {
LoadOptionF16(o.F16),
LoadOptionThreads(o.Threads),
ModelPath(o.SystemState.Model.ModelsPath),
LoadOptionGalleryFiles(o.Galleries...),
}
}

Expand Down
Loading
Loading