Konfiguration¶
Alle Einstellungen befinden sich in der Erweiterungskonfiguration: Admin Tools → Settings → Extension Configuration → nt_ai.
Werte lassen sich auch je Umgebung über den Standard-TYPO3-Mechanismus in config/system/settings.php überschreiben:
Für Geheimnisse können Umgebungsvariablen-Platzhalter direkt im Erweiterungskonfigurationsformular verwendet werden:
provider.anthropic.apiKey = %env(NT_AI_ANTHROPIC_KEY)%
provider.openai.apiKey = %env(NT_AI_OPENAI_KEY)%
nt-ai löst diese zur Laufzeit über getenv() auf.
Modellnamen aus der Umgebung¶
Modellnamen verstehen denselben Platzhalter. Ein Projekt kann sie damit aus der versionierten config/system/settings.php heraushalten und das Modell wechseln, indem es eine Umgebungsvariable ändert — ohne Commit und ohne Deployment:
// config/system/settings.php (Auszug)
'EXTENSIONS' => [
'nt_ai' => [
'provider' => [
'openai' => [
'apiKey' => '%env(NT_AI_OPENAI_KEY)%',
'model' => '%env(AI_MODEL_OPENAI)%',
],
],
],
],
Das gilt für die Modell-Einstellung jedes Anbieters und für tts.model. Der Platzhalter muss den ganzen Wert bilden, der Variablenname darf A–Z, 0–9 und _ enthalten. Die Variable muss für PHPs getenv() sichtbar sein — gesetzt vom Webserver oder Container oder aus einer .env geladen, etwa über helhum/dotenv-connector.
Ein bewusster Unterschied zu den API-Schlüsseln: Ist die Variable leer oder fehlt sie, gilt der unten genannte Standard des Anbieters, kein leerer Wert. Ein fehlender API-Schlüssel macht einen Anbieter zu Recht unverfügbar. Ein leerer Modellname dagegen ginge an den Anbieter und ließe jeden Aufruf scheitern — ein vergessener ENV-Eintrag soll die KI-Funktionen nicht lahmlegen. Derselbe Rückfall gilt für ein im Backend leer gespeichertes Modellfeld.
Verfügbar ab 1.15.0. Wörtliche Modellnamen funktionieren unverändert weiter.
Anbieter-Einstellungen¶
provider.default legt fest, welcher Anbieter verwendet wird, wenn bei einem Aufruf kein Anbieter angegeben ist. Mögliche Werte: anthropic, openai, gemini, deepseek, mistral, groq, ollama.
Anthropic Claude¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.anthropic.apiKey |
string | (leer) | API-Schlüssel von console.anthropic.com. Erforderlich zur Nutzung von Claude. Unterstützt %env(VAR)%-Platzhalter. |
provider.anthropic.model |
string | claude-sonnet-4-5 |
Modell-Bezeichner. Beispiele: claude-opus-4-5, claude-haiku-4-5. Vision wird bei allen Claude-3+- und 4+-Modellen unterstützt. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.anthropic.baseUrl |
string | https://api.anthropic.com/v1 |
Nur überschreiben, wenn Anthropic über eine eigene Infrastruktur als Proxy betrieben wird. |
OpenAI¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.openai.apiKey |
string | (leer) | API-Schlüssel von platform.openai.com. Erforderlich zur Nutzung von OpenAI. |
provider.openai.model |
string | gpt-4o-mini |
Beispiele: gpt-4o, gpt-4o-mini, gpt-4-turbo. Für die Alt-Text-Generierung ein Vision-Modell verwenden (gpt-4o, gpt-4o-mini). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.openai.baseUrl |
string | https://api.openai.com/v1 |
Überschreiben für Azure OpenAI, OpenRouter, LM Studio oder andere OpenAI-API-kompatible Endpunkte. |
Google Gemini¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.gemini.apiKey |
string | (leer) | API-Schlüssel von aistudio.google.com. Erforderlich zur Nutzung von Gemini. |
provider.gemini.model |
string | gemini-2.0-flash |
Beispiele: gemini-2.5-pro, gemini-2.0-flash, gemini-1.5-flash. Alle aufgeführten Modelle unterstützen Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.gemini.baseUrl |
string | https://generativelanguage.googleapis.com/v1beta |
Überschreiben bei Proxy-Setups. |
DeepSeek¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.deepseek.apiKey |
string | (leer) | API-Schlüssel von platform.deepseek.com. Erforderlich zur Nutzung von DeepSeek. |
provider.deepseek.model |
string | deepseek-chat |
deepseek-chat = DeepSeek-V3 (allgemein), deepseek-reasoner = R1 (Chain-of-Thought). Keines der Modelle unterstützt Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.deepseek.baseUrl |
string | https://api.deepseek.com/v1 |
Überschreiben bei Proxy-Setups. |
Mistral AI¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.mistral.apiKey |
string | (leer) | API-Schlüssel von console.mistral.ai. |
provider.mistral.model |
string | mistral-small-latest |
Beispiele: mistral-large-latest, pixtral-large-latest (Vision). Vision ist nur bei pixtral-*-Modellen verfügbar. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.mistral.baseUrl |
string | https://api.mistral.ai/v1 |
Überschreiben bei Proxy-Setups. |
Groq¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.groq.apiKey |
string | (leer) | API-Schlüssel von console.groq.com. |
provider.groq.model |
string | llama-3.3-70b-versatile |
Beispiele: llama-3.1-8b-instant, gemma2-9b-it. Groq unterstützt kein Vision. Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
provider.groq.baseUrl |
string | https://api.groq.com/openai/v1 |
Überschreiben bei Proxy-Setups. |
Ollama (lokal)¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
provider.ollama.baseUrl |
string | http://localhost:11434 |
URL der Ollama-Instanz. Bei getrennten Containern für TYPO3 und Ollama die container-interne URL verwenden (z. B. http://host.docker.internal:11434). |
provider.ollama.model |
string | llama3.2 |
Lokal installierter Modellname. Für Vision-Funktionen zuerst ein multimodales Modell installieren: ollama pull llama3.2-vision Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
KI-Foundation-Extensions (optional)¶
Seit 1.22.0. Statt eines eingebauten Anbieters kann nt_ai seine Anfragen an eine KI-Foundation-Extension übergeben. API-Schlüssel, Modell, Budgets und Protokoll werden dann dort verwaltet; die provider.*-Einstellungen oben greifen nicht.
provider.default |
Voraussetzung | Konfiguriert in |
|---|---|---|
aim |
b13/aim |
Backend-Modul von AiM (Anbieter-Konfigurationen) |
nr_llm |
netresearch/nr-llm |
Backend-Modul von nr_llm (Standard-Konfiguration) |
Eine Brücke gibt es nur, solange die jeweilige Extension installiert ist, und sie gilt nur dann als verfügbar, wenn dort ein nutzbarer Anbieter eingerichtet ist.
Grenzen: Massenläufe gehen über eine Brücke nacheinander statt parallel; eine Anfrage trägt ein Bild; Bildanfragen über nr_llm (0.40) laufen an dessen Budget und Telemetrie vorbei; die Kostenschätzung im Token-Widget kennt nur Modelle aus der Preistabelle von nt_ai. Beide Foundations sind noch vor Version 1.0 — nach einem Update dort zuerst eine Alt-Text-Erzeugung testen, bevor geplante Läufe darauf bauen.
Verhalten¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
behavior.timeout |
integer (Sekunden) | 60 |
Maximale Wartezeit für KI-Anfragen. Bei sehr langsamen lokalen Modellen erhöhen. |
behavior.maxTokens |
integer | 2048 |
Maximale Token pro Antwort. Gilt für alle Anbieter. |
behavior.logRequests |
boolean | aus | Wenn aktiv, wird jeder KI-Aufruf über den Standard-TYPO3-Logger protokolliert. Hilfreich zum Debuggen, kann jedoch sensible Prompt-Inhalte in Log-Dateien schreiben. Im Produktivbetrieb deaktiviert lassen. |
behavior.defaultLanguage |
string (ISO 639-1) | en |
Wird verwendet, wenn bei einem Aufruf keine Sprache angegeben ist. Beeinflusst Inhaltserstellung, Übersetzungen und Alt-Texte. |
Alt-Text-Anpassung¶
Diese Einstellungen formen die von der KI erzeugten Alt-Texte so, dass sie zur Tonalität und Barrierefreiheitsrichtlinie Ihrer Website passen. Die Einstellungen gelten für jede Alt-Text-Generierung, einschließlich Massen-CLI-Läufen und den „Alt-Text generieren"-Schaltflächen.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
altText.customInstructions |
mehrzeiliger Text | (leer) | Freiformige zusätzliche Regeln für die KI. Eine Anweisung pro Zeile. Werden wörtlich an den System-Prompt angehängt. |
altText.maxLength |
integer | 125 |
Weiche Obergrenze für die Alt-Text-Länge in Zeichen. 0 deaktiviert die Begrenzung. Die KI wird angewiesen, das Limit einzuhalten; die Ausgabe wird zusätzlich hart an Wortgrenzen gekürzt, falls das Modell es überschreitet. WCAG-/Screenreader-Best-Practice liegt bei ca. 125 Zeichen. |
altText.style |
enum | concise |
concise — ein kurzer Satz. descriptive — 1–2 Sätze. detailed — 2–3 Sätze, geeignet für Diagramme und Inhaltsbilder. |
altText.forbidImagePrefix |
boolean | an | Entfernt Formulierungen wie „Bild von…", „Abbildung zeigt…", „Image of…" aus dem Prompt und defensiv aus der Antwort. Screenreader kündigen Grafiken bereits an, solche Präfixe sind daher überflüssig. |
altText.includeDetectedText |
boolean | an | Die KI transkribiert sichtbaren Text im Bild (Schilder, Screenshots, Beschriftungen, Verpackungen). Wichtig für die Barrierefreiheit — Text in Bildern ist für Screenreader-Nutzer sonst nicht zugänglich. |
altText.tone |
string | neutral, factual |
Freiformige Tonbeschreibung. Beispiele: friendly, casual (Blogs), marketing, enthusiastic (Landingpages), technical, precise (Dokumentation). |
altText.brandContext |
string (max. 500 Zeichen) | (leer) | Ein kurzer Hinweis zu Ihrer Website oder Marke, der jeder Alt-Text-Anfrage beigefügt wird. Nützlich für kontextsensitive Beschreibungen. |
Strikte Alt-Text-Richtlinie — deutsches Kunstmuseum
altText.style = descriptive
altText.maxLength = 200
altText.tone = neutral, sachlich
altText.brandContext = Museum für moderne Kunst. Bildbeschreibungen für ein Fachpublikum, Künstlernamen nur wenn klar erkennbar.
altText.customInstructions:
Bei Kunstwerken: Stil, Material und ungefähre Epoche nennen.
Personen nur als "Besucher", "Mitarbeiter" o.ä. bezeichnen.
Texttafeln und Beschriftungen wörtlich übernehmen.
Alt-Text beim Upload¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
altText.generateOnUpload |
boolean | aus | Alt-Text erzeugen, sobald ein neues Bild ankommt. Synchron: Ein Upload dauert etwa 2–5 Sekunden länger. Gefüllt wird nur die Standardsprache, Übersetzungen kommen über die Metadaten-Übersetzung von nt-lingua. |
altText.generateOnUploadSource |
enum | all |
Welche neuen Dateien zählen, siehe unten. |
altText.generateOnUploadLimit |
integer | 0 (unbegrenzt) |
Höchstzahl an Alt-Texten pro Anfrage oder Planer-Lauf. Begrenzt die Kosten, wenn viele Dateien auf einmal ankommen. Was darüber hinausgeht, bleibt ohne Alt-Text und wird einmal als Warnung protokolliert; nachholen lässt es sich gesammelt mit vendor/bin/typo3 nt_ai:generate-alt-texts. |
TYPO3 meldet eine neue Datei auf zwei Wegen, und altText.generateOnUploadSource legt fest, welcher zählt:
all— jede neu erfasste Datei, wie vor 1.16.0. Dazu gehören neben Uploads auch Dateien, die TYPO3 nur auf der Platte findet: per SFTP oder rsync kopiert und dann vom Planer „Dateiliste: Speicherindex aktualisieren" erfasst, oder sobald jemand den Ordner in der Dateiliste öffnet. Jede dieser Dateien kostet einen KI-Aufruf.backend— nur Dateien, die im Backend hochgeladen werden. Auf den Server kopierte Dateien, Importe auf der Kommandozeile und Uploads aus Frontend-Formularen bleiben außen vor.
Wo Dateien auch auf anderem Weg als über das Backend auf den Server kommen, ist backend die richtige Wahl.
Audit-Einstellungen¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
audit.enabled |
boolean | an | Hauptschalter für das Barrierefreiheits-Audit-Backend-Modul. |
audit.autoOnSave |
boolean | aus | Wenn aktiv, wird nach jedem Speichern einer Seite im Backend automatisch ein Audit ausgelöst (durch audit.autoCooldown ratenbegrenzt). |
audit.autoCooldown |
integer (Sekunden) | 120 |
Mindestabstand zwischen automatischen Audits für dieselbe Seite. Verhindert Audit-Stürme bei schnellem Speichern durch Redakteure. |
audit.aiRules |
boolean | an | Legt fest, ob KI-gestützte Audit-Regeln ausgeführt werden. Bei Deaktivierung laufen nur deterministische regelbasierte Prüfungen. KI-Regeln werden auch automatisch übersprungen, wenn kein Anbieter konfiguriert ist. |
audit.retentionDays |
integer (Tage) | 90 |
Audit-Berichte, die älter als dieser Wert sind, können über den Standard-TYPO3-Garbage-Collection-Task gelöscht werden. 0 deaktiviert die Bereinigung. |
audit.maxReportsPerPage |
integer | 10 |
Maximale Anzahl gespeicherter Berichte pro Seite. Ältere Berichte werden nach jedem neuen Audit-Lauf automatisch bereinigt. |
audit.httpAuthUser |
string | leer | Seit 1.21.0. Benutzername für Websites hinter HTTP-Basic-Auth (Staging). Der Audit meldet sich damit beim Abruf der eigenen Seiten an. Auch %env(NAME)%. |
audit.httpAuthPassword |
string | leer | Seit 1.21.0. Passwort dazu; am besten als %env(NAME)%. Wird nur an die eigene Website gesendet. |
audit.explainPrompt |
mehrzeiliger Text | (integriert) | Benutzerdefinierte Prompt-Vorlage für KI-generierte Befund-Erläuterungen. Verfügbare Platzhalter: {ruleId}, {severity}, {message}, {wcagReference}, {snippet}. |
Barrierefreiheitserklärung¶
Angaben für den Reiter „Erklärung" im Audit-Modul, der aus den Audit-Daten einen Entwurf einer Erklärung zur Barrierefreiheit erzeugt (siehe Benutzerhandbuch → „Barrierefreiheitserklärung erstellen").
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
declaration.targetPageUid |
integer | 0 |
Zielseite, auf der die Erklärung veröffentlicht wird. 0 = automatisch die Seite mit dem Slug /barrierefreiheit. |
declaration.organisation |
string | (leer) | Name der Organisation in der Erklärung. Leer = Website-Titel aus der Site-Konfiguration. |
declaration.feedbackContact |
Text | (leer) | Ansprechpartner für Barrierefreiheits-Feedback (Name, E-Mail, Telefon). Pflichtangabe der Erklärung. |
declaration.enforcementBody |
Text | (leer) | Zuständige Durchsetzungs-/Schlichtungsstelle (für Unternehmen unter BFSG i. d. R. die Marktüberwachungsstelle der Länder). |
declaration.enforcementUrl |
string | (leer) | Link zur zuständigen Stelle (optional). |
declaration.measures |
Text | (integriert) | Bereits umgesetzte Maßnahmen, eine pro Zeile oder mit \| getrennt. Installierte Schwester-Erweiterungen (nt-lingua) und das nt-ai-Audit werden automatisch ergänzt. |
Publishing Quality Gate¶
Warnt beim Veröffentlichen einer Seite vor offenen Barrierefreiheits-Findings oder blockiert die Veröffentlichung, bis kritische Punkte behoben sind. Das Gate nutzt den zuletzt gespeicherten Audit-Bericht der Seite — daher audit.autoOnSave aktiviert lassen, damit der Bericht aktuell bleibt. Ablauf: beheben → speichern (re-Audit) → Bericht aktualisiert → Veröffentlichen erlaubt.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
audit.qualityGate |
Optionen (off/warn/block) |
off |
warn: Flash-Warnung beim Veröffentlichen. block: Veröffentlichen wird verhindert (Seite bleibt versteckt), solange das Gate nicht bestanden ist. |
audit.qualityGateSeverity |
Optionen (error/warning) |
error |
Ab welchem Schweregrad das Gate greift. error = nur kritische Fehler, warning = Fehler und Warnungen. |
audit.qualityGateScope |
Optionen (onPublish/onSave) |
onPublish |
onPublish: nur beim Sichtbarschalten (hidden=0). onSave: bei jedem Speichern einer nicht versteckten Seite. |
audit.qualityGateAdminBypass |
boolean | an | Administratoren dürfen trotz Findings veröffentlichen (erhalten nur eine Warnung). |
Für Pipelines: nt_ai:audit --fail-on=error (bzw. warning) liefert Exit-Code ≠ 0 bei Findings — nutzbar als CI/CD-Gate.
PDF-Barrierefreiheit (Upload-Gate)¶
Prüft PDFs beim Backend-Upload auf Barrierefreiheit (getaggtes PDF, Textebene, Dokumentsprache, Titel, Alternativtexte …) und warnt oder blockiert je nach Modus. Unabhängig vom Modus wird bei jedem Backend-PDF-Upload ein Bericht für das Modul Medien → PDF-Barrierefreiheit gespeichert. Frontend-Formular-Uploads sind ausgenommen. Details zu den Prüfregeln: Benutzerhandbuch.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
pdf.uploadGate |
Optionen (off/warn/block) |
off |
warn: Datei wird gespeichert, der Redakteur erhält eine bleibende Warnmeldung mit den Befunden. block: Der Upload wird mit einer Meldung inkl. Befunden abgelehnt — es entsteht keine Datei. |
pdf.uploadGateSeverity |
Optionen (error/warning) |
error |
Ab welchem Schweregrad das Gate greift. warning = Fehler und Warnungen (z. B. fehlender Dokumenttitel), error = nur kritische Fehler. |
pdf.uploadGateAdminBypass |
boolean | an | Administratoren dürfen trotz Befunden hochladen (erhalten nur die Warnung statt einer Blockade). |
pdf.auditTimeLimit |
int (Sekunden) | 60 |
Seit 1.19.0. Höchstdauer je Datei in der Bestandsprüfung nt_ai:pdf-audit (Planer-Aufgabe). Eine Datei darüber wird als „nicht prüfbar" vermerkt und erst nach einer Änderung erneut geprüft; der Lauf endet mit Exit-Code 1 und nennt die Anzahl in der Zusammenfassung. Mit der PHP-Erweiterung pcntl (CLI) macht der Lauf mit der nächsten Datei weiter, ohne pcntl endet er an dieser Stelle und setzt beim nächsten Mal dahinter fort. 0 = kein Limit. Je Lauf überschreibbar mit --time-limit N. Gilt nicht für Upload-Gate und Modul (dort greift max_execution_time). |
pdf.verifyCommand |
string | leer | Seit 1.33.0. Zusätzliche Strukturprüfung einer durch die Schnellkorrektur geänderten PDF, bevor sie das Original ersetzt. Aufgerufen mit dem Pfad der Arbeitskopie als letztem Argument; abgelehnt wird, wenn die Kopie die Prüfung nicht besteht (Rückgabewert ≠ 0), das Original aber schon – Warnungen, die schon das Original hat, blockieren nicht. Leer = nur die eingebaute Prüfung (Neueinlesen und Vergleich). Beispiele: qpdf --check oder Python mit pikepdf und dem mitgelieferten Skript Resources/Private/Scripts/pdf-check.py (siehe Benutzerhandbuch, Schnellkorrektur). |
pdf.uploadMaxSizeMb |
int (MB) | 25 |
Seit 1.23.0. Größere PDFs werden beim Upload nicht sofort geprüft, damit der Upload nicht hängt (das Zeitlimit der Bestandsprüfung wirkt nur auf der Kommandozeile). Der Redakteur erhält einen Hinweis; die Bestandsprüfung erfasst die Datei beim nächsten Lauf. 0 = keine Grenze. |
pdf.altTextDataPolicy |
Optionen (all/local/off) |
all |
Seit 1.23.0. Für einen KI-Alt-Text zu einem PDF gehen Titel und bis zu 8.000 Zeichen Dokumenttext an den KI-Anbieter. local erlaubt das nur mit Ollama, off schaltet die Funktion für PDFs ab. Gilt für Schaltflächen, Upload und Massenlauf. Bilder sind nicht betroffen. Einzelne Ordner schließt altText.excludePrefixes aus – seit 1.23.0 auch für die Schaltflächen. |
Seit 1.23.0 ist error der Standard für pdf.uploadGateSeverity. Eine Installation, in der der Wert schon gespeichert ist, behält ihn; nur neue Installationen und nie gespeicherte Konfigurationen bekommen den neuen Standard. Der Upload-Hinweis nennt zuerst die Fehler, dann – falls die Schwelle warning ist – die Warnungen, höchstens drei, und zählt den Rest. Ein PDF mit mindestens einem Fehler erhält höchstens 49 von 100 Punkten.
Für Bestandsprüfung und Pipelines: nt_ai:pdf-audit [--limit N] [--force] [--fail-on=error|warning] [--time-limit N]
— rein PHP-basiert (keine Systemwerkzeuge nötig). Jede Datei wird je Inhalt (SHA1) und Fassung der Prüfung genau einmal versucht — auch ein fehlgeschlagener oder abgebrochener Versuch zählt; eine ältere Fassung der Prüfung oder --force lösen eine neue Prüfung aus.
Token-Tracking und Kostenschätzung¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
tokenTracking.enabled |
boolean | aus | Wenn aktiv, wird jeder KI-Aufruf in tx_ntai_token_usage protokolliert. Erforderlich für die Token-Verbrauchs-Dashboard-Widgets. |
tokenTracking.currency |
Optionen | USD |
Anzeigewährung für geschätzte Kosten. USD → ~$0.19, EUR → ~0,18 €. |
tokenTracking.eurRate |
float | 0.92 |
USD-zu-EUR-Umrechnungskurs. Wird nur verwendet, wenn die Währung auf EUR gesetzt ist. |
tokenTracking.customPricing |
Text (JSON) | (leer) | Integrierte Modellpreistabelle überschreiben oder erweitern. Preise in USD pro 1.000.000 Token. Präfix-Matching wird angewendet — "gpt-4o" trifft auf gpt-4o-2024-08-06. |
{
"my-fine-tuned-gpt4o": {"input": 4.00, "output": 12.00},
"custom-ollama-model": {"input": 0.00, "output": 0.00}
}
Integrierte Preistabelle (Stand 2026-07)¶
| Modell-Präfix | Anbieter | Input $/1M | Output $/1M |
|---|---|---|---|
gpt-4o-mini |
OpenAI | 0.15 | 0.60 |
gpt-4o |
OpenAI | 2.50 | 10.00 |
claude-haiku-4 |
Anthropic | 0.80 | 4.00 |
claude-sonnet-4 |
Anthropic | 3.00 | 15.00 |
claude-opus-4 |
Anthropic | 15.00 | 75.00 |
gemini-2.0-flash |
0.10 | 0.40 | |
gemini-2.5-pro |
1.25 | 10.00 | |
deepseek-chat |
DeepSeek | 0.27 | 1.10 |
mistral-small |
Mistral AI | 0.20 | 0.60 |
llama-3.3-70b |
Groq | 0.59 | 0.79 |
Die vollständige Tabelle befindet sich in EXT:nt_ai/Configuration/ModelPricing.php. Unbekannte Modelle werden im Dashboard-Widget als Warnung angezeigt. TTS-Modelle (tts-1, tts-1-hd, gpt-4o-mini-tts) sind dort mit dem Preis pro 1 Mio. Zeichen hinterlegt.
Vorlesen (TTS)¶
Engine, Tempo und Vorlese-Bereich werden in den Site-Einstellungen gewählt (Kategorie „Vorlesen (TTS)"). Die folgenden Werte gelten nur für die Cloud-Engine und stehen in der Erweiterungskonfiguration (Tab „Vorlesen (TTS)"):
Lehnt der Endpunkt einen Abschnitt ab (403 Text steht nicht auf der Seite, 429 Ratenlimit, 503 Budget oder ausgelastet, 502 Anbieterfehler), liest ihn seit 1.22.2 die Browserstimme; danach wird der nächste Abschnitt wieder in der Cloud angefragt. Nach zwei Ablehnungen in Folge liest die Browserstimme den Rest der Seite ohne weitere Anfragen. Pause, Weiter, Tempo und Lautstärke wirken auf die Stimme, die gerade liest.
Zwei Fälle, in denen die Seitentext-Prüfung Abschnitte immer ablehnt:
- Per JavaScript nachgeladene Inhalte (z. B. eine per Ajax geladene Liste): Die Prüfung vergleicht mit dem HTML, das der Server ausliefert; solche Abschnitte stehen dort nicht. Sie werden von der Browserstimme gelesen.
- Websites hinter HTTP-Basic-Auth (Staging): Die Prüfung ruft die Seite selbst ab und erhält 401, solange
audit.httpAuthUserundaudit.httpAuthPasswordnicht gesetzt sind (seit 1.21.0) – die Vorlese-Prüfung nutzt dieselben Zugangsdaten wie der Audit.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
tts.cloudProvider |
Optionen | openai |
Anbieter der Premium-Sprachausgabe. API-Key = der des jeweiligen Providers (Tab „Anbieter-Einstellungen"). |
tts.voice |
string | alloy |
Stimme des Anbieters (OpenAI: alloy, echo, fable, onyx, nova, shimmer). |
tts.model |
string | tts-1 |
TTS-Modell (OpenAI: tts-1, tts-1-hd, gpt-4o-mini-tts). Unterstützt %env(VAR)%, siehe Modellnamen aus der Umgebung. |
tts.rateLimit |
integer | 30 |
Max. neue Cloud-Anfragen pro IP und Minute (Schutz vor Bots/Massennutzung). 0 = unbegrenzt; Cache-Treffer zählen nicht. Wechselnde IPs umgehen dieses Limit, die Tagesbudgets nicht. |
tts.dailyCharacterBudget |
integer | 200000 |
Zeichen pro Kalendertag (UTC), die an den Anbieter gehen dürfen — für alle Besucher zusammen. Wird vor jedem Aufruf atomar reserviert; erschöpft → HTTP 503 bis zum Folgetag. 0 = kein globales Limit (nicht empfohlen). Mit OpenAI tts-1 entspricht der Standard etwa 3 USD pro Tag. |
tts.dailyRequestBudget |
integer | 2000 |
Anbieter-Aufrufe pro Kalendertag (UTC), für alle Besucher zusammen. 0 = kein globales Limit (nicht empfohlen). |
tts.maxConcurrent |
integer | 4 |
Cloud-Erzeugungen, die gleichzeitig laufen dürfen — für alle Besucher zusammen (seit 1.18.0). Weitere neue Passagen erhalten sofort HTTP 503 mit Retry-After: 5 und werden mit der Browserstimme gelesen. Der Platz einer abgebrochenen Anfrage wird nach Anfrage-Timeout plus 30 s frei. Cache-Treffer zählen nicht. 0 = keine Begrenzung. |
tts.requirePageText |
boolean | 1 |
Nur Text vorlesen, der auf der angefragten Seite dieser Website steht. Die öffentliche Fassung der Seite wird einmal abgerufen und eine Stunde zwischengespeichert. Grenzen siehe Benutzerhandbuch. |
Der Cloud-Endpunkt /nt-ai/tts antwortet nur, wenn die Site-Engine auf cloud steht; er weist Cross-Site-Anfragen ab und ist rate-limitiert. Erzeugte Audios werden serverseitig gecacht, wiederholte Vorlesevorgänge desselben Textes sind kostenlos. Details siehe Benutzerhandbuch → Vorlesefunktion.
Berechtigungen im Backend¶
Seit 1.17.0 wenden alle Ansichten, Exporte und AJAX-Aktionen von nt-ai dieselben Regeln an wie der TYPO3-Kern. Administratoren sind nicht eingeschränkt.
- Seiten: Berichte, Scores und Lighthouse-Werte gibt es nur für Seiten, die der Redakteur anzeigen darf und die in seinen Webmounts liegen, und nur für Sprachen, die er bearbeiten darf. Site-Übersicht, Summen, Regelauswertung, Gesamtbericht, Lighthouse-Reiter und Dashboard-Widgets entstehen nur aus diesen Seiten. „Alle Websites" heißt: alle Websites, die der Redakteur sehen darf; die Website-Auswahl listet nur diese. Eine in der Auswahl oder der URL gewählte Website ist ein Filter, keine Berechtigung.
- Dateien: Einen Alt-Text erzeugen darf, wer die Datei lesen darf (Dateifreigabe). Einen Alt-Text aus dem Audit speichern darf nur, wer die Metadaten bearbeiten darf: beschreibbare (nicht schreibgeschützte) Dateifreigabe, Änderungsrecht auf
sys_file_metadataund das Feldalternative, Zugriff auf die Standardsprache. Gespeichert wird über DataHandler (Verlauf, Workspaces). Fehlt ein Recht, antwortet nt-ai mit 403 und ändert nichts. Geschrieben wird nur der Metadatensatz der Standardsprache; übersetzte Alt-Texte werden nicht mehr überschrieben. - PDF-Modul und PDF-Widget: Liste, Summen, Detailansicht und Prüf-Aktionen umfassen nur PDFs in den Dateifreigaben des Redakteurs.
- Barrierefreiheitserklärung (seit 1.18.0): Sie ist eine rechtliche Aussage über eine ganze Website und entsteht deshalb nie aus Teildaten. Redakteure (bei
declaration.editorsMayPublish) sehen ihre Kennzahlen und dürfen sie erzeugen und veröffentlichen nur mit Zugriff auf die Startseite und auf jede Seite mit Audit- oder Lighthouse-Ergebnissen dieser Website, jede Sprache mit Ergebnissen und jedes PDF, das die Erklärung zählt (Dateifreigaben). Sonst erklärt der Reiter, dass voller Zugriff auf die Website nötig ist, und die AJAX-Aktionen antworten mit 403. Alle Kennzahlen — auch der Lighthouse-Durchschnitt — umfassen nur die gewählte Website und ihre konfigurierten Sprachen, auch für Administratoren. - Dashboard-Widgets (seit 1.18.0): Audit-Score, Lighthouse, Seiten-Score und die Score-Diagramme filtern nach den Sprachen des Redakteurs ebenso wie nach seinen Seiten.
- KI-Budget (seit 1.18.0): Alle Backend-Aktionen, die einen kostenpflichtigen Anbieter aufrufen (Audit-Lauf, Erklären, Alt-Text und Bildbeschreibung, SEO- und Formulartexte, Score-Analyse, Erklärung), zehren von einem Budget pro Benutzer,
rateLimitPerMinute(Standard 30 pro Minute). Ein Wechsel der Aktion setzt es nicht zurück; ist es verbraucht, antwortet die Aktion mit HTTP 429, bevor der Anbieter gefragt wird.
Lighthouse-Monitoring¶
Öffentlich erreichbare URLs erforderlich
Die PSI-API kann ausschließlich öffentlich zugängliche URLs analysieren. Diese Funktion auf Staging- oder Produktivservern verwenden, nicht auf lokalen DDEV-Instanzen — Google kann *.ddev.site-URLs nicht erreichen.
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
lighthouse.apiKey |
string | (leer) | Google-API-Schlüssel von console.cloud.google.com (API „PageSpeed Insights" aktivieren). Ohne Schlüssel sind Anfragen auf ~25 pro 100 Sekunden begrenzt. Im Produktivbetrieb immer einen Schlüssel konfigurieren. Unterstützt %env(NT_AI_LIGHTHOUSE_KEY)%. |
lighthouse.strategy |
Optionen | mobile |
Geräteprofil für Lighthouse. mobile (Standard), desktop oder both (führt zwei PSI-Aufrufe pro Seite durch — verdoppelt den Kontingentverbrauch). |
# Alle Seiten, mobile Strategie (liest Einstellung aus der Erweiterungskonfiguration).
vendor/bin/typo3 nt_ai:lighthouse
# Seite 42 und vollständiger Teilbaum, nur Desktop.
vendor/bin/typo3 nt_ai:lighthouse 42 99 --strategy=desktop
# Unterseiten von Seite 1, beide Strategien ausführen.
vendor/bin/typo3 nt_ai:lighthouse 1 1 --strategy=both
Ergebnisse werden als rein additive Verlaufshistorie in tx_ntai_lighthouse_report gespeichert. Das Dashboard-Widget Lighthouse-Scores zeigt die durchschnittlichen Scores über alle analysierten Seiten.
Score-Schwellenwert-Alarme¶
| Einstellung | Typ | Standard | Beschreibung |
|---|---|---|---|
alerting.enabled |
boolean | aus | Hauptschalter. Kein E-Mail wird versendet, solange dieser deaktiviert ist. |
alerting.recipient |
string | (leer) | Eine oder mehrere E-Mail-Adressen, kommagetrennt. Beispiel: webmaster@example.com, seo@example.com. |
alerting.thresholdGeo |
integer (0–100) | 0 |
Alarm, wenn der GEO/SEO-KI-Score einer Seite diesen Wert unterschreitet. 0 deaktiviert den Alarm für diese Kategorie. |
alerting.thresholdPerformance |
integer (0–100) | 0 |
Schwellenwert für den Performance-KI-Score. |
alerting.thresholdSemantics |
integer (0–100) | 0 |
Schwellenwert für den Semantics-KI-Score. |
alerting.thresholdKeywords |
integer (0–100) | 0 |
Schwellenwert für den Keywords-KI-Score. |
alerting.thresholdAccessibility |
integer (0–100) | 0 |
Schwellenwert für den Barrierefreiheits-KI-Score. |
alerting.thresholdLighthousePerformance |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Performance-Score. |
alerting.thresholdLighthouseAccessibility |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Accessibility-Score. |
alerting.thresholdLighthouseBestPractices |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-Best-Practices-Score. |
alerting.thresholdLighthouseSeo |
integer (0–100) | 0 |
Schwellenwert für den Lighthouse-SEO-Score. |
Empfohlene Scheduler-Konfiguration — nt_ai:alert-check nach den Analyse-Befehlen ausführen, damit aktuelle Daten gelesen werden:
03:00 nt_ai:analyze-pages (KI-Inhalts-Scores)
03:30 nt_ai:lighthouse (Lighthouse-PSI-Scores)
04:00 nt_ai:alert-check (vergleichen + E-Mail senden falls nötig)
Welche Sprache ein Audit abdeckt¶
Eine Seite wird in der Sprache geprüft, auf die die Aufgabe eingestellt ist —
indem für die UID des Satzes in der Standardsprache die URL dieser Sprache
gebaut wird. Übersetzte Seitensätze sind deshalb keine eigenen Prüfziele und
werden übersprungen: Als eigener Kandidat ergäbe ein solcher Satz den
übersetzten Slug ohne Sprachpräfix — etwa /about-us/ statt /en/about-us/ —
also eine URL, die es nicht gibt und die nur 404 antworten kann.
Für mehrere Sprachen richtet man je Sprache eine Aufgabe ein, jede mit ihrer eigenen Spracheinstellung. Sie teilen sich die Sperrtabelle und doppeln ihr Wissen über unerreichbare Seiten deshalb nicht.
Bis einschließlich 1.13.1
Übersetzte Sätze wurden als Kandidaten ausgewählt. Jeder von ihnen antwortete 404, belegte damit einen Platz je Lauf und konnte — vor 1.13.0, als die Sperrfrist einen Lauf noch nicht überlebte — den Stapel vollständig füllen. Auf einer zweisprachigen Site betraf das rund die Hälfte aller Kandidaten. Nach dem Update verschwinden sie von selbst aus dem Umlauf; Sperreinträge aus früheren Läufen laufen von allein ab.
Seiten ohne Übersetzung
Ob eine Seite ohne Übersetzung in der Zielsprache 404 antwortet oder die
Standardsprache ausliefert, hängt von der Fallback-Einstellung der Site ab.
Bei strict antwortet sie 404 und wird als Ergebnis eine Woche
zurückgestellt — richtig und unschädlich; mit Fallback wird geprüft, was
ausgeliefert wird.
Seiten, die derzeit nicht veröffentlicht sind — verborgen oder außerhalb ihrer Zeitsteuerung — sind ebenfalls keine Kandidaten. Eine Seite mit abgelaufener Endzeit antwortet 404 wie eine verborgene, und anders als eine Seite im Wartungsmodus wird sie nie von selbst wieder prüfbar; eine Seite mit künftigem Startdatum tritt von allein in den Umlauf ein, sobald sie live geht. Eine Seite bewusst vor der Veröffentlichung zu prüfen, ist Aufgabe des signierten Vorschau-Tokens im Backend. Es gilt nur für die eine Seite (Sprache, Site, URL-Pfad), für die es erzeugt wurde.
Seiten, die der Audit nicht erreicht¶
Der geplante Audit arbeitet den Seitenbaum ab, die am längsten nicht geprüfte Seite zuerst. Eine Seite, die nicht abgerufen werden kann, schreibt keinen Bericht — ihr „zuletzt geprüft" bleibt leer, und sie stünde beim nächsten Lauf wieder ganz vorn. Wenige unerreichbare Seiten können so jeden Stapel belegen und den Umlauf zum Stillstand bringen.
Deshalb wird eine solche Seite eine Zeit lang zurückgestellt. Wie lange, hängt von der Antwort des Servers ab:
- 404 oder 410 — ein beabsichtigtes „nicht gefunden", typischerweise eine Detail-URL ohne Datensatz. Eine Woche Pause: Das ist ein Ergebnis, kein Fehler, und der Inhalt entsteht selten kurzfristig.
- 503 oder 429 — „vorübergehend nicht verfügbar", also Wartungsseite oder
Drosselung. Zurückgestellt für die Zeit, die der Server im Kopffeld
Retry-Afternennt, sonst eine Stunde. Eine Site im Wartungsmodus braucht damit keine weitere Einstellung: Sie nimmt sich selbst aus dem Umlauf und kehrt zurück, sobald sie wieder da ist. - Alles andere (HTTP 5xx, Zeitüberschreitungen, Verbindungsfehler) gilt als technischer Fehler. Die Pause wächst mit jedem weiteren Fehlschlag — 6 Stunden, 24 Stunden, 3 Tage, dann 7 Tage. Ein erfolgreicher Audit löscht den Eintrag.
Nur ein echter technischer Fehler zählt für die Regel, die die Aufgabe rot färbt, wenn jede prüfbare Seite eines Stapels gescheitert ist. Seiten, die lediglich 404 oder 503 geantwortet haben, zählen nicht mit.
Die Einträge stehen in tx_ntai_audit_deferral (eine Zeile je Seite und Sprache,
mit Grund und Ende der Pause) und sind damit einsehbar:
SELECT page_uid, status_code, failure_count,
FROM_UNIXTIME(deferred_until) AS pausiert_bis, reason
FROM tx_ntai_audit_deferral ORDER BY page_uid;
Abgelaufene Einträge werden automatisch entfernt.
Die Spalte reason nennt auch die Herkunft der Frist — Retry-After: 1800s,
no Retry-After, default, clean 404/410 oder die Stufe der Fehler-Eskalation.
Ohne diese Angabe lässt sich die Frage nicht beantworten: Ein Server mit
Retry-After: 3600 und der eingebaute Vorgabewert von einer Stunde ergeben
denselben Zeitpunkt.
Vor 1.13.0
Dieser Zustand lag auf dem Objekt der Planer-Aufgabe und konnte einen Lauf
nicht überleben: Der Planer speichert eine Aufgabe vor der Ausführung und
schreibt danach nur ihre Ausführungsdaten zurück, nie ihre Parameter. Die
Pause griff deshalb nie, und ein Stapel unerreichbarer Seiten konnte den
Umlauf aushungern. Zu konfigurieren ist nichts — extension:setup muss
einmal laufen, damit die neue Tabelle entsteht.
Optionale Argumente in einer Planer-Aufgabe¶
Eine über das TYPO3-Backend angelegte Aufgabe speichert alle Argumente des
Befehls — auch die, die Sie leer gelassen haben: Eine nicht gesetzte pageId
wird als leerer String abgelegt, nicht als „nicht vorhanden". nt_ai:analyze-pages
und nt_ai:lighthouse behandeln eine leere pageId als „nicht angegeben" und
messen dann alle Seiten — das Feld im Backend leer zu lassen tut also das, wonach
es aussieht.
Zwei Hinweise dazu:
- Eine
pageIdvon0wird mit einer Fehlermeldung abgewiesen. Seite 0 ist die Baumwurzel und nie eine echte Seite: Sie gehört zu keiner Site und hat keine URL, kann also nur unerreichbare Ergebnisse liefern. - Wer Aufgaben per Skript statt über das Backend anlegt, übergibt am besten
arguments: [], damit gar keine leeren Werte gespeichert werden.