Formularvalidierungsskript
Kurzfassung: Formularvalidierungsskripte werden ausgeführt, nachdem alle individuellen Feldvalidierer auf einem Formular-Knoten bestanden haben, um eine Validierung über mehrere Felder hinweg, Wertänderungen und die Ablehnung des Formulars mit LLM-Feedback zu ermöglichen. Verwenden Sie sie, um Beziehungen zwischen Feldern zu validieren (z. B. Enddatum > Startdatum), Werte vor dem Speichern zu transformieren oder ganze Formulare mit beschreibenden Fehlermeldungen abzulehnen, die das LLM zur erneuten Eingabe anleiten.
Ein Formularvalidierungsskript ist ein benutzerdefiniertes Python-Skript, das auf Formularebene ausgeführt wird, nachdem alle individuellen Extraktionsfeldvalidierer bestanden haben. Im Gegensatz zu Feldvalidierungsskripten, die einzelne Werte isoliert validieren, können Formularvalidierungsskripte auf alle extrahierten Werte gleichzeitig zugreifen, was sie ideal für komplexe Validierungslogik macht, die sich über mehrere Felder erstreckt.
Warum Formularvalidierungsskripte verwenden?
Formularvalidierungsskripte geben Ihnen präzise Kontrolle über die endgültige Validierungsstufe der Formular-Extraktion. Anstatt nur Felder einzeln zu validieren, können Sie:
- Validierung über mehrere Felder hinweg - Stellen Sie sicher, dass Beziehungen zwischen mehreren Feldern gültig sind (z. B. Enddatum nach Startdatum, Passwortbestätigung stimmt mit Passwort überein)
- Werttransformation - Validierte Werte vor dem Speichern ändern oder anreichern (z. B. Gesamtsummen berechnen, Formate standardisieren)
- Durchsetzung von Geschäftsregeln - Komplexe Geschäftslogik anwenden, die mehrere Feldwerte erfordert
- Formularablehnung - Das gesamte Formular mit einer beschreibenden Fehlermeldung ablehnen, die an das LLM zur erneuten Eingabe zurückgegeben wird
- Dynamische Validierung - Gesprächsverlauf oder externe Daten zur Validierung des Formulars verwenden
Wann Formularvalidierung vs. Feldvalidierung verwenden
Verwenden Sie Formularvalidierungsskripte, wenn:
- Sie Beziehungen zwischen mehreren Feldern validieren müssen
- Die Validierungslogik von Kombinationen von Werten abhängt
- Sie mehrere Felder basierend auf anderen Feldwerten ändern möchten
- Geschäftsregeln die Bewertung der vollständigen Formulardaten erfordern
Verwenden Sie Feldvalidierungsskripte (auf individuellen Extraktionsfeldern), wenn:
- Die Validierung für jedes Feld unabhängig ist
- Jedes Feld isoliert validiert werden kann
- Sie möchten, dass die Validierung ausgeführt wird, sobald das LLM dieses spezifische Feld extrahiert
Best Practice: Beginnen Sie mit der Feldvalidierung für einfache Überprüfungen und fügen Sie die Formularvalidierung nur hinzu, wenn Sie Logik über mehrere Felder hinweg benötigen. Dies hält Ihre Validierung modular und einfacher zu warten.
Erstellen eines Formularvalidierungsskripts
Schritt 1: Öffnen Sie Ihren Formular-Knoten
- Navigieren Sie zu Inhalt → Flows
- Öffnen Sie den Flow, der Ihren Formular-Knoten enthält
- Klicken Sie auf den Formular-Knoten, dem Sie die Validierung hinzufügen möchten

Schritt 2: Formularvalidierung aktivieren
- Scrollen Sie nach unten zum Abschnitt Formularvalidierungsskript am unteren Rand des Formular-Knoten-Editors
- Schalten Sie den Formularvalidierung aktiv-Schalter um, um ihn zu aktivieren
- Der Code-Editor erscheint mit einer Standardvorlage

Schritt 3: Schreiben Sie Ihre Validierungslogik
Die Standardvorlage bietet die grundlegende Struktur:
from shared import RemoteLLMTrackerApi
from shared import FormValidator
from loguru import logger
from typing import Any
class form_validator(FormValidator):
async def run(
self,
tracker_api: RemoteLLMTrackerApi,
validated_slots: dict[str, Any]
) -> dict[str, Any]:
"""
Formularvalidierer auf Formularebene, der ausgeführt wird, nachdem alle Feldvalidierer bestanden haben.
Args:
tracker_api: Voller Zugriff auf Gesprächsverlauf, Slots, LLM-Aufrufe
validated_slots: Dict von slot_name -> validated_value
Returns:
Das validierte (und möglicherweise modifizierte) Slots-Dict
Raises:
ValueError: Wenn die Validierung fehlschlägt, mit beschreibender Fehlermeldung
"""
# Beginnen Sie hier mit dem Codieren
# Beispiel-Validierungslogik
is_valid = True
if not is_valid:
# Standard-Formular-Agent gibt diesen Fehler an das LLM
raise ValueError("Formularvalidierung fehlgeschlagen")
return validated_slots
Schritt 4: Speichern und Bereitstellen
- Klicken Sie auf Speichern, um Ihr Skript als Entwurf zu speichern
- Klicken Sie auf Bereitstellen, um Ihr Validierungsskript zu aktivieren
- Das Skript wird nun jedes Mal ausgeführt, wenn dieser Formular-Knoten die Extraktion abschließt
Hinweis: Wie andere Skripte unterstützen Formularvalidierungsskripte den Entwurfsmodus und die Versionsverwaltung. Siehe Skripte für Details zur Verwaltung von Skriptversionen.
Wie Formularvalidierung funktioniert
Ausführungsablauf
Wenn ein Formular-Knoten Daten extrahiert, folgt der Validierungsprozess dieser Sequenz:
1. Benutzer gibt Eingaben ein
↓
2. LLM extrahiert Feldwerte (Werkzeugaufruf)
↓
3. Pydantic-Typvalidierung (automatische Typkonvertierung)
↓
4. Einzelne Feldvalidierer werden ausgeführt (falls aktiv)
↓
5. ✨ Formularvalidierungsskript wird ausgeführt (falls aktiv) ✨
↓
6. Werte werden in Slots gespeichert ODER Formular wird mit Fehler abgelehnt
Erfolgsszenario
Wenn Ihr Formularvalidierer das validated_slots-Dict zurückgibt, ohne eine Ausnahme auszulösen:
- Alle Slots werden mit ihren (möglicherweise modifizierten) Werten gespeichert
- Der Formular-Knoten wird erfolgreich abgeschlossen
- Ein
FormValidationSuccessEventwird in den Ereignispuffer gesendet - Der Bot fährt mit dem nächsten Knoten im Flow fort
Fehlerszenario
Wenn Ihr Formularvalidierer eine ValueError auslöst:
- Alle Slots für dieses Formular werden auf
Nonezurückgesetzt (außer dem speziellen__form__-Slot) - Die Fehlermeldung aus der
ValueErrorwird an das LLM zurückgesendet - Ein
FormValidationErrorEventwird in den Ereignispuffer gesendet - Das LLM erhält den Fehler als Funktionsaufruf-Feedback und kann mit korrigierten Werten erneut versuchen
Beispiel-Fehlerablauf:
# Ihr Validierer löst einen Fehler aus
raise ValueError("Enddatum muss nach dem Startdatum liegen. Bitte geben Sie gültige Daten an.")
# LLM erhält: "Buchungstermin konnte aufgrund der folgenden Fehler nicht durchgeführt werden:
# - __form__: Enddatum muss nach dem Startdatum liegen. Bitte geben Sie gültige Daten an."
# LLM antwortet dem Benutzer: "Entschuldigung, aber das Enddatum muss nach dem Startdatum liegen. Könnten Sie bitte ein gültiges Enddatum angeben?"
Häufige Anwendungsfälle
1. Validierung über mehrere Felder hinweg
Validieren Sie Beziehungen zwischen mehreren Feldern:
async def run(self, tracker_api, validated_slots):
# Datumsbereichsvalidierung
if validated_slots['end_date'] < validated_slots['start_date']:
raise ValueError(
"Das Enddatum muss nach dem Startdatum liegen. "
"Bitte geben Sie gültige Daten an."
)
# Passwortbestätigung
if validated_slots.get('password') != validated_slots.get('password_confirm'):
raise ValueError(
"Das Passwort und das Bestätigungspasswort stimmen nicht überein. "
"Bitte versuchen Sie es erneut."
)
# Menge vs. Verfügbarkeit
if validated_slots['quantity'] > validated_slots['available_stock']:
raise ValueError(
f"Es sind nur {validated_slots['available_stock']} Einheiten verfügbar. "
f"Bitte reduzieren Sie Ihre Menge."
)
return validated_slots
2. Werttransformation
Ändern Sie Werte vor dem Speichern:
async def run(self, tracker_api, validated_slots):
# Abgeleitete Werte berechnen
num_days = (validated_slots['end_date'] - validated_slots['start_date']).days
validated_slots['total_price'] = num_days * validated_slots['daily_rate']
# Textwerte normalisieren
validated_slots['email'] = validated_slots['email'].lower().strip()
validated_slots['country_code'] = validated_slots['country_code'].upper()
# Telefonnummern formatieren
phone = validated_slots['phone_number'].replace('-', '').replace(' ', '')
validated_slots['phone_number'] = f"+1-{phone[:3]}-{phone[3:6]}-{phone[6:]}"
return validated_slots
3. Bedingte Validierung
Anwenden von Validierungsregeln basierend auf anderen Feldwerten:
async def run(self, tracker_api, validated_slots):
# Länderspezifische Validierung
if validated_slots['country'] == 'US':
if not validated_slots.get('zip_code'):
raise ValueError(
"Postleitzahl ist für US-Adressen erforderlich. "
"Bitte geben Sie Ihre Postleitzahl an."
)
if len(validated_slots['zip_code']) != 5:
raise ValueError(
"US-Postleitzahlen müssen 5 Ziffern haben. "
"Bitte geben Sie eine gültige Postleitzahl an."
)
# Altersbasierte Validierung
if validated_slots['age'] < 18:
if not validated_slots.get('parent_consent'):
raise ValueError(
"Elterliche Zustimmung ist für Benutzer unter 18 Jahren erforderlich. "
"Bitte bestätigen Sie die elterliche Zustimmung."
)
return validated_slots
4. Externe API-Validierung
Externe Dienste aufrufen, um Formulardaten zu validieren:
async def run(self, tracker_api, validated_slots):
import aiohttp
# Überprüfen, ob E-Mail bereits registriert ist
email = validated_slots['email']
async with aiohttp.ClientSession() as session:
async with session.get(
f"https://api.example.com/check-email?email={email}"
) as response:
if response.status == 200:
data = await response.json()
if data['exists']:
raise ValueError(
f"Die E-Mail {email} ist bereits registriert. "
"Bitte verwenden Sie eine andere E-Mail oder melden Sie sich an."
)
# Adresse mit Geocoding-API validieren
address = validated_slots['address']
# ... Validierungslogik
return validated_slots
5. Komplexe Geschäftsregeln
Implementieren Sie anspruchsvolle Geschäftslogik:
async def run(self, tracker_api, validated_slots):
# Preisstufenberechnung
quantity = validated_slots['quantity']
base_price = validated_slots['unit_price']
if quantity >= 100:
discount = 0.20 # 20% Rabatt
elif quantity >= 50:
discount = 0.10 # 10% Rabatt
elif quantity >= 10:
discount = 0.05 # 5% Rabatt
else:
discount = 0
validated_slots['discount_percent'] = discount * 100
validated_slots['total_price'] = quantity * base_price * (1 - discount)
# Kreditlimit validieren
customer_credit_limit = tracker_api.get_slot("customer_credit_limit")
if customer_credit_limit:
if validated_slots['total_price'] > customer_credit_limit:
raise ValueError(
f"Ihr Bestellwert (${validated_slots['total_price']:.2f}) "
f"übersteigt Ihr Kreditlimit (${customer_credit_limit:.2f}). "
"Bitte reduzieren Sie Ihre Bestellmenge oder kontaktieren Sie den Vertrieb."
)
return validated_slots
Best Practices
1. Halten Sie die Validierungslogik einfach und fokussiert
Ihr Formularvalidierer sollte zuverlässig und leicht verständlich sein:
Gut:
# Klare, zielgerichtete Überprüfungen
if validated_slots['end_date'] < validated_slots['start_date']:
raise ValueError("Enddatum muss nach dem Startdatum liegen")
if validated_slots['age'] < 18:
raise ValueError("Sie müssen 18 Jahre oder älter sein, um sich zu registrieren")
Vermeiden:
# Übermäßig komplexe verschachtelte Logik
if (validated_slots['field1'] and
(validated_slots['field2'] or validated_slots['field3']) and
not validated_slots.get('field4', None) and
some_complex_calculation(validated_slots) > threshold):
# Schwer zu verstehen und zu warten
2. Schreiben Sie klare Fehlermeldungen
Fehlermeldungen werden an das LLM zurückgegeben, das sie verwendet, um den Benutzer zu leiten. Machen Sie sie gesprächig und spezifisch:
Gut:
raise ValueError(
"Das Enddatum (15. Juni) muss nach dem Startdatum (20. Juni) liegen. "
"Bitte geben Sie ein gültiges Enddatum an, das nach dem 20. Juni liegt."
)
Vermeiden:
raise ValueError("Ungültiger Datumsbereich") # Zu vage
raise ValueError("end_date <= start_date") # Zu technisch
3. Behandeln Sie fehlende optionale Felder
Überprüfen Sie immer, ob optionale Felder existieren, bevor Sie sie validieren:
# Sicher - überprüft, ob das Feld existiert
if validated_slots.get('optional_field'):
# Validieren Sie das optionale Feld
pass
# Unsicher - wird KeyError auslösen, wenn das Feld nicht existiert
if validated_slots['optional_field']: # ❌ Nicht so machen
pass
4. Protokollieren Sie wichtige Validierungsereignisse
Verwenden Sie Protokollierung, um Validierungsprobleme zu debuggen:
from loguru import logger
async def run(self, tracker_api, validated_slots):
logger.info(f"Formularvalidierung gestartet mit {len(validated_slots)} Feldern")
try:
# Validierungslogik
if some_condition:
logger.warning("Validierung fehlgeschlagen: Bedingung X nicht erfüllt")
raise ValueError("...")
logger.info("Formularvalidierung erfolgreich")
return validated_slots
except Exception as e:
logger.error(f"Formularvalidierungsfehler: {e}")
raise
5. Minimieren Sie externe API-Aufrufe
Externe API-Aufrufe fügen Latenz und potenzielle Fehlerquellen hinzu. Verwenden Sie sie sparsam:
Überlegen:
- Kann die Validierung mit lokalen Daten durchgeführt werden?
- Ist der API-Aufruf für jede Formulareinreichung notwendig?
- Was passiert, wenn die API langsam oder nicht verfügbar ist?
Wenn Sie APIs verwenden müssen:
# Zeitüberschreitungen festlegen
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=5)) as session:
try:
async with session.get(url) as response:
# Antwort behandeln
pass
except asyncio.TimeoutError:
logger.warning("API-Zeitüberschreitung, Fortfahren ohne Validierung")
# Entscheiden: Validierung fehlschlagen oder fortfahren?
6. Ändern Sie Slots nicht direkt über tracker_api
Obwohl Sie Zugriff auf tracker_api.set_slot() haben, vermeiden Sie die Verwendung in Formularvalidierern. Ändern Sie stattdessen das validated_slots-Dict:
Gut:
# Ändern Sie das zurückgegebene Dict
validated_slots['calculated_field'] = some_value
return validated_slots
Vermeiden:
# Setzen Sie Slots nicht direkt im Validierer
tracker_api.set_slot('calculated_field', some_value) # ❌
Warum? Der Formular-Agent verwaltet die Slot-Zuweisung. Das direkte Ändern von Slots kann zu einem inkonsistenten Zustand führen.
7. Testen Sie Randfälle
Berücksichtigen und testen Sie Szenarien wie:
- Alle Felder auf Minimalwerten
- Alle Felder auf Maximalwerten
- Grenzbedingungen (z. B. genau gleiche Daten)
- Leere optionale Felder
- Sonderzeichen in Textfeldern
- Sehr große oder sehr kleine Zahlen
8. Verwenden Sie Typ-Hinweise
Typ-Hinweise verbessern die Lesbarkeit des Codes und fangen Fehler ab:
from typing import Any
from datetime import datetime
async def run(
self,
tracker_api: RemoteLLMTrackerApi,
validated_slots: dict[str, Any]
) -> dict[str, Any]:
start_date: datetime = validated_slots['start_date']
end_date: datetime = validated_slots['end_date']
# Ihre Validierungslogik mit klaren Typen
return validated_slots
Fehlertypen und Behandlung
ValueError - Validierung fehlgeschlagen
Verwenden Sie ValueError, wenn die Validierung aufgrund von Geschäftslogik fehlschlägt:
if condition_not_met:
raise ValueError("Beschreibende Nachricht für das LLM")
Ergebnis:
- Alle Formular-Slots werden auf
Nonezurückgesetzt - Fehlermeldung wird an das LLM gesendet
FormValidationErrorEventwird gesendet- LLM kann mit korrigierten Werten erneut versuchen
Andere Ausnahmen - Ausführungsfehler
Jeder andere Ausnahmetyp zeigt einen Skriptfehler an:
# Nicht behandelte Ausnahme
result = some_api_call() # Löst ConnectionError aus
Ergebnis:
- Alle Formular-Slots werden auf
Nonezurückgesetzt - Eine generische Fehlermeldung wird gesendet
FormValidationErrorEventwird mit Ausführungsfehlerstatus gesendet- Fehler wird zur Fehlerbehebung protokolliert
Best Practice: Fangen und behandeln Sie erwartete Ausnahmen, indem Sie sie in
ValueErrormit benutzerfreundlichen Nachrichten umwandeln:
try:
result = await external_api_call()
except aiohttp.ClientError as e:
logger.error(f"API-Aufruf fehlgeschlagen: {e}")
raise ValueError(
"Ihre Informationen können derzeit nicht überprüft werden. "
"Bitte versuchen Sie es in einem Moment erneut."
)
Überwachung und Debugging
Ereignisse
Das System sendet Ereignisse, die Sie überwachen können:
Erfolgsevent:
FormValidationSuccessEvent(
payload=FormValidationSuccessPayload(
form_name="book_appointment",
validated_slots={
"start_date": "2024-06-01",
"end_date": "2024-06-15",
# ... andere Slots
}
)
)
Fehlerevent:
FormValidationErrorEvent(
payload=FormValidationErrorPayload(
form_name="book_appointment",
validation_status=ValidationFailureStatus(
message="Enddatum muss nach dem Startdatum liegen",
value={...} # Die versuchten Slot-Werte
),
failed_slots={
"start_date": "Fehler bei der Validierung des Formulars",
"end_date": "Fehler bei der Validierung des Formulars",
"__form__": "Enddatum muss nach dem Startdatum liegen"
}
)
)
Debugging-Tipps
- Verwenden Sie Protokolle: Fügen Sie
logger.info()-Anweisungen hinzu, um die Ausführung zu verfolgen - Ereignis überprüfen: Überwachen Sie Ereignisse im Verlauf
- Im Entwicklungs-Chat testen: Verwenden Sie den Entwicklungs-Chat, um Randfälle zu testen
- Fehlermeldungen überprüfen: Überprüfen Sie, ob Fehlermeldungen klar und umsetzbar sind
- Skript-Syntax validieren: Stellen Sie sicher, dass Ihr Python-Code keine Syntaxfehler hat, bevor Sie ihn bereitstellen
Verwandte Funktionen
Feldvalidierung
Für feldspezifische Validierung verwenden Sie Validierungsskripte auf individuellen Extraktionsfeldern:
# Auf dem Extraktionsfeld selbst
if "@example.com" not in value:
raise ValueError("E-Mail muss aus der example.com-Domain stammen")
Siehe Extraktionsfelder für Details.
Fehlerflüsse
Wenn die Formularvalidierung wiederholt fehlschlägt, ziehen Sie in Betracht, einen Error Flow auszulösen, um die Situation elegant zu handhaben:
# In einem Aktionsknoten nach mehreren fehlgeschlagenen Versuchen
failed_attempts = tracker_api.get_slot("form_failed_attempts") or 0
if failed_attempts > 3:
# Error Flow auslösen oder an einen Menschen eskalieren
tracker_api.set_slot("escalate_to_human", True)
Häufig gestellte Fragen
F: Was passiert, wenn mein Validierer abstürzt?
Wenn Ihr Validierer eine unerwartete Ausnahme (nicht ValueError) auslöst, behandelt das System dies als Ausführungsfehler:
- Alle Slots werden auf
Nonezurückgesetzt - Eine generische Fehlermeldung wird gesendet
- Der Fehler wird zur Fehlerbehebung protokolliert
- Die Formular-Extraktion kann erneut versuchen
F: Kann ich das LLM von innerhalb des Validierers aufrufen?
Ja, Sie haben Zugriff auf die vollständige tracker_api, einschließlich LLM-Aufrufen:
response = await tracker_api.a_call_llm(messages=[...])
Verwenden Sie dies jedoch sparsam, da es Latenz und Komplexität hinzufügt.
F: Wie teste ich meinen Formularvalidierer?
Verwenden Sie den Entwicklungs-Chat (siehe Entwicklungs-Chat):
- Testen Sie mit gültigen Eingaben, um den Erfolg sicherzustellen
- Testen Sie mit ungültigen Eingaben, um Validierungsfehler auszulösen
- Überprüfen Sie, ob Fehlermeldungen klar und hilfreich sind
- Überprüfen Sie, ob geänderte Werte korrekt gespeichert werden
F: Kann ich die Formularvalidierung vorübergehend deaktivieren?
Ja, schalten Sie den Formularvalidierung aktiv-Schalter im Formular-Knoten-Editor um. Dadurch können Sie die Validierung deaktivieren, ohne Ihr Skript zu löschen.
F: Was ist der Unterschied zwischen Formularvalidierung und Feldvalidierung?
| Funktion | Feldvalidierung | Formularvalidierung |
|---|---|---|
| Umfang | Einzelnes Feld | Alle Felder |
| Wann | Nach jeder Feldextraktion | Nach allen extrahierten Feldern |
| Zugriff | Nur aktueller Feldwert | Alle Feldwerte |
| Verwendung für | Unabhängige Feldüberprüfungen | Beziehungen über mehrere Felder hinweg |
F: Kann ich auf den Gesprächsverlauf zugreifen?
Ja, verwenden Sie tracker_api.get_history(), um auf den vollständigen Gesprächsverlauf zuzugreifen:
history = tracker_api.get_history()
user_messages = [turn.content for turn in history if turn.role == 'user']
Verwandte Dokumentation
- Extraktionsfelder - Erfahren Sie mehr über das Erstellen und Verwalten von Extraktionsfeldern
- Formular-Knoten - Verstehen Sie, wie Formular-Knoten funktionieren
- Skripte - Allgemeine Skriptverwaltung und Best Practices
- Error Flow - Validierungsfehler mit Error Flows behandeln
- Entwicklungs-Chat - Testen Sie Ihre Formularvalidierungsskripte
Brauchen Sie Hilfe?
Wenn Sie Probleme mit der Formularvalidierung haben:
- Überprüfen Sie die Protokolle auf Fehlermeldungen und Stack-Traces
- Stellen Sie sicher, dass Ihr Skript keine Syntaxfehler hat
- Testen Sie zuerst mit einfacher Validierungslogik, dann fügen Sie Komplexität hinzu
- Überprüfen Sie den Abschnitt Best Practices