Wie es funktioniert
ProviderInterface ist der zentrale Vertrag (getName, getIdentifier, configure, chatCompletion, complete, embeddings, testConnection und Fähigkeitsprüfungen). Optionale Funktionen sind zuschaltbare Capability-Interfaces – VisionCapableInterface, StreamingCapableInterface, ToolCapableInterface, DocumentCapableInterface –, die per instanceof erkannt werden, während embeddings eine Kernmethode bleibt. AbstractProvider stellt gemeinsames Verhalten bereit, und jeder mitgelieferte Adapter erweitert es.
Die Registrierung ist attributgesteuert: Eine mit #[AsLlmProvider(priority: N)] markierte Klasse im Namespace Netresearch\NrLlm\ wird vom ProviderCompilerPass zur Container-Compile-Zeit automatisch mit nr_llm.provider getaggt (ADR-022). Provider bleiben privat; nichts löst sie über den Klassennamen auf – der Zugriff erfolgt über LlmServiceManager, aufgelöst über den von getIdentifier() zurückgegebenen Identifier. Die Priorität ist lediglich ein Hinweis auf die Reihenfolge. Fremde Provider außerhalb des Namespaces behalten den alten Services.yaml-Tag-Pfad.
Die drei Ebenen sind Extbase-Entities über tx_nrllm_provider, tx_nrllm_model und tx_nrllm_configuration. Eine Configuration referenziert ein Model, das einen Provider referenziert, dem die Verbindung gehört (endpoint_url, adapter_type, timeout, max_retries und api_key, gespeichert als Vault-UUID). Aufrufe laufen durch eine Middleware-Pipeline (ADR-026), geordnet nach Tag-Priorität: Guardrail (115), Telemetry (110), Idempotency (105), Cache (100), Budget (75), Fallback (50), Usage (25), CircuitBreaker (20).
FallbackMiddleware führt die primäre Konfiguration aus; bei einem wiederholbaren Fehlschlag läuft sie die FallbackChain der Konfiguration aus Geschwister-Konfigurations-Identifiern durch, überspringt nicht gefundene und inaktive, bis einer erfolgreich ist oder die Kette erschöpft ist (FallbackChainExhaustedException). Wiederholbar sind ProviderConnectionException, eine 429-ProviderResponseException oder CircuitOpenException. AbstractProvider::getHttpClient() authentifiziert über den HTTP-Client von nr-vault (vault->http()->withAuthentication(identifier, placement, options)); Provider ohne API-Key wie Ollama nutzen den rohen Factory-Client hinter einer expliziten SSRF-Host-Prüfung.
Netresearch\NrLlm\Provider\Contract\ProviderInterface
Zentraler Provider-Vertrag, den jeder Adapter implementiert – name, identifier, configure, chatCompletion, complete, embeddings, testConnection, Fähigkeitsprüfungen.
Netresearch\NrLlm\Provider\AbstractProvider
Gemeinsame Basis der sieben Adapter; speichert apiKeyIdentifier und baut in getHttpClient() den über den Vault authentifizierten HTTP-Client.
Netresearch\NrLlm\Attribute\AsLlmProvider
#[AsLlmProvider(priority)]-Marker; der ProviderCompilerPass taggt ihn automatisch mit nr_llm.provider, sodass kein Services.yaml-Eintrag nötig ist.
Netresearch\NrLlm\Domain\DTO\FallbackChain
Unveränderliche, normalisierte geordnete Liste von LlmConfiguration-Identifiern, die versucht werden, wenn die primäre fehlschlägt; flach (die eigene Kette eines Fallbacks wird ignoriert).
Netresearch\NrLlm\Provider\Middleware\FallbackMiddleware
Durchsetzung zur Laufzeit (Tag-Priorität 50): versucht die Kette bei wiederholbaren Fehlern erneut, überspringt inaktive/fehlende Konfigurationen, wirft FallbackChainExhaustedException, wenn alle fehlschlagen.
Netresearch\NrVault\Service\VaultServiceInterface
Löst den gespeicherten UUID-Identifier zum echten Secret auf und injiziert es zum Sendezeitpunkt; hält Klartext-Keys aus Code und Datenbank von nr-llm heraus.