index.d.ts: EmbeddingProviderConfig/EmbeddingGroupConfig (onSingleQuery, onBulkWrite, health), EmbeddingConfig für config.server().embedding (Roh-JSON von config.Server. Embedding) sowie die Status-Payloads von GET …/admin/embedding/status (Projekt- und Server-Scope, Zustände live|degraded|quarantined|offline, Breaker closed|open|half-open). VectorConfig.provider dokumentiert jetzt, dass dort auch ein Gruppenname stehen darf. schemas/config/embedding.schema.json: validierbares Schema des Server-Abschnitts (Enums für Policies/Distributionen, Go-Duration-Muster, Pflichtfelder, keine erfundenen Properties); Beispiel examples/server/embedding.yml, per scripts/validate-schemas.mjs mitgeprüft (npm test: 5 YAML gegen 17 Schemas). Quelle der Wahrheit: internal/config/server.go + internal/config/embedding_group.go (tibi-server). Typecheck: tsc --noEmit --strict über index.d.ts grün.
256 lines
9.2 KiB
JSON
256 lines
9.2 KiB
JSON
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"$id": "embedding.schema.json",
|
|
"title": "Tibi server config — embedding section (server-level, not project config)",
|
|
"description": "Der Abschnitt `embedding` aus der Server-config.yml (server.embedding): Provider + Failover-Gruppen + Gold-Datei-Pfad. Quelle der Wahrheit: internal/config/server.go und internal/config/embedding_group.go im tibi-server.",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"providers": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/provider"
|
|
}
|
|
},
|
|
"groups": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/group"
|
|
}
|
|
},
|
|
"goldenPath": {
|
|
"type": "string",
|
|
"description": "Verzeichnis der Gold-Dateien für die Mitglieds-Prüfung (Vorgabe: testdata/embedding-golden relativ zum Arbeitsverzeichnis). Erzeugen mit cmd/embed-probe-golden. Ohne verankerte Gold-Datei prüft die Gruppe nur gegen ihre Referenz."
|
|
}
|
|
},
|
|
"definitions": {
|
|
"duration": {
|
|
"type": "string",
|
|
"description": "Go-Duration, z. B. 120s, 800ms, 25s",
|
|
"pattern": "^[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)+$"
|
|
},
|
|
"provider": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"name"
|
|
],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"description": "Provider-Name; Sammlungen referenzieren ihn (oder eine Gruppe) über vector.provider."
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"native",
|
|
"flagembedding"
|
|
],
|
|
"description": "native = ONNX im Prozess (braucht -tags cgo_embedding), flagembedding = externer HTTP-Endpunkt. Ohne Angabe: native."
|
|
},
|
|
"model": {
|
|
"type": "string"
|
|
},
|
|
"modelPath": {
|
|
"type": "string",
|
|
"description": "ONNX-Modellverzeichnis (type: native)."
|
|
},
|
|
"dimensions": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"baseURL": {
|
|
"type": "string",
|
|
"description": "Embedding-Endpunkt (type: flagembedding)."
|
|
},
|
|
"apiKey": {
|
|
"type": "string"
|
|
},
|
|
"documentPrefix": {
|
|
"type": "string"
|
|
},
|
|
"queryPrefix": {
|
|
"type": "string"
|
|
},
|
|
"timeoutPerAttempt": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "flagembedding: HTTP-Timeout (Vorgabe 120s); native: Schranke je Embed-Aufruf (nur am Aufruf-/Stufen-Eintritt wirksam, ONNX-Runs sind nicht unterbrechbar). Ungültige oder nicht-positive Werte werden ignoriert (Warnung im Log)."
|
|
},
|
|
"slowThreshold": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Nur gruppenwirksam: langsamere Aufrufe zählen für lowest-latency als langsam."
|
|
},
|
|
"revision": {
|
|
"type": "string",
|
|
"description": "Gewichts-/Build-Tag (Datei-Hash, Quantisierung); fließt in die Modell-Identität ein (Gruppen-Prüfung, Query-Cache)."
|
|
},
|
|
"sparse": {
|
|
"type": "boolean",
|
|
"description": "false = Endpunkt/Modell liefert keine Sparse-Vektoren: native lädt die Sparse-Session nicht, flagembedding schweigt die einmalige Dense-only-Warnung; in einer Gruppe lehnt die Prüfung abweichende Sparse-Formen ab."
|
|
}
|
|
}
|
|
},
|
|
"group": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"name",
|
|
"members"
|
|
],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"description": "Gruppenname; darf kein Provider-Name sein und darf nur einmal vorkommen."
|
|
},
|
|
"description": {
|
|
"type": "string"
|
|
},
|
|
"members": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"uniqueItems": true,
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider-Namen der Gruppe. Alle Mitglieder müssen dieselbe Modell-Identität liefern (Dimensionen, Sparse-Unterstützung, revision)."
|
|
},
|
|
"onSingleQuery": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"policy": {
|
|
"type": "string",
|
|
"enum": [
|
|
"prefer-in-order",
|
|
"fastest-wins",
|
|
"round-robin",
|
|
"lowest-latency",
|
|
"weighted"
|
|
]
|
|
},
|
|
"preferredOrder": {
|
|
"description": "Bevorzugte Reihenfolge; als Komma-String oder YAML-Liste. Mitglieder, die fehlen, hängen in Config-Reihenfolge hinten an.",
|
|
"oneOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"timeoutPerAttempt": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Schranke je Versuch. Der bevorzugte Member läuft genau darin; Ausweich-Member bekommen max(Provider-Timeout, dieser Wert)."
|
|
},
|
|
"timeoutTotal": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Gesamt-Deadline je Aufruf; muss >= timeoutPerAttempt sein."
|
|
},
|
|
"autoFailback": {
|
|
"type": "boolean",
|
|
"description": "true (Vorgabe) = jeder Aufruf beginnt wieder beim bevorzugten Mitglied; false = bleibt beim letzten Gewinner."
|
|
},
|
|
"raceDelay": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Nur policy fastest-wins: Staffelung zwischen den Teilnehmern."
|
|
},
|
|
"raceMaxFanout": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Nur policy fastest-wins: maximale parallele Teilnehmer (0 = alle)."
|
|
},
|
|
"weights": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"description": "Nur policy weighted: relative Gewichte je Mitglied, positional zur members-Liste."
|
|
},
|
|
"latencyWindow": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"description": "Fenster für die EWMA-Latenz (lowest-latency)."
|
|
},
|
|
"retryAttempts": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"retryBackoff": {
|
|
"$ref": "#/definitions/duration"
|
|
},
|
|
"retryBackoffMax": {
|
|
"$ref": "#/definitions/duration"
|
|
},
|
|
"hedgeAfterSlow": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "prefer-in-order: nach dieser Dauer starten die übrigen Mitglieder parallel (Hedge)."
|
|
}
|
|
}
|
|
},
|
|
"onBulkWrite": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"distribution": {
|
|
"type": "string",
|
|
"enum": [
|
|
"round-robin",
|
|
"lowest-latency",
|
|
"weighted"
|
|
],
|
|
"description": "Verteilung der Batch-Ranges über die Mitglieder; ohne Angabe kein Sharding (serieller Schreibpfad). Jeder Range bleibt ganz auf einem Mitglied."
|
|
},
|
|
"maxConcurrentTotal": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"maxConcurrentPerEndpoint": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"description": "Pro Mitglied; lokale (native) Mitglieder sind auf 1 begrenzt."
|
|
},
|
|
"timeoutPerAttempt": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Bulk-Schranke je Versuch; pro Mitglied gilt max(Provider-Timeout, dieser Wert)."
|
|
},
|
|
"timeoutTotal": {
|
|
"$ref": "#/definitions/duration"
|
|
}
|
|
}
|
|
},
|
|
"health": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"checkInterval": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Abstand der Health-Probes. > 0 aktiviert zusätzlich den Late-Join: quarantänisierte Mitglieder (und offline Gruppen) werden gegen die aktuelle Referenz neu geprüft und kommen zurück, sobald sie passen. 0 = nur Neustart hilft."
|
|
},
|
|
"checkTimeout": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Schranke je Probe-Embed; die Rundenschranke beim Start skaliert mit der Zahl der Probe-Texte."
|
|
},
|
|
"unhealthyAfterFailures": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"healthyAfterSuccesses": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
},
|
|
"cooldownAfterUnhealthy": {
|
|
"$ref": "#/definitions/duration",
|
|
"description": "Pause, bevor ein offenes Mitglied wieder halb geöffnet wird (danach genügt Verkehr, kein Probe-Lauf)."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|