# Plan: Control Relevance Filter — Generische Controls kontextsensitiv filtern ## Problem Die UCCA-Engine empfiehlt Controls pauschal basierend auf Intake-Flags (Boolean-Felder wie `personal_data: true`, `marketing: true`). Sie prueft NICHT, ob der analysierte Text die Bedingungen fuer einen spezifischen Control tatsaechlich erfuellt. ### Konkretes Beispiel (Opodo-Test, 2026-04-28) - **Control:** `[C_TRANSPARENCY] Nutzer informieren dass sie mit KI interagieren` - **Quelle:** AI Act Art. 52 — nur relevant wenn KI eingesetzt wird - **Opodo sagt:** "automated processing" (kann regelbasierte Software sein, muss keine KI sein) - **Ergebnis:** False Positive — Control wird empfohlen obwohl kein KI-Einsatz belegt ist ### Skalierung Von ~166.740 Controls in der RAG-Datenbank wird ein unbekannter Prozentsatz bei jeder Bewertung generisch empfohlen. Jedes False Positive untergräbt das Vertrauen des Nutzers und macht das Tool fuer Abmahnungen unbrauchbar. ## Loesung: 3-Stufen Relevance Filter ### Stufe 1: Regelbasierter Vorfilter (deterministisch, schnell) Jeder Control bekommt ein `relevance_conditions` Feld (JSON): ```json { "control_id": "C_TRANSPARENCY", "relevance_conditions": { "text_must_contain_any": ["KI", "kuenstliche Intelligenz", "artificial intelligence", "machine learning", "maschinelles Lernen", "neural", "deep learning", "AI system", "AI-System", "algorith"], "text_must_not_contain": [], "requires_intake_flag": "automation", "min_confidence": 0.5 } } ``` **Implementierung:** - Neues Feld `relevance_conditions` in `compliance.canonical_controls` (JSONB) - Funktion `check_relevance(control, source_text) -> (relevant: bool, confidence: float)` - Laeuft NACH dem UCCA-Assessment, BEVOR das Ergebnis zurueckgegeben wird - Filtert Controls raus deren Keywords im Quelltext nicht vorkommen **Aufwand:** ~200 LOC Python, kein LLM-Call noetig **Datei:** `ai-compliance-sdk/internal/ucca/relevance_filter.go` oder `backend-compliance/compliance/services/relevance_filter.py` ### Stufe 2: LLM-Validierung (fuer High-Value Controls) Fuer Controls mit `severity >= HIGH` oder wenn der regelbasierte Filter unsicher ist (confidence < 0.7), wird Qwen gefragt: ``` Gegeben dieser Dokumenttext: "[...Auszug...]" Ist der folgende Control relevant fuer dieses Dokument? Control: "[C_TRANSPARENCY] Nutzer informieren dass sie mit KI interagieren" Rechtsgrundlage: Art. 52 AI Act Antworte NUR mit: JA (mit Begruendung) oder NEIN (mit Begruendung) ``` **Implementierung:** - Neuer Endpoint: `POST /sdk/v1/ucca/validate-controls` - Nimmt: `assessment_id`, `source_text`, `controls[]` - Gibt zurueck: `controls[]` mit `relevant: bool`, `reason: string` - Cached: Gleicher Text + Control = gleiche Antwort (24h TTL) **Aufwand:** ~150 LOC, 1 LLM-Call pro Control (parallelisierbar) ### Stufe 3: Follow-Up-Fragen an den Nutzer (Hybrid) Wenn weder Regel noch LLM sicher entscheiden koennen: ``` Follow-Up: "Setzt der Anbieter KI oder maschinelles Lernen ein?" → Ja: Control bleibt → Nein: Control wird entfernt → Unsicher: Control bleibt mit Hinweis "Nicht verifizierbar" ``` **Bereits implementiert:** Das `follow_up_questions` System im Agent-Endpoint. ## Datenmodell-Aenderung ```sql -- Neues Feld in canonical_controls ALTER TABLE compliance.canonical_controls ADD COLUMN IF NOT EXISTS relevance_conditions JSONB DEFAULT '{}'; -- Index fuer schnelle Abfrage CREATE INDEX IF NOT EXISTS idx_controls_relevance ON compliance.canonical_controls USING gin (relevance_conditions); ``` ## Architektur ``` UCCA Assessment │ ▼ ┌────────────────────┐ │ Stufe 1: Regelfilter│ ← text_must_contain_any, intake_flags │ (deterministisch) │ └────────┬───────────┘ │ unsicher oder high-severity ▼ ┌────────────────────┐ │ Stufe 2: LLM-Check │ ← Qwen validiert Relevanz │ (1 Call/Control) │ └────────┬───────────┘ │ immer noch unsicher ▼ ┌────────────────────┐ │ Stufe 3: Follow-Up │ ← Nutzer beantwortet Frage │ (Frontend) │ └────────────────────┘ ``` ## Implementierungsreihenfolge ### Phase 1: Regelfilter (1 Tag) 1. Migration: `relevance_conditions` Feld zu `canonical_controls` 2. Seed-Script: Top-20 generische Controls mit Bedingungen versehen (C_TRANSPARENCY, C_EXPLICIT_CONSENT, C_DSFA_REQUIRED, etc.) 3. Filter-Funktion in `agent_analyze_routes.py` 4. Test: Opodo erneut analysieren — C_TRANSPARENCY sollte rausfallen ### Phase 2: LLM-Validierung (1 Tag) 1. Neuer SDK-Endpoint `/sdk/v1/ucca/validate-controls` 2. Integration in den Agent-Workflow 3. Caching-Layer (Redis/Valkey) ### Phase 3: Batch-Seeding (2-3 Tage) 1. Pipeline-Job: Fuer alle 166k Controls `relevance_conditions` generieren (LLM-gestuetzt: "Welche Keywords im Quelltext wuerden diesen Control relevant machen?") 2. Qualitaetspruefung: Stichprobe von 100 Controls manuell validieren ## Betroffene Dateien | Datei | Aenderung | |-------|-----------| | `backend-compliance/compliance/api/agent_analyze_routes.py` | Filter-Integration | | `backend-compliance/compliance/services/relevance_filter.py` | NEU: Regelfilter | | `ai-compliance-sdk/internal/ucca/relevance_filter.go` | NEU: SDK-seitig (alternativ) | | `ai-compliance-sdk/internal/api/handlers/ucca_handlers.go` | Neuer Endpoint | | Migration | `relevance_conditions` Spalte | | `control-pipeline/` | Batch-Seeding Job (Phase 3) | ## Risiken | Risiko | Mitigation | |--------|------------| | Zu aggressive Filterung (False Negatives) | Stufe 1 nur fuer klare Faelle, Stufe 2 als Fallback | | LLM-Kosten bei vielen Controls | Caching + nur high-severity Controls | | Datenbank-Migration auf Production | `ADD COLUMN IF NOT EXISTS` ist non-blocking | | 166k Controls ohne relevance_conditions | Default `{}` = kein Filter = bisheriges Verhalten | ## Testfaelle 1. **Opodo-Test:** C_TRANSPARENCY sollte NICHT mehr empfohlen werden (kein KI-Nachweis) 2. **Chatbot-Anbieter:** C_TRANSPARENCY SOLL empfohlen werden (KI explizit erwaehnt) 3. **Arztpraxis-Website:** C_DSFA_REQUIRED SOLL empfohlen werden (Gesundheitsdaten) 4. **Blog ohne Tracking:** Nur minimale Controls (Impressum, Datenschutzerklaerung)