- Add PIPELINE_VERSION=2 constant and pipeline_version column to canonical_controls and canonical_processed_chunks (migration 062) - Anthropic API decides chunk relevance via null-returns (skip_prefilter) - Annex/appendix chunks explicitly protected in prompts - Fix 6 failing tests (CRYP domain, _process_batch tuple return) - Add TestPipelineVersion + TestRegulationFilter test classes (10 new tests) - Add MkDocs page: control-generator-pipeline.md (541 lines) - Update canonical-control-library.md with v2 pipeline diagram - Update testing.md with 71-test breakdown table Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
541 lines
19 KiB
Markdown
541 lines
19 KiB
Markdown
# Control Generator Pipeline
|
|
|
|
Automatische Generierung von Canonical Controls aus dem gesamten RAG-Korpus (~105.000 Chunks aus Gesetzen, Verordnungen und Standards).
|
|
|
|
**Backend:** `backend-compliance/compliance/services/control_generator.py`
|
|
**Routes:** `backend-compliance/compliance/api/control_generator_routes.py`
|
|
**API-Prefix:** `/api/compliance/v1/canonical/generate`
|
|
|
|
---
|
|
|
|
## Pipeline-Uebersicht
|
|
|
|
Die Pipeline durchlaeuft 7 Stufen, um aus RAG-Chunks eigenstaendige Security/Compliance Controls zu erzeugen:
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[1. RAG Scan] -->|Alle Chunks laden| B[2. License Classify]
|
|
B -->|Rule 1/2| C[3a. Structure Batch]
|
|
B -->|Rule 3| D[3b. Reform Batch]
|
|
C --> E[4. Harmonize]
|
|
D --> E
|
|
E -->|Duplikat| F[Als Duplikat markieren]
|
|
E -->|Neu| G[5. Anchor Search]
|
|
G --> H[6. Store Control]
|
|
H --> I[7. Mark Processed]
|
|
```
|
|
|
|
| Stufe | Name | Beschreibung |
|
|
|-------|------|-------------|
|
|
| 1 | **RAG Scan** | Laedt unverarbeitete Chunks aus Qdrant (Scroll-API), filtert per SHA-256-Hash |
|
|
| 2 | **License Classify** | Bestimmt die Lizenzregel (Rule 1/2/3) anhand `regulation_code` |
|
|
| 3a | **Structure (Batch)** | Rule 1+2: Strukturiert Originaltext als Control (Anthropic API) |
|
|
| 3b | **Reform (Batch)** | Rule 3: Vollstaendige Reformulierung ohne Originaltext (Anthropic API) |
|
|
| 4 | **Harmonize** | Embedding-basierte Duplikaterkennung (bge-m3, Cosine > 0.85) |
|
|
| 5 | **Anchor Search** | Findet Open-Source-Referenzen (OWASP, NIST, ENISA) |
|
|
| 6 | **Store** | Persistiert Control in `canonical_controls` mit Metadaten |
|
|
| 7 | **Mark Processed** | Markiert jeden Chunk als verarbeitet (auch bei Skip/Error/Duplikat) |
|
|
|
|
---
|
|
|
|
## Pipeline-Versionen
|
|
|
|
Die Pipeline hat zwei Versionen. Die Version wird als `pipeline_version` auf `canonical_controls` und `canonical_processed_chunks` gespeichert.
|
|
|
|
### v1 (Original)
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| **Vorfilter** | Lokales LLM (llama3.2 3B) entscheidet ob Chunk relevant |
|
|
| **Anthropic-Prompt** | Alter Prompt ohne null-Skip |
|
|
| **Annexe/Anhaenge** | Kein Schutz — wurden haeufig faelschlich als irrelevant uebersprungen |
|
|
| **`pipeline_version`** | `1` |
|
|
|
|
### v2 (Aktuell)
|
|
|
|
| Eigenschaft | Wert |
|
|
|-------------|------|
|
|
| **Vorfilter** | Optional (`skip_prefilter`). Wenn aktiviert, entscheidet Anthropic API selbst |
|
|
| **Anthropic-Prompt** | Neuer Prompt mit **null-Skip**: API gibt `null` fuer Chunks ohne Anforderung zurueck |
|
|
| **Annexe/Anhaenge** | Explizit geschuetzt — Prompt-Anweisung: "Anhaenge/Annexe enthalten oft KONKRETE technische Anforderungen — diese MUESSEN als Control erfasst werden!" |
|
|
| **`pipeline_version`** | `2` |
|
|
|
|
#### Wesentliche Aenderungen v1 → v2
|
|
|
|
1. **Relevanz-Entscheidung an Anthropic delegiert** — Das lokale LLM (Vorfilter) ist optional. Die Anthropic API entscheidet selbst, welche Chunks Controls enthalten, indem sie `null` fuer irrelevante Chunks zurueckgibt.
|
|
2. **null-Skip im JSON-Array** — Das Ergebnis-Array enthaelt `null`-Eintraege fuer Chunks ohne umsetzbare Anforderung. Kein separater Vorfilter-Schritt noetig.
|
|
3. **Annexe/Anhaenge geschuetzt** — Explizite Prompt-Anweisung verhindert, dass technische Anforderungen in Anhaengen uebersprungen werden.
|
|
|
|
#### Datenbank-Feld
|
|
|
|
```sql
|
|
-- Migration 062
|
|
ALTER TABLE canonical_controls
|
|
ADD COLUMN pipeline_version smallint NOT NULL DEFAULT 1;
|
|
|
|
ALTER TABLE canonical_processed_chunks
|
|
ADD COLUMN pipeline_version smallint NOT NULL DEFAULT 1;
|
|
```
|
|
|
|
Neue Controls erhalten automatisch `pipeline_version = 2`. Bestehende (v1) behalten `1`, damit sie spaeter identifiziert und ggf. reprocessiert werden koennen.
|
|
|
|
---
|
|
|
|
## Konfiguration
|
|
|
|
### Request-Parameter (`GenerateRequest`)
|
|
|
|
| Parameter | Typ | Default | Beschreibung |
|
|
|-----------|-----|---------|-------------|
|
|
| `collections` | `List[str]` | Alle 5 Collections | Qdrant-Collections zum Durchsuchen |
|
|
| `domain` | `str` | — | Filter auf eine Domain (z.B. `AUTH`, `NET`) |
|
|
| `regulation_filter` | `List[str]` | — | Prefix-Matching auf `regulation_code` (z.B. `["eu_2023_1230", "owasp_"]`) |
|
|
| `skip_prefilter` | `bool` | `false` | Ueberspringt lokalen LLM-Vorfilter, sendet alle Chunks an die Anthropic API |
|
|
| `batch_size` | `int` | `5` | Chunks pro Anthropic-API-Call |
|
|
| `max_controls` | `int` | `50` | Maximale Anzahl Controls pro Job (0 = unbegrenzt) |
|
|
| `max_chunks` | `int` | `1000` | Maximale Chunks pro Job (0 = unbegrenzt, respektiert Dokumentgrenzen) |
|
|
| `skip_web_search` | `bool` | `false` | Ueberspringt Web-Suche in der Anchor-Findung (Stufe 5) |
|
|
| `dry_run` | `bool` | `false` | Trockenlauf ohne DB-Schreibzugriffe (synchron, mit Controls im Response) |
|
|
|
|
!!! info "`regulation_filter` — Prefix-Matching"
|
|
Der Filter vergleicht den `regulation_code` jedes Chunks per Prefix.
|
|
Beispiel: `["eu_2023_1230"]` erfasst nur Chunks aus der Maschinenverordnung.
|
|
`["owasp_"]` erfasst alle OWASP-Dokumente (OWASP ASVS, OWASP SAMM, etc.).
|
|
Gross-/Kleinschreibung wird ignoriert.
|
|
|
|
### Umgebungsvariablen
|
|
|
|
| Variable | Default | Beschreibung |
|
|
|----------|---------|-------------|
|
|
| `ANTHROPIC_API_KEY` | — | API-Key fuer Anthropic Claude (Pflicht) |
|
|
| `CONTROL_GEN_ANTHROPIC_MODEL` | `claude-sonnet-4-6` | Anthropic-Modell fuer Strukturierung/Reformulierung |
|
|
| `OLLAMA_URL` | `http://host.docker.internal:11434` | Lokaler Ollama-Server (Vorfilter + QA) |
|
|
| `CONTROL_GEN_OLLAMA_MODEL` | `qwen3.5:35b-a3b` | Lokales LLM-Modell fuer Vorfilter und QA-Arbitrierung |
|
|
| `CONTROL_GEN_LLM_TIMEOUT` | `180` | Timeout in Sekunden pro Anthropic-API-Call |
|
|
|
|
### Pipeline-interne Konstanten
|
|
|
|
| Konstante | Wert | Beschreibung |
|
|
|-----------|------|-------------|
|
|
| `PIPELINE_VERSION` | `2` | Aktuelle Pipeline-Version |
|
|
| `HARMONIZATION_THRESHOLD` | `0.85` | Cosine-Similarity-Schwelle fuer Duplikaterkennung |
|
|
| `max_tokens` | `8192` | Maximale Token-Laenge der LLM-Antwort |
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
Alle Endpoints unter `/api/compliance/v1/canonical/`.
|
|
|
|
### Uebersicht
|
|
|
|
| Methode | Pfad | Beschreibung |
|
|
|---------|------|-------------|
|
|
| `POST` | `/generate` | Generierungs-Job starten (laeuft im Hintergrund) |
|
|
| `GET` | `/generate/status/{job_id}` | Status eines laufenden Jobs abfragen |
|
|
| `GET` | `/generate/jobs` | Alle Jobs auflisten (paginiert) |
|
|
| `GET` | `/generate/processed-stats` | Verarbeitungsstatistik pro Collection |
|
|
| `GET` | `/generate/review-queue` | Controls zur manuellen Pruefung |
|
|
| `POST` | `/generate/review/{control_id}` | Review eines einzelnen Controls abschliessen |
|
|
| `POST` | `/generate/bulk-review` | Bulk-Review nach `release_state` |
|
|
| `POST` | `/generate/qa-reclassify` | QA-Reklassifizierung bestehender Controls |
|
|
| `GET` | `/blocked-sources` | Gesperrte Quellen (Rule 3) auflisten |
|
|
| `POST` | `/blocked-sources/cleanup` | Cleanup-Workflow fuer gesperrte Quellen starten |
|
|
|
|
---
|
|
|
|
### POST `/v1/canonical/generate` — Job starten
|
|
|
|
Startet einen Generierungs-Job im Hintergrund. Gibt sofort eine `job_id` zurueck.
|
|
|
|
**Request:**
|
|
|
|
```json
|
|
{
|
|
"collections": ["bp_compliance_gesetze"],
|
|
"regulation_filter": ["eu_2023_1230"],
|
|
"skip_prefilter": false,
|
|
"batch_size": 5,
|
|
"max_chunks": 500,
|
|
"max_controls": 0,
|
|
"skip_web_search": false,
|
|
"dry_run": false
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
|
|
```json
|
|
{
|
|
"job_id": "a1b2c3d4-...",
|
|
"status": "running",
|
|
"message": "Generation started in background. Poll /generate/status/{job_id} for progress."
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
# Alle Chunks der Maschinenverordnung verarbeiten
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{
|
|
"collections": ["bp_compliance_ce"],
|
|
"regulation_filter": ["eu_2023_1230"],
|
|
"max_chunks": 200,
|
|
"batch_size": 5
|
|
}'
|
|
```
|
|
|
|
```bash
|
|
# Dry Run: Keine DB-Aenderungen, Controls im Response
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{
|
|
"collections": ["bp_compliance_gesetze"],
|
|
"max_chunks": 10,
|
|
"dry_run": true
|
|
}'
|
|
```
|
|
|
|
```bash
|
|
# Ohne Vorfilter: Alle Chunks direkt an Anthropic API
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{
|
|
"collections": ["bp_compliance_gesetze"],
|
|
"regulation_filter": ["bdsg"],
|
|
"skip_prefilter": true,
|
|
"max_chunks": 100
|
|
}'
|
|
```
|
|
|
|
!!! warning "Kosten beachten"
|
|
Ohne `regulation_filter` und mit `max_chunks: 0` werden **alle** ~105.000 Chunks verarbeitet.
|
|
Das verursacht erhebliche Anthropic-API-Kosten (~$700).
|
|
|
|
---
|
|
|
|
### GET `/v1/canonical/generate/status/{job_id}` — Job-Status
|
|
|
|
Gibt den vollstaendigen Status eines Jobs zurueck inkl. Metriken und Fehler.
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
curl https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/status/a1b2c3d4-... \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"id": "a1b2c3d4-...",
|
|
"status": "completed",
|
|
"total_chunks_scanned": 500,
|
|
"controls_generated": 48,
|
|
"controls_verified": 45,
|
|
"controls_needs_review": 3,
|
|
"controls_too_close": 0,
|
|
"controls_duplicates_found": 12,
|
|
"controls_qa_fixed": 5,
|
|
"config": { "..." },
|
|
"started_at": "2026-03-17T10:00:00+00:00",
|
|
"completed_at": "2026-03-17T10:15:32+00:00"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/v1/canonical/generate/jobs` — Alle Jobs
|
|
|
|
Paginierte Liste aller Generierungs-Jobs.
|
|
|
|
**Query-Parameter:**
|
|
|
|
| Parameter | Default | Beschreibung |
|
|
|-----------|---------|-------------|
|
|
| `limit` | `20` | Anzahl Jobs (1-100) |
|
|
| `offset` | `0` | Offset fuer Paginierung |
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
curl "https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/jobs?limit=5" \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/v1/canonical/generate/review-queue` — Review-Queue
|
|
|
|
Listet Controls auf, die eine manuelle Pruefung benoetigen.
|
|
|
|
**Query-Parameter:**
|
|
|
|
| Parameter | Default | Beschreibung |
|
|
|-----------|---------|-------------|
|
|
| `release_state` | `needs_review` | Filter: `needs_review`, `too_close`, `duplicate` |
|
|
| `limit` | `50` | Anzahl (1-200) |
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
curl "https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/review-queue?release_state=needs_review&limit=10" \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/v1/canonical/generate/review/{control_id}` — Review abschliessen
|
|
|
|
Schliesst die manuelle Pruefung eines Controls ab.
|
|
|
|
**Request:**
|
|
|
|
```json
|
|
{
|
|
"action": "approve",
|
|
"release_state": "draft",
|
|
"notes": "Inhaltlich korrekt, Severity passt."
|
|
}
|
|
```
|
|
|
|
**Moegliche `action`-Werte:**
|
|
|
|
| Action | Neuer State | Beschreibung |
|
|
|--------|-------------|-------------|
|
|
| `approve` | `draft` (oder per `release_state` ueberschreiben) | Control freigeben |
|
|
| `reject` | `deprecated` | Control verwerfen |
|
|
| `needs_rework` | `needs_review` | Zurueck in die Queue |
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/review/AUTH-042 \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{"action": "approve", "release_state": "draft"}'
|
|
```
|
|
|
|
---
|
|
|
|
### POST `/v1/canonical/generate/bulk-review` — Bulk-Review
|
|
|
|
Aendert den `release_state` aller Controls, die einen bestimmten State haben.
|
|
|
|
**Request:**
|
|
|
|
```json
|
|
{
|
|
"release_state": "needs_review",
|
|
"action": "approve",
|
|
"new_state": "draft"
|
|
}
|
|
```
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
# Alle needs_review Controls auf draft setzen
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/bulk-review \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{"release_state": "needs_review", "action": "approve", "new_state": "draft"}'
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/v1/canonical/generate/processed-stats` — Verarbeitungsstatistik
|
|
|
|
Liefert Statistiken pro RAG-Collection.
|
|
|
|
**Beispiel:**
|
|
|
|
```bash
|
|
curl https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/processed-stats \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000'
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"stats": [
|
|
{
|
|
"collection": "bp_compliance_gesetze",
|
|
"processed_chunks": 45200,
|
|
"direct_adopted": 1850,
|
|
"llm_reformed": 120,
|
|
"skipped": 43230,
|
|
"total_chunks_estimated": 0,
|
|
"pending_chunks": 0
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Kosten und Performance
|
|
|
|
### Kostenabschaetzung
|
|
|
|
| Metrik | Wert |
|
|
|--------|------|
|
|
| **Kosten pro Chunk** | ~$0.0067 (Anthropic API, Batch-Modus) |
|
|
| **Yield (Controls/Chunks)** | ~4.5-10% (nur Chunks mit konkreten Anforderungen erzeugen Controls) |
|
|
| **Vorfilter-Ersparnis** | ~55% der API-Kosten wenn aktiviert (irrelevante Chunks werden lokal aussortiert) |
|
|
|
|
### Performance-Kennzahlen
|
|
|
|
| Metrik | Wert |
|
|
|--------|------|
|
|
| **Batch-Groesse** | 5 Chunks pro API-Call (Default) |
|
|
| **API-Aufrufe Reduktion** | ~80% weniger Aufrufe durch Batching |
|
|
| **LLM-Timeout** | 180 Sekunden pro Call |
|
|
| **QA-Overhead** | ~2s pro Control (nur bei Disagreement, ~10-15% der Controls) |
|
|
|
|
### RAG Collections
|
|
|
|
| Collection | Inhalte | Erwartete Regel |
|
|
|-----------|---------|----------------|
|
|
| `bp_compliance_gesetze` | Deutsche Gesetze (BDSG, TTDSG, TKG etc.) | Rule 1 |
|
|
| `bp_compliance_datenschutz` | Datenschutz-Leitlinien + EU-Verordnungen | Rule 1/2 |
|
|
| `bp_compliance_ce` | CE/Sicherheitsstandards | Rule 1/2/3 |
|
|
| `bp_dsfa_corpus` | DSFA-Korpus | Rule 1/2 |
|
|
| `bp_legal_templates` | Rechtsvorlagen | Rule 1 |
|
|
|
|
### Aktuelle Groessenordnung
|
|
|
|
| Metrik | Wert |
|
|
|--------|------|
|
|
| RAG-Chunks gesamt | ~105.000 (nach Dedup 2026-03-16) |
|
|
| Verarbeitete Chunks | ~105.000 |
|
|
| Generierte Controls | **~4.738** |
|
|
| Konversionsrate | ~4,5% |
|
|
|
|
---
|
|
|
|
## Lizenz-Klassifikation (3-Regel-System)
|
|
|
|
Jeder Chunk wird basierend auf `regulation_code` einer Lizenzregel zugeordnet:
|
|
|
|
| Regel | Typ | Original erlaubt? | Beispiele |
|
|
|-------|-----|-------------------|----------|
|
|
| **Rule 1** (free_use) | EU-Gesetze, NIST, DE-Gesetze, Public Domain | Ja | DSGVO, BDSG, NIS2, AI Act |
|
|
| **Rule 2** (citation_required) | CC-BY, CC-BY-SA | Ja, mit Zitation | OWASP ASVS, OWASP SAMM |
|
|
| **Rule 3** (restricted) | Proprietaer | Nein, volle Reformulierung | BSI TR-03161, ISO 27001 |
|
|
|
|
### Verarbeitung nach Regel
|
|
|
|
- **Rule 1+2 → `_structure_batch()`**: Anthropic strukturiert den Originaltext als Control. Ein API-Call fuer den gesamten Batch.
|
|
- **Rule 3 → `_reformulate_batch()`**: Anthropic reformuliert vollstaendig — kein Originaltext, keine Quellennamen. Ein API-Call fuer den gesamten Batch.
|
|
|
|
### Batch Processing
|
|
|
|
Die Pipeline sammelt Chunks in Batches (Default: 5 Chunks) und sendet sie in einem einzigen Anthropic-API-Call.
|
|
|
|
1. Relevante Chunks werden mit Lizenz-Info in `pending_batch` gesammelt
|
|
2. Bei `batch_size` erreicht → `_flush_batch()`
|
|
3. Batch wird nach Lizenzregel getrennt: Rule 1+2 → `_structure_batch()`, Rule 3 → `_reformulate_batch()`
|
|
4. Ergebnis: JSON-Array mit genau N Elementen (`null` fuer irrelevante Chunks)
|
|
|
|
**Fallback:** Bei Batch-Fehler (Timeout, Parsing-Error) wird automatisch auf Einzelverarbeitung zurueckgefallen.
|
|
|
|
---
|
|
|
|
## Chunk-Tracking (Processed Chunks)
|
|
|
|
### Tabelle `canonical_processed_chunks`
|
|
|
|
| Spalte | Typ | Beschreibung |
|
|
|--------|-----|-------------|
|
|
| `chunk_hash` | VARCHAR(64) | SHA-256 Hash des Chunk-Textes |
|
|
| `collection` | VARCHAR(100) | Qdrant-Collection |
|
|
| `regulation_code` | VARCHAR(100) | Quell-Regulation (z.B. `bdsg`, `eu_2016_679`) |
|
|
| `license_rule` | INTEGER | 1, 2 oder 3 |
|
|
| `processing_path` | VARCHAR(20) | Wie der Chunk verarbeitet wurde |
|
|
| `generated_control_ids` | JSONB | UUIDs der generierten Controls |
|
|
| `pipeline_version` | SMALLINT | Pipeline-Version (1 oder 2) |
|
|
| `job_id` | UUID | Referenz auf den Generierungs-Job |
|
|
|
|
**UNIQUE Constraint:** `(chunk_hash, collection, document_version)` — verhindert Doppelverarbeitung.
|
|
|
|
### Processing Paths
|
|
|
|
| Wert | Stufe | Bedeutung |
|
|
|------|-------|-----------|
|
|
| `prefilter_skip` | 2 | Lokaler LLM-Vorfilter: Chunk nicht relevant |
|
|
| `structured` | 3a | Einzelner Chunk strukturiert (Rule 1/2) |
|
|
| `structured_batch` | 3a | Batch-Strukturierung (Rule 1/2) |
|
|
| `llm_reform` | 3b | Einzelner Chunk reformuliert (Rule 3) |
|
|
| `llm_reform_batch` | 3b | Batch-Reformulierung (Rule 3) |
|
|
| `no_control` | 3 | LLM konnte kein Control ableiten (null im Array) |
|
|
| `store_failed` | 6 | DB-Speichern fehlgeschlagen |
|
|
| `error` | — | Unerwarteter Fehler |
|
|
|
|
---
|
|
|
|
## QA Validation (Automatische Qualitaetspruefung)
|
|
|
|
Die QA-Stufe validiert die Klassifizierung jedes generierten Controls:
|
|
|
|
1. **LLM-Category:** Anthropic liefert `category` und `domain` im JSON-Response
|
|
2. **Keyword-Detection:** `_detect_category(chunk.text)` liefert eine zweite Meinung
|
|
3. **Stimmen beide ueberein?** → Schneller Pfad (kein QA noetig)
|
|
4. **Bei Disagreement:** Lokales LLM (Ollama) arbitriert
|
|
5. **Auto-Fix:** Category/Domain werden automatisch korrigiert
|
|
|
|
Die QA-Metriken werden in `generation_metadata` gespeichert:
|
|
|
|
```json
|
|
{
|
|
"qa_category_fix": {"from": "authentication", "to": "finance", "reason": "IFRS-Thema"},
|
|
"qa_domain_fix": {"from": "AUTH", "to": "FIN", "reason": "Finanzregulierung"}
|
|
}
|
|
```
|
|
|
|
### QA-Reklassifizierung bestehender Controls
|
|
|
|
```bash
|
|
# Dry Run: Welche AUTH-Controls sind falsch klassifiziert?
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/qa-reclassify \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{"limit": 50, "dry_run": true, "filter_domain_prefix": "AUTH"}'
|
|
|
|
# Korrekturen anwenden:
|
|
curl -X POST https://api-dev.breakpilot.ai/api/compliance/v1/canonical/generate/qa-reclassify \
|
|
-H 'Content-Type: application/json' \
|
|
-H 'X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000' \
|
|
-d '{"limit": 50, "dry_run": false, "filter_domain_prefix": "AUTH"}'
|
|
```
|
|
|
|
---
|
|
|
|
## Quelldateien
|
|
|
|
| Datei | Beschreibung |
|
|
|-------|-------------|
|
|
| `backend-compliance/compliance/services/control_generator.py` | 7-Stufen-Pipeline mit Batch Processing |
|
|
| `backend-compliance/compliance/api/control_generator_routes.py` | REST API Endpoints |
|
|
| `backend-compliance/compliance/services/license_gate.py` | Lizenz-Gate-Logik |
|
|
| `backend-compliance/compliance/services/similarity_detector.py` | Too-Close-Detektor (5 Metriken) |
|
|
| `backend-compliance/compliance/services/rag_client.py` | RAG-Client (Qdrant Search + Scroll) |
|
|
| `backend-compliance/migrations/046_control_generator.sql` | Job-Tracking, Chunk-Tracking Tabellen |
|
|
| `backend-compliance/migrations/048_processing_path_expand.sql` | Erweiterte Processing-Path-Werte |
|
|
| `backend-compliance/migrations/062_pipeline_version.sql` | `pipeline_version` Spalte |
|
|
| `backend-compliance/tests/test_control_generator.py` | 15 Tests (Lizenz, Domain, Batch, Pipeline) |
|
|
|
|
---
|
|
|
|
## Verwandte Dokumentation
|
|
|
|
- [Canonical Control Library (CP-CLIB)](canonical-control-library.md) — Domains, Datenmodell, Too-Close-Detektor, CI/CD Validation
|
|
- [Multi-Layer Control Architecture](canonical-control-library.md#multi-layer-control-architecture) — 10-Stage Pipeline-Erweiterung mit Obligations, Patterns, Crosswalk
|