mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-30 09:57:57 -04:00
* feat(settings): add declarative runtime-settings field registry One fieldSpec row per RuntimeSettings field, with a reflection completeness spec so a field added without a registry row is a red test instead of a silently-dropped setting (the #10845 bug class). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * refactor(settings): drive ToRuntimeSettings/ApplyRuntimeSettings from the field registry Behavior-preserving: ~350 hand-written per-field lines become two loops over runtimeSettingsFields, gated by a To->Apply->To round-trip spec. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * feat(settings): baseline-driven startup merge for persisted runtime settings ApplyRuntimeSettingsAtStartup compares the live config against DefaultRuntimeBaseline (option-less-run defaults incl. kong-injected flag defaults) instead of per-field == 0 guards. Fixes persisted lru_eviction_max_retries, tracing_max_items, agent_job_retention_days, memory_reclaimer_threshold, galleries and autoload flags being silently ignored at boot. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * fix(settings): registry-driven startup merge, applied before consumers loadRuntimeSettingsFromFile becomes a thin wrapper over ApplyRuntimeSettingsAtStartup and runs at the top of New(), before model configs capture app-level defaults. WithThreads stops eagerly resolving 0 so a persisted thread count survives restart while LOCALAI_THREADS still wins (#10845); the physical-core fallback moves after the merge. Also: run.go now injects the memory-reclaimer threshold unconditionally so the option-less boot matches DefaultRuntimeBaseline and a UI-saved threshold survives restart. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * refactor(settings): file watcher delegates to the registry merge; shared API-key merge Manual edits to runtime_settings.json now behave like a boot-time load (env still wins) instead of the inverted diverged-from-startup guard that ignored most manual edits. MergeAPIKeys dedups env keys in one place for the endpoint and the watcher. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * docs(settings): document unified runtime-settings precedence Document the single env/CLI > runtime_settings.json > defaults rule, applied identically at boot, on POST /api/settings, and on manual file edits, plus the two known limitations (default-valued env vars are indistinguishable from unset; API-changed fields hot-apply on the next restart only). Also add a completion debug log when the watcher applies runtime_settings.json. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 * test(settings): reset the global VRAM cap leaked by the round-trip spec The round-trip spec applies vram_budget=12GiB, whose post-loop hook installs a process-global default cap; without a reset every spec ordered after it runs under that phantom budget. Also drop a stale enumeration in the ApplyRuntimeSettings doc comment. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-fable-5 --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
113 lines
3.4 KiB
Go
113 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/alecthomas/kong"
|
|
"github.com/joho/godotenv"
|
|
"github.com/mudler/LocalAI/core/cli"
|
|
"github.com/mudler/LocalAI/core/config"
|
|
"github.com/mudler/LocalAI/internal"
|
|
"github.com/mudler/xlog"
|
|
|
|
_ "github.com/mudler/LocalAI/swagger"
|
|
)
|
|
|
|
func main() {
|
|
var err error
|
|
|
|
// Initialize xlog at a level of INFO, we will set the desired level after we parse the CLI options
|
|
xlog.SetLogger(xlog.NewLogger(xlog.LogLevel("info"), "text"))
|
|
|
|
// handle loading environment variables from .env files
|
|
envFiles := []string{".env", "localai.env"}
|
|
homeDir, err := os.UserHomeDir()
|
|
if err == nil {
|
|
envFiles = append(envFiles, filepath.Join(homeDir, "localai.env"), filepath.Join(homeDir, ".config/localai.env"))
|
|
}
|
|
envFiles = append(envFiles, "/etc/localai.env")
|
|
|
|
for _, envFile := range envFiles {
|
|
if _, err := os.Stat(envFile); err == nil {
|
|
xlog.Debug("env file found, loading environment variables from file", "envFile", envFile)
|
|
err = godotenv.Load(envFile)
|
|
if err != nil {
|
|
xlog.Error("failed to load environment variables from file", "error", err, "envFile", envFile)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actually parse the CLI options
|
|
k := kong.Must(&cli.CLI,
|
|
kong.Description(
|
|
` LocalAI is a drop-in replacement OpenAI API for running LLM, GPT and genAI models locally on CPU, GPUs with consumer grade hardware.
|
|
|
|
For a list of all available models run local-ai models list
|
|
|
|
Copyright: Ettore Di Giacinto
|
|
|
|
Version: ${version}
|
|
|
|
For documentation and support:
|
|
Documentation: https://localai.io/
|
|
Getting Started: https://localai.io/basics/getting_started/
|
|
GitHub Issues: https://github.com/mudler/LocalAI/issues
|
|
`,
|
|
),
|
|
kong.UsageOnError(),
|
|
kong.Vars{
|
|
"basepath": kong.ExpandPath("."),
|
|
// Per-user temp locations for ephemeral writable content. A fixed
|
|
// shared name under /tmp collides across accounts on multi-user hosts
|
|
// (notably macOS, where /tmp is the shared /private/tmp for everyone),
|
|
// failing startup with "mkdir /tmp/generated/content: permission
|
|
// denied". See cli.DefaultGeneratedContentPath.
|
|
"generatedcontentpath": cli.DefaultGeneratedContentPath(),
|
|
"uploadpath": cli.DefaultUploadPath(),
|
|
"galleries": config.DefaultGalleriesJSON,
|
|
"backends": config.DefaultBackendGalleriesJSON,
|
|
"version": internal.PrintableVersion(),
|
|
},
|
|
)
|
|
ctx, err := k.Parse(os.Args[1:])
|
|
if err != nil {
|
|
k.FatalIfErrorf(err)
|
|
}
|
|
|
|
// Pass Kong model to the completion command for dynamic script generation
|
|
cli.CLI.Completion.SetApplication(k.Model)
|
|
|
|
// Configure the logging level before we run the application
|
|
// This is here to preserve the existing --debug flag functionality
|
|
logLevel := "info"
|
|
if cli.CLI.Debug && cli.CLI.LogLevel == nil {
|
|
logLevel = "debug"
|
|
cli.CLI.LogLevel = &logLevel
|
|
}
|
|
|
|
if cli.CLI.LogLevel == nil {
|
|
cli.CLI.LogLevel = &logLevel
|
|
}
|
|
|
|
// Set xlog logger with the desired level and text format.
|
|
// xlog auto-enables log deduplication when output is a terminal.
|
|
var logOpts []xlog.LoggerOption
|
|
if cli.CLI.LogDedupLogs != nil {
|
|
if *cli.CLI.LogDedupLogs {
|
|
logOpts = append(logOpts, xlog.WithDedup())
|
|
} else {
|
|
logOpts = append(logOpts, xlog.WithoutDedup())
|
|
}
|
|
}
|
|
|
|
xlog.SetLogger(xlog.NewLogger(xlog.LogLevel(*cli.CLI.LogLevel), *cli.CLI.LogFormat, logOpts...))
|
|
|
|
// Run the thing!
|
|
err = ctx.Run(&cli.CLI.Context)
|
|
if err != nil {
|
|
xlog.Fatal("Error running the application", "error", err)
|
|
}
|
|
}
|