mirror of
https://github.com/mudler/LocalAI.git
synced 2026-09-12 22:33:54 -04:00
feat: bound backend admission and expose running traces Add process-wide backend execution admission without blocking UI or administrative HTTP work. Represent backend operations while they are in flight, surface running traces with immediate log links, and tie streaming admission leases to the gRPC receive lifecycle. Assisted-by: OpenAI Codex: GPT-5 Signed-off-by: Richard Palethorpe <io@richiejp.com>
117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
package backend
|
|
|
|
import (
|
|
"maps"
|
|
"time"
|
|
|
|
"github.com/mudler/LocalAI/core/config"
|
|
"github.com/mudler/LocalAI/core/trace"
|
|
"github.com/mudler/LocalAI/pkg/grpc/proto"
|
|
model "github.com/mudler/LocalAI/pkg/model"
|
|
)
|
|
|
|
// Model3DGenerationOptions is the backend-neutral request passed to 3D
|
|
// generators. Image contains a staged local path by the time it reaches
|
|
// this layer.
|
|
type Model3DGenerationOptions struct {
|
|
Image string
|
|
Destination string
|
|
Seed int32
|
|
Step int32
|
|
CFGScale float32
|
|
TextureSteps int32
|
|
Quality string
|
|
Background string
|
|
Params map[string]string
|
|
}
|
|
|
|
func Model3DGeneration(options Model3DGenerationOptions, loader *model.ModelLoader, modelConfig config.ModelConfig, appConfig *config.ApplicationConfig) (func() error, error) {
|
|
opts := ModelOptions(modelConfig, appConfig)
|
|
inferenceModel, err := loader.Load(opts...)
|
|
if err != nil {
|
|
recordModelLoadFailure(appConfig, modelConfig.Name, modelConfig.Backend, err, nil)
|
|
return nil, err
|
|
}
|
|
|
|
fn := func() error {
|
|
_, err := inferenceModel.Generate3D(
|
|
appConfig.Context,
|
|
&proto.Generate3DRequest{
|
|
Src: options.Image,
|
|
Dst: options.Destination,
|
|
Seed: options.Seed,
|
|
Step: options.Step,
|
|
CfgScale: options.CFGScale,
|
|
TextureSteps: options.TextureSteps,
|
|
Quality: options.Quality,
|
|
Background: options.Background,
|
|
Params: maps.Clone(options.Params),
|
|
},
|
|
)
|
|
return err
|
|
}
|
|
|
|
if appConfig.EnableTracing {
|
|
trace.InitBackendTracingIfEnabled(appConfig.TracingMaxItems, appConfig.TracingMaxBodyBytes)
|
|
|
|
traceType := trace.BackendTrace3DGeneration
|
|
traceSummary := "3d: " + options.Quality
|
|
traceData := map[string]any{}
|
|
if options.Params["operation"] == "print_remesh" {
|
|
traceType = trace.BackendTrace3DRemesh
|
|
traceSummary = "3d: remesh"
|
|
traceData["detail_percent"] = options.Params["detail_percent"]
|
|
traceData["has_mesh"] = options.Image != ""
|
|
} else {
|
|
traceData = map[string]any{
|
|
"seed": options.Seed,
|
|
"step": options.Step,
|
|
"cfg_scale": options.CFGScale,
|
|
"texture_steps": options.TextureSteps,
|
|
"quality": options.Quality,
|
|
"background": options.Background,
|
|
"has_image": options.Image != "",
|
|
}
|
|
}
|
|
|
|
originalFn := fn
|
|
fn = func() error {
|
|
startTime := time.Now()
|
|
traceID := trace.BeginBackendTrace(trace.BackendTrace{Timestamp: startTime, Type: traceType, ModelName: modelConfig.Name, Backend: modelConfig.Backend, Summary: trace.TruncateString(traceSummary, 200)})
|
|
defer trace.CancelBackendTrace(traceID)
|
|
err := originalFn()
|
|
duration := time.Since(startTime)
|
|
|
|
errStr := ""
|
|
if err != nil {
|
|
errStr = err.Error()
|
|
}
|
|
|
|
trace.RecordBackendTrace(trace.BackendTrace{
|
|
ID: traceID,
|
|
Timestamp: startTime,
|
|
Duration: duration,
|
|
Type: traceType,
|
|
ModelName: modelConfig.Name,
|
|
Backend: modelConfig.Backend,
|
|
Summary: trace.TruncateString(traceSummary, 200),
|
|
Error: errStr,
|
|
Data: traceData,
|
|
})
|
|
|
|
return err
|
|
}
|
|
}
|
|
originalFn := fn
|
|
fn = func() error {
|
|
release, err := AcquireGlobalBackendSlot()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer release()
|
|
return originalFn()
|
|
}
|
|
|
|
return fn, nil
|
|
}
|