← Gesamte Dokumentation
Produktivbetrieb

Im Produktivbetrieb

Die Standardwerte sind auf einen typischen SaaS-Kunden abgestimmt. Unten stehen die Stellschrauben, die Sie anfassen, wenn sich das Verkehrsprofil ändert – Rate Limiting, Retry-Richtlinie, Audit-Logging, Erreichbarkeitsprüfungen von Abhängigkeiten, Integration mit IHealthCheck, Idempotenz, Überschreiben von Prompt-Vorlagen und die BYOK-Verwaltung.

Rate Limiting für KI-Aufrufe

POST /richtextbox/ai und POST /richtextbox/ai/stream teilen sich einen Token-Bucket pro IP, damit ein einzelner außer Kontrolle geratener Tab Ihr Kontingent beim Anbieter nicht in Sekunden aufbraucht. Standard: 30 Aufrufe pro Minute und IP.

builder.Services.AddRichTextBox(opts =>
{
    opts.AiRateLimit       = 30;                          // calls per window
    opts.AiRateLimitWindow = TimeSpan.FromMinutes(1);     // window length
});

Setzen Sie AiRateLimit = 0, um es abzuschalten, oder ersetzen Sie es durch einen Limiter auf Redis-Basis:

builder.Services.AddSingleton<IRichTextBoxAiRateLimiter, RedisAiRateLimiter>();
builder.Services.AddRichTextBox();

HTTP-Retry bei vorübergehenden Fehlern des Anbieters

OpenAI / Anthropic / Azure OpenAI geben unter normaler Last 429 und 503 zurück. Die eingebauten Resolver wiederholen diese Requests (plus 502 / 504 und Verbindungsabbrüche) mit exponentiellem Backoff und vollem Jitter, begrenzt auf 30 Sekunden. Der Header Retry-After des Anbieters wird beachtet.

services.AddRichTextBoxOpenAiResolver(opts =>
{
    opts.ApiKey         = builder.Configuration["OpenAI:ApiKey"];
    opts.MaxRetryAttempts = 2;                              // 0 to disable
    opts.RetryBaseDelay   = TimeSpan.FromMilliseconds(500);
});

Idempotenzschlüssel

Jedes POST /richtextbox/ai, /ai/stream und /upload beachtet Idempotency-Key. Doppelte Wiederholungen spielen den zwischengespeicherten Body unverändert ab – keine doppelte Abrechnung, keine verwaisten Dateien. Streaming-Antworten spielen den gesamten SSE-Bytestrom Byte für Byte ab.

builder.Services.AddRichTextBox(opts =>
{
    opts.IdempotencyTtl = TimeSpan.FromHours(1);
    opts.IdempotencyPruneInterval = TimeSpan.FromMinutes(5);
});

Hosts mit mehreren Instanzen: Registrieren Sie einen IIdempotencyStore auf Redis-Basis statt des standardmäßigen In-Memory-Speichers. Durch die native TTL können Sie die periodische Bereinigung abschalten.

Audit-Logging für Sicherheit

Jede sicherheitsrelevante Ablehnung erzeugt ein strukturiertes LogWarning unter der Kategorie RichTextBox.Audit mit einer stabilen EventId:

EventIdNameWird ausgelöst, wenn
8001LicenseInvalidEin Endpoint einen Request abgelehnt hat, weil die .lic-Datei fehlte oder ungültig war.
8101UploadMagicByteMismatchDie Magic Bytes nicht zur angegebenen Dateiendung passen.
8102UploadRejectedByValidatorEin IUploadValidator Reject zurückgegeben hat.
8103UploadInvalidExtensionEin Upload abgelehnt wurde, weil er außerhalb der Allowlist liegt.
8104UploadOversizeMaxUploadBytes überschritten wurde.
8201AiRequestOversizeDer KI-Body MaxRequestBytes überschritten hat.
8202AiRateLimitExceededDer Aufrufer das KI-Rate-Limit pro IP überschritten hat.
8203AiResolverExceptionDer KI-Resolver eine Ausnahme geworfen hat; protokolliert mit Korrelations-ID.
8204AiKeyVaultMissDer BYOK-Tresor keinen Schlüssel zurückgegeben hat.
8205AiKeyVaultHitDer BYOK-Tresor einen Schlüssel zurückgegeben hat (KeyId wird protokolliert, das Geheimnis nie).
8206AiResponseFilterMatchedEin IRichTextBoxAiResponseFilter die Antwort verändert hat.

Audit-Ereignisse in einen eigenen Stream leiten

Mit IRichTextBoxAuditSink können regulierte Workloads (HIPAA / PCI / SOC2) nur die Audit-Ereignisse an ein Write-Once-Ziel leiten – Splunk HEC, S3 mit Object Lock, eine reine Audit-Datenbank. Mitgeliefert wird JsonLinesAuditSink für den Offline- bzw. Einzelinstanzbetrieb:

builder.Services.AddRichTextBox();
builder.Services.AddJsonLinesAuditSink("/var/log/myapp/rtb-audit.jsonl");
Verhalten. Begrenzter Channel + Abarbeitung im Hintergrund; RecordAsync blockiert nie. Läuft die Warteschlange über, werden Ereignisse verworfen und in der Metrik DroppedCount gezählt. Mehrere Sinks lassen sich einfach registrieren – kombinieren Sie JsonLines ohne Mehraufwand mit einem Splunk-Sink in Echtzeit.

Erreichbarkeitsprüfungen für Abhängigkeiten

Über optionale Begleitschnittstellen kann jede Abhängigkeit von RichTextBox melden, ob ihr zugrunde liegender Dienst erreichbar ist. Der Endpoint /richtextbox/health zeigt das Ergebnis neben dem Lizenzstatus an:

SchnittstelleEingebaute ImplementierungenPrüfziel
IRichTextBoxAiResolverProbeOpenAI, Azure OpenAI (kostenlos); Wrapper AnthropicResolverWithProbe (POST mit wenigen Tokens)GET /v1/models / GET /openai/deployments / POST /v1/messages mit max_tokens=1
IIdempotencyStoreProbeEigener Redis- / SQL-Speicher (von Ihnen implementiert)PING / SELECT 1
IRichTextBoxUploadStoreProbeEigener Speicher für S3 / Azure Blob / CloudinaryHEAD auf den Bucket / list-objects --max-items 1
builder.Services.AddRichTextBox(opts =>
{
    opts.AiResolverHealthProbeEnabled        = true;
    opts.AiResolverHealthProbeTimeout        = TimeSpan.FromSeconds(3);
    opts.AiResolverHealthProbeCacheTtl       = TimeSpan.FromSeconds(30);

    opts.IdempotencyStoreHealthProbeEnabled  = true;
    opts.UploadStoreHealthProbeEnabled       = true;
});

Eine Cache-TTL pro Prüfung schützt vor dauerndem Abfragen durch den Load Balancer – ein Balancer, der /health alle 5 Sekunden aufruft, würde sonst 12 Prüfungen pro Minute auslösen, auch wenn Prüfungen echtes Geld kosten.

Standardintegration mit IHealthCheck

Für Hosts mit Microsoft.Extensions.Diagnostics.HealthChecks registrieren Sie den Adapter, und der Status von RichTextBox erscheint neben Ihren anderen Prüfungen – kein paralleler Überwachungsweg:

builder.Services.AddRichTextBox();
builder.Services.AddHealthChecks()
.AddRichTextBox(name: "richtextbox", failureStatus: HealthStatus.Unhealthy, tags: new[]  { "ready" } );

app.MapHealthChecks("/health");

Gibt Healthy zurück, wenn Lizenz und alle maßgeblichen Prüfungen bestehen, sonst Unhealthy mit einer Beschreibung der fehlgeschlagenen Abhängigkeit. HealthCheckResult.Data spiegelt die JSON-Daten von /richtextbox/health.

BYOK – API-Schlüssel pro Mandant

SaaS-Hosts mit mehreren Mandanten rechnen KI-Verkehr über IAiKeyVault + IAiKeyVaultAdmin auf das eigene Anbieterkonto jedes Mandanten ab. Das Paket enthält eine In-Memory-Referenzimplementierung; Produktivumgebungen setzen auf Azure Key Vault, Redis oder einen echten SQL-Speicher.

Den vollständigen Vertrag, die REST-Endpoints für die Verwaltung und Referenzimplementierungen (Redis, Azure Key Vault, verschlüsselt auf der Festplatte mit FileBackedAiKeyVault) finden Sie auf der eigenen Seite zum BYOK-Schlüsseltresor.

Kostenbuch pro Aufruf

IRichTextBoxAiCostSink erzeugt pro KI-Aufruf ein AiUsageRecord – Anbieter, Modell, Modus, Tokens (Eingabe / Ausgabe / gesamt), Latenz, Status, KeyId. Leiten Sie es zur Weiterberechnung an Mandanten an Ihr Abrechnungssystem weiter:

builder.Services.AddSingleton<IRichTextBoxAiCostSink, MyBillingApiCostSink>();

Für Mandanten mit viel Verkehr umhüllen Sie ihn mit dem puffernden Sink, sodass der innere Sink pro Intervall ein gebündeltes Flush erhält statt eines HTTP- oder SQL-Aufrufs pro KI-Request. Implementiert Ihr innerer Sink auch IRichTextBoxAiCostBatchSink, leitet der Wrapper über RecordBatchAsync – ein INSERT statt N.

builder.Services.AddBufferingAiCostSink<MyBillingApiCostSink>(
    flushInterval: TimeSpan.FromSeconds(30),
    maxBatchSize:  500);

Filtern der Ausgabe – Schwärzen personenbezogener Daten, Blockieren von Inhalten

IRichTextBoxAiResponseFilter läuft nach dem Resolver, aber bevor die Antwort gesendet wird. Die Referenzimplementierung RegexAiResponseFilter deckt ~80% der praktischen Schwärzung personenbezogener Daten ab:

var emailMask = new Regex(@"[\w.+-]+@[\w-]+\.[\w.-]+");
var ssnMask   = new Regex(@"\b\d{3}-\d{2}-\d{4}\b");

builder.Services.AddSingleton<IRichTextBoxAiResponseFilter>(
new RegexAiResponseFilter(
        (emailMask, "[email-redacted]"),
        (ssnMask,   "[ssn-redacted]")));

Bei Streaming-Antworten puffert das Framework die Tokens auf dem Server, wenn Filter registriert sind (Standard BufferStreamingForFilters = true), damit ein regulärer Ausdruck für Kreditkarten, der sich über mehrere Deltas erstreckt, tatsächlich greift.

Prompt-Vorlagen überschreiben

Mit IRichTextBoxPromptTemplateProvider überschreiben Sie die System-Prompts pro Modus, die die eingebauten Resolver senden. Mit der Decorator-Basisklasse PromptTemplateProviderBase überschreiben Sie nur die Methode(n), die Sie brauchen:

public sealed class FormalTonePromptProvider : PromptTemplateProviderBase
{
    public override string BuildSystemPrompt(RichTextBoxAiRequest request, string? operatorSuffix)
        => base.BuildSystemPrompt(request, operatorSuffix)
         + "\n\nAlways reply in formal British English; avoid contractions.";
}

Für einzelne Anpassungen eines Modus ohne vollständigen Provider verwenden Sie das Dictionary:

services.AddRichTextBoxOpenAiResolver(opts =>
{
    opts.ApiKey = "sk-...";
    opts.SystemPromptOverridesByMode["proofread"] =
        "You are a hyper-pedantic copy-editor for legal documents.";
});

Prüfung auf Prompt Injection

IRichTextBoxAiPolicy ist die Schranke, die die KI-Endpoints befragen, bevor sie den Resolver aufrufen. Die eingebaute DefaultPromptInjectionPolicy lehnt gängige Jailbreak-Vorlagen ab („ignore previous instructions“, „you are now DAN“ usw.). Ergänzen Sie weitere Richtlinien für das Schwärzen personenbezogener Daten oder Allowlists für Modi pro Mandant.

builder.Services.AddSingleton<IRichTextBoxAiPolicy, DefaultPromptInjectionPolicy>();
builder.Services.AddSingleton<IRichTextBoxAiPolicy, MyTenantPolicy>();

Verteiltes Tracing (OpenTelemetry)

Jeder KI-Aufruf, DOCX-Export und Upload erzeugt einen Span über die ActivitySource RichTextBox.AspNetCore. Abonnieren Sie sie in der Konfiguration Ihres Tracer-Providers:

builder.Services.AddOpenTelemetry().WithTracing(t => t
.AddSource(RichTextBoxDiagnostics.SourceName)   // "RichTextBox.AspNetCore"
.AddAspNetCoreInstrumentation()
.AddOtlpExporter());

Validierung der Optionen beim Start

RichTextBoxOptionsValidator + AiResolverOptionsValidator<T> laufen bei der ersten Auflösung von IOptions.Value – bevor der Host den ersten Request annimmt. Eine fehlerhafte Konfiguration (vergessener /, negatives Byte-Limit, Heartbeat > Timeout, fehlender API-Schlüssel, fehlendes Azure-Deployment) wirft beim Start eine OptionsValidationException, sodass Deployments deutlich fehlschlagen.

Keine Verdrahtung nötig. Die Validatoren registrieren sich automatisch über AddRichTextBox().

Ergänzende Dokumentation

BYOK-Schlüsseltresor·KI-Anbieter & Streaming·Cloud-Upload-Anbieter·Barrierefreiheit