mirror of
https://github.com/mudler/LocalAI.git
synced 2026-06-21 07:08:50 -04:00
feat(config): add model alias field and self-validation
Add ModelConfig.Alias (yaml: alias), IsAlias(), and an alias short-circuit at the top of Validate() that rejects self-reference and forbids setting backend/parameters.model on a pure-redirect alias. Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
@@ -37,6 +37,12 @@ type ModelConfig struct {
|
||||
schema.PredictionOptions `yaml:"parameters,omitempty" json:"parameters,omitempty"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
|
||||
// Alias, when set, makes this config a pure redirect: every request for
|
||||
// Name is served by the model named here. All other fields are ignored.
|
||||
// The target must be an existing, non-alias model (enforced at load and
|
||||
// at create/swap time). See docs/content for Model Aliases.
|
||||
Alias string `yaml:"alias,omitempty" json:"alias,omitempty"`
|
||||
|
||||
F16 *bool `yaml:"f16,omitempty" json:"f16,omitempty"`
|
||||
Threads *int `yaml:"threads,omitempty" json:"threads,omitempty"`
|
||||
Debug *bool `yaml:"debug,omitempty" json:"debug,omitempty"`
|
||||
@@ -391,6 +397,10 @@ func (c *ModelConfig) HasRouter() bool {
|
||||
return len(c.Router.Candidates) > 0
|
||||
}
|
||||
|
||||
// IsAlias reports whether this config is a pure redirect to another model.
|
||||
// Value receiver so it is callable on non-addressable config values too.
|
||||
func (c ModelConfig) IsAlias() bool { return c.Alias != "" }
|
||||
|
||||
// @Description PII filtering configuration. PII redaction is per-model so
|
||||
// that local models don't pay the latency or behaviour change of regex
|
||||
// scanning, while cloud-bound traffic (cloud-proxy backend) can default to
|
||||
@@ -1243,6 +1253,22 @@ func (cfg *ModelConfig) SetDefaults(opts ...ConfigLoaderOption) {
|
||||
}
|
||||
|
||||
func (c *ModelConfig) Validate() (bool, error) {
|
||||
// An alias is a pure redirect: validate only its own shape here. Target
|
||||
// existence and the no-chain rule need the full config set, so the loader
|
||||
// (load-time) and the create/swap endpoints enforce those.
|
||||
if c.IsAlias() {
|
||||
if c.Name == "" {
|
||||
return false, fmt.Errorf("alias config requires a name")
|
||||
}
|
||||
if c.Alias == c.Name {
|
||||
return false, fmt.Errorf("alias %q cannot point to itself", c.Name)
|
||||
}
|
||||
if c.Backend != "" || c.Model != "" {
|
||||
return false, fmt.Errorf("alias config %q must not set backend or parameters.model: an alias is a pure redirect", c.Name)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
downloadedFileNames := []string{}
|
||||
for _, f := range c.DownloadFiles {
|
||||
downloadedFileNames = append(downloadedFileNames, f.Filename)
|
||||
|
||||
@@ -787,3 +787,32 @@ var _ = Describe("pattern detector config", func() {
|
||||
Expect(err).To(MatchError(ContainSubstring("pattern \"EMAILish\"")))
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("ModelConfig alias", func() {
|
||||
It("reports IsAlias when alias is set", func() {
|
||||
c := ModelConfig{Name: "gpt-4", Alias: "my-llama-3"}
|
||||
Expect(c.IsAlias()).To(BeTrue())
|
||||
Expect(ModelConfig{Name: "real"}.IsAlias()).To(BeFalse())
|
||||
})
|
||||
|
||||
It("validates a minimal alias config", func() {
|
||||
c := ModelConfig{Name: "gpt-4", Alias: "my-llama-3"}
|
||||
ok, err := c.Validate()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ok).To(BeTrue())
|
||||
})
|
||||
|
||||
It("rejects an alias pointing to itself", func() {
|
||||
c := ModelConfig{Name: "loop", Alias: "loop"}
|
||||
ok, err := c.Validate()
|
||||
Expect(ok).To(BeFalse())
|
||||
Expect(err).To(MatchError(ContainSubstring("itself")))
|
||||
})
|
||||
|
||||
It("rejects an alias that also sets a backend", func() {
|
||||
c := ModelConfig{Name: "gpt-4", Alias: "my-llama-3", Backend: "llama-cpp"}
|
||||
ok, err := c.Validate()
|
||||
Expect(ok).To(BeFalse())
|
||||
Expect(err).To(MatchError(ContainSubstring("pure redirect")))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user