mirror of
https://github.com/mudler/LocalAI.git
synced 2026-10-02 19:14:38 -04:00
feat(systemone): register the decisions API on auth and instructions
Adds a default-on systemone route feature for the three /v1/systemone routes and an /api/instructions area for them. No MCP tool is added: the endpoints run inference and are not admin install/edit actions, and the route-map test still passes. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
1 parent
36846466e4
commit
b4852d62d2
5 files changed
+51
-2
No files matched your search
@@ -71,6 +71,11 @@ var RouteFeatureRegistry = []RouteFeature{
|
||||
// Detection
|
||||
{"POST", "/v1/detection", FeatureDetection},
|
||||
|
||||
// SystemOne decision API
|
||||
{"POST", "/v1/systemone", FeatureSystemOne},
|
||||
{"POST", "/v1/systemone/permute", FeatureSystemOne},
|
||||
{"POST", "/v1/systemone/separate", FeatureSystemOne},
|
||||
|
||||
// Face recognition
|
||||
{"POST", "/v1/face/verify", FeatureFaceRecognition},
|
||||
{"POST", "/v1/face/analyze", FeatureFaceRecognition},
|
||||
@@ -209,5 +214,6 @@ func APIFeatureMetas() []FeatureMeta {
|
||||
{FeatureVoiceRecognition, "Voice Recognition", true},
|
||||
{FeatureAudioTransform, "Audio Transform", true},
|
||||
{FeaturePIIFilter, "PII Analyze / Redact", true},
|
||||
{FeatureSystemOne, "SystemOne Decisions", true},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
. "github.com/mudler/LocalAI/core/http/auth"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("SystemOne feature registration", func() {
|
||||
It("gates the three decision routes behind one default-on API feature", func() {
|
||||
Expect(APIFeatures).To(ContainElement(FeatureSystemOne))
|
||||
|
||||
patterns := []string{}
|
||||
for _, route := range RouteFeatureRegistry {
|
||||
if route.Feature == FeatureSystemOne {
|
||||
Expect(route.Method).To(Equal("POST"))
|
||||
patterns = append(patterns, route.Pattern)
|
||||
}
|
||||
}
|
||||
Expect(patterns).To(ConsistOf("/v1/systemone", "/v1/systemone/permute", "/v1/systemone/separate"))
|
||||
|
||||
Expect(APIFeatureMetas()).To(ContainElement(FeatureMeta{Key: FeatureSystemOne, Label: "SystemOne Decisions", DefaultValue: true}))
|
||||
})
|
||||
})
|
||||
@@ -59,6 +59,7 @@ const (
|
||||
FeatureFaceRecognition = "face_recognition"
|
||||
FeatureVoiceRecognition = "voice_recognition"
|
||||
FeatureAudioTransform = "audio_transform"
|
||||
FeatureSystemOne = "systemone"
|
||||
// FeaturePIIFilter gates the synchronous PII analyze/redact service
|
||||
// (POST /api/pii/{analyze,redact}). Default ON like the other API
|
||||
// features; the admin-only events log is gated separately in-handler.
|
||||
@@ -78,7 +79,7 @@ var APIFeatures = []string{
|
||||
FeatureVAD, FeatureDetection, FeatureVideo, Feature3D, FeatureEmbeddings, FeatureSound,
|
||||
FeatureRealtime, FeatureModeration, FeatureRerank, FeatureTokenize, FeatureMCP, FeatureStores,
|
||||
FeatureFaceRecognition, FeatureVoiceRecognition, FeatureAudioTransform,
|
||||
FeaturePIIFilter,
|
||||
FeaturePIIFilter, FeatureSystemOne,
|
||||
}
|
||||
|
||||
// AllFeatures lists all known features (used by UI and validation).
|
||||
|
||||
@@ -105,6 +105,12 @@ var instructionDefs = []instructionDef{
|
||||
Tags: []string{"voice-recognition"},
|
||||
Intro: "Voice (speaker) recognition — the audio analog to /v1/face/*. Use /v1/voice/verify for 1:1 speaker comparison, /v1/voice/identify for 1:N match against the registered store, /v1/voice/{register,forget} to manage that store, /v1/voice/embed for a raw speaker-encoder vector, and /v1/voice/analyze for age / gender / emotion inferred from speech. Registrations are in-memory by default and lost on restart. Audio inputs accept URL, base64, or data-URI; /v1/embeddings remains text-only.",
|
||||
},
|
||||
{
|
||||
Name: "systemone",
|
||||
Description: "Typed decisions (choice, noul, score) over a state text with calibrated confidence",
|
||||
Tags: []string{"systemone"},
|
||||
Intro: "POST /v1/systemone answers every question in one pass; /v1/systemone/permute re-runs one choice question under n_perm option orders; /v1/systemone/separate answers each question in its own pass. Request: { model, state, questions: { <id>: { type: choice|noul|score, instructions, criteria } } }. The model must declare known_usecases: [systemone] (or token_classify for the zero-shot NER path); a config that declares no usecases keeps working. Responses carry per-question answers with confidence and probabilities plus token usage. The wire shape matches Ollama's /v1/systemone.",
|
||||
},
|
||||
{
|
||||
Name: "branding",
|
||||
Description: "Whitelabel the instance: configure name, tagline, logo, and favicon",
|
||||
|
||||
@@ -39,7 +39,7 @@ var _ = Describe("API Instructions Endpoints", func() {
|
||||
|
||||
instructions, ok := resp["instructions"].([]any)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(instructions).To(HaveLen(20))
|
||||
Expect(instructions).To(HaveLen(21))
|
||||
|
||||
// Verify each instruction has required fields and correct URL format
|
||||
for _, s := range instructions {
|
||||
@@ -82,6 +82,7 @@ var _ = Describe("API Instructions Endpoints", func() {
|
||||
"voice-library",
|
||||
"3d",
|
||||
"failover",
|
||||
"systemone",
|
||||
))
|
||||
})
|
||||
})
|
||||
@@ -136,6 +137,17 @@ var _ = Describe("API Instructions Endpoints", func() {
|
||||
Expect(string(body)).NotTo(ContainSubstring("/v1/3d/generations"))
|
||||
})
|
||||
|
||||
It("should advertise the SystemOne decisions API", func() {
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/instructions/systemone", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
app.ServeHTTP(rec, req)
|
||||
|
||||
Expect(rec.Code).To(Equal(http.StatusOK))
|
||||
body, _ := io.ReadAll(rec.Body)
|
||||
Expect(string(body)).To(ContainSubstring("POST /v1/systemone"))
|
||||
Expect(string(body)).To(ContainSubstring("known_usecases: [systemone]"))
|
||||
})
|
||||
|
||||
It("should return JSON fragment when format=json", func() {
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/instructions/chat-inference?format=json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
Reference in new issue
Block a user