Kansho/docs/work_orders/detect_self_learning_pipeline.md
Lars 011cc9dd81
Some checks failed
Deploy Development / deploy (push) Successful in 1m0s
Test Suite / pytest-backend (push) Failing after 2m58s
Test Suite / smoke-dev (push) Successful in 0s
Test Suite / frontend-build (push) Successful in 23s
Put student-first detect learning ahead of the teacher call.
Identity-only senses no longer lock a new cue. Learning stages, journal-generate review, and additive docs follow the closed section 6.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 08:59:18 +02:00

12 KiB
Raw Blame History

title status date document_role canonical_functional canonical_technical
Kanshō – Selbstlernende Detect-Pipeline (Konzept und Anforderung) Konzept / Arbeitsauftrag — §6 finalisiert 2026-09-11 2026-09-11 Cursor Implementation Brief / Concept Record docs/architecture/functional/guardrails.md §22.4 docs/architecture/technical/privacy_gateway.md §9.7

Selbstlernende Detect-Pipeline

Dieses Dokument ist das Home für das Zielbild 2026-09-11. Es ersetzt weder guardrails.md noch privacy_gateway.md. Statuswörter ernst nehmen. §6 wurde am 2026-09-11 mit dem Nutzer im Planmodus geschlossen; die Umsetzung folgt diesen Entscheidungen.

Herkunft: explizite Nutzeranforderung und gemeinsame Bewertung in der Konzeptsession 2026-09-11.

1. Ziel

Ein selbstlernender Schutz pro Profil, der über Zeit immer weniger persönliche Klarformen an ein externes LLM gibt und dabei verlässlicher wird.

GLiNER findet neue Spannen. Kanshō entscheidet und merkt (Sinne, Cues, Registry). OpenRouter ist Lehrer und Lückenfüller, nicht Alltag und nicht Identitätsquelle. GLiNER-Gewichte werden zur Laufzeit nicht nachtrainiert; ein gemeinsames Jinkendo-NER-Projekt ist ein späterer, getrennter Dienst (stateless, keine gemeinsame Identität).

Leitbeispiel: Lange Zeit bedeutet „Sushi“ die Partnerin. Am Tag 21 ist „Sushi“ Essen. Ein Lexem-Lock auf Identität und ein Lehrer, der nur noch Platzhalter sieht, machen das Essen unsichtbar. Das darf nicht passieren.

2. Entscheidungsstand

Entschieden

  • Identität bleibt lokal. Klasse-A-Mapping, Klarnamen und Registry gehen nicht an Provider.
  • Keine Wortlisten-UI. Sinne entstehen aus Bestätigungen (Identität / nicht schützenswert).
  • OpenRouter darf Identitäten nicht stillschweigend anlegen oder löschen. Der Mensch entscheidet über neue Identität und über Abweichungen.
  • Cue-Treffer gelten nur für dieses Vorkommen, nicht für die Schreibweise insgesamt.
  • Nur Identity-Hits ohne Non-Identity dürfen einen neuen Cue nicht festnageln (Sushi-Tag-21).
  • Schülerpfad-Reihenfolge: lokal cue-aufgelöste Vorkommen → unklare Homonyme als enger Ausschnitt an das Passage-LLM → GLiNER auf den Rest → Generate mit gebauten Mappings.
  • GLiNER sieht die Originalzeile mit übersprungenen, bereits aufgelösten Offsets, nicht den schon ersetzten Platzhaltertext.
  • Zwei Lernstufen. Umschalten ist eine Admin-Entscheidung, kein Autopilot.
  • Stufe 1 (vollständig): Kontrollaufruf auf den unveränderten Nutzersatz (keine Ersetzungen), parallel der Schülerpfad, Vergleich, bei Uneinigkeit oder neuer Identität Popup, dann lernen.
  • Stufe 2: Lehrer sieht keine cue-sicheren Vorkommen mehr. Dieselbe Vergleichslogik. Am Anfang fehleranfälliger; deshalb nach Stufe 1, nicht als Start.
  • Lehrer-Slice ist der Nutzersatz, nicht der gerenderte Detect-Prompt (kein Mitnehmen von Biografie/Kontext, den GLiNER nicht sieht).
  • Übereinstimmung plus bereits bestätigtes Label: Cue verstärken, kein Popup.
  • GLiNER nicht als alleiniges Detect in die Detect-URL schreiben. Detect-OpenRouter bleibt konfigurierbar.
  • Kein Gateway-Bypass, kein Feature-Flag zum Abschalten der Maskierung.
  • Bestehenden GLiNER-Client, Local-NER-Settings, Cues und Review-UI wiederverwenden, nicht wegwerfen; umverdrahten.
  • Startbetrieb: Lernmodus Stufe 1. Schüler (Cues → Verwandtschaft → Homonym-Mini-LLM bei beiden Sinnen → GLiNER) und Lehrer (unveränderter Nutzersatz) parallel. Diff zum Nutzer. Geprüftes Ergebnis maskiert Generate.
  • Admin: Zielpfad (student) + Lernen automatisch Stufe 1 (learning_full) + Lernen automatisch Stufe 2 (learning_reduced) + Lernen manuell (learning_manual) + Bypass (bypass, alter OpenRouter-Voll-Detect). Bypass entfällt mittelfristig. Default nach Umbau: learning_full. Aliase: learning → learning_full, semantic → bypass.
  • Stufe 2 ist im ersten Schnitt vollständig (Lehrer ohne cue-sichere Oberflächenformen).
  • Lehrer weg: alle Schüler-/GLiNER-Funde zur Bestätigung (gleicher Weg wie manuell).
  • GLiNER weg: im Lernmodus manuelle Review nach lokaler Vorauswahl. Außerhalb Lernmodus: Nutzer bestätigt Klartext-Egress an das öffentliche LLM.
  • Verwandtschaft bleibt eigener lokaler Schüler-Schritt vor GLiNER.
  • Vergleich: gleiche Nennung = gleicher Wortlaut an derselben Stelle oder eine Spanne vollständig in der anderen. Typen person→PERSON usw.; ähnliche schützenswerte Typen gleich; FOOD gegen PERSON immer Diff. Nur bei abweichendem Schutz fragen; gleicher Schutz, anderer Zuschnitt → längere Spanne. Nutzer entscheidet Speise/Person; Cue nicht still ändern; Lehrer-Miss ohne Meldung → kein Popup, Cue bleibt.
  • Diagnose: Zähler ohne Klartext (Einigkeit, nur Schüler, nur Lehrer, Typkonflikt, neue Identität, Cue verstärkt). Keine Langeweile-Kennzahl; Stufe nur per Schalter.
  • Mini-LLM nur wenn beide Sinne schon existieren, auch in Stufe 1.
  • Geltungsbereich: alle persönlichen Detect-Aufrufe (Security-Gateway), einschließlich Journalentwurf.

Bevorzugte Richtung

  • Nach ausreichend langweiliger Abweichung in Stufe 1: Stufe 2, später Betrieb ohne Kontrollaufruf (Schülerpfad allein).
  • Diagnostik zeigt Diff-Art (nur Schüler / nur Lehrer / Typkonflikt), ohne Klartextlabels in Compact-Exports.
  • Fragment-Ausschnitte so eng, dass fremde noch unmaskierte Identitäten nicht mitgehen.
  • Eigenes Jinkendo-Local-Detect als späteres LAN-Projekt (Text rein, Spannen raus, kein Speicher). Nicht in diesem Slice.

Verworfen

  • GLiNER oder OpenRouter als alleiniges Detect.
  • Lexemweites „einmal Person, immer Person“.
  • Lehrer auf bereits komplett vormaskiertem Text in Stufe 1.
  • Online-Fine-Tune von GLiNER auf Journaltext.
  • Gemeinsame Namensliste über Jinkendo-Produkte.
  • Detect-Treffer ohne Nutzer als aktive Identität speichern.

Offen

Keine offenen Punkte aus der Planmodus-Runde 2026-09-11. Frühere §6-Fragen sind unter Entschieden festgehalten.

3. Ziel-Workflow

Nutzersatz
    │
    ├─ Schüler (immer, sobald dieser Pfad gilt)
    │     1. Cue-aufgelöste Vorkommen lokal binden
    │        (Identität maskieren / Nicht-Identität sperren)
    │     2. Unklare Homonyme: enger Ausschnitt → Passage-LLM
    │     3. Rest → GLiNER (Skip bereits gebundener Spannen)
    │     4. Mappings für Generate
    │
    └─ Lehrer (nur Lernmodus)
          Stufe 1: unveränderter Nutzersatz → OpenRouter-Detect
          Stufe 2: Nutzersatz ohne cue-sichere Oberflächenformen
          Vergleich Schüler ↔ Lehrer
          Uneinigkeit / neue Identität → Nutzer → Cue/Sinn
          Einigkeit + bekanntes Label → Cue verstärken

Generate folgt auf geprüfte bzw. schülerseitig gebaute Mappings, ohne zweiten Voll-Detect.

4. Ist-Stand (Code, 2026-09-11)

Nicht mit dem Zielbild verwechseln. Älterer Stand vor der Umsetzung nach §6:

  • _learning_pause hing OpenRouter-Detect an den gerenderten Prompt, dann Verwandtschaft, GLiNER, Cues, Passage, Popup.
  • decision_for_mention nagelte bei nur Identity-Hits jeden neuen Cue fest (Tag-21).
  • Admin: semantic | learning.

Additiv nach Umsetzung §6: Schülerpfad in detect_pipeline.py, Lehrer auf dem Nutzersatz, Admin-Modi student | learning_full | learning_reduced | learning_manual | bypass. Tabellen label_senses, label_sense_cues, pending_mask_reviews bleiben die Lernspeicher.

5. Anforderungen an die Umsetzung (nach Finalisierung)

  1. Policy: decision_for_mention so ändern, dass ein neuer Cue bei nur einem Sinn sichtbar bleibt (nicht automatisch binden). Cue-Hit bleibt bindend.
  2. Schülerpfad als eigene, testbare Funktion; _learning_pause und später semantic hängen daran, sobald §6 das festlegt.
  3. Lehrer Stufe 1: Detect-Schema auf dem Nutzersatz, Offsets vergleichbar machen (GLiNER person|place|… ↔ Detect PERSON|…).
  4. Diff nur auf User-Spans; Lehrer-Miss eines bereits nutzerbestätigten Cues nicht automatisch verlernen.
  5. Popup über vorhandenes MaskReviewPanel, Inhalt = Diff und neue Identitätskandidaten, nicht jedes schon gelöste Cue-Vorkommen.
  6. Admin: zwei Lernstufen wählbar (konkretes Schaltermodell laut §6).
  7. Tests: Tag-21-Sushi (Identity-Hits, Cue Frau vs. neuer Cue „essen“); Diff-Fälle; kein Klartext in Compact-Diagnose; Local-URL-Policy für GLiNER bleibt.
  8. Docs additiv in guardrails.md §22.4, privacy_gateway.md §9.7, admin_diagnostics.md. Bestehende Absätze nicht kürzen. Dieses Work-Order-Dokument als Konzept-Home belassen, bis der Code dem Zielbild entspricht.
  9. Kein Commit/Push, unless explicitly requested.

Nicht in diesem Slice: Fine-Tune, neues NER-Repo, Wortlisten-Editor, Shared-Identity. Journal-Generate-Pause ist durch §6.9 doch im Schnitt (alle persönlichen Detect-Aufrufe).

6. Offene Punkte — geschlossen 2026-09-11

  1. Start ist Stufe 1 Lernen, nicht Schüler-allein und nicht der alte semantic-Alltag. Schüler und Lehrer-Klartext (Nutzersatz) parallel, Diff zum Nutzer, dann Generate.
  2. Admin: Zielpfad + Lernen (automatisch 1 / automatisch 2 / manuell) + Bypass. Bypass mittelfristig weg. Default: learning_full.
  3. Stufe 2 vollständig im ersten Schnitt.
  4. Lehrer weg → manuelle Review aller GLiNER-/Schülerfunde. GLiNER weg → im Lernmodus manuell nach Vorauswahl; sonst Bestätigung vor öffentlichem Klartext-Egress.
  5. Verwandtschaft bleibt eigener lokaler Schritt vor GLiNER.
  6. Vergleich: enthaltene Spanne / gleicher Wortlaut; Mapping inkl. FOOD≠PERSON; nur abweichender Schutz fragt; Cue nicht still ändern; Lehrer-Miss ohne Meldung kein Popup.
  7. Diagnose: Zähler ohne Klartext, keine Langeweile-Kennzahl.
  8. Mini-LLM nur bei schon beiden Sinnen, auch in Stufe 1.
  9. Alle persönlichen Detect-Aufrufe, einschließlich Journalentwurf.

7. Context Bundle für die Umsetzungs-Session

  1. Diese Datei.
  2. docs/architecture/functional/documentation_index.md
  3. docs/architecture/functional/guardrails.md (§22.4, Invarianten)
  4. docs/architecture/technical/privacy_gateway.md (§9.7)
  5. docs/architecture/technical/admin_diagnostics.md
  6. Code: backend/detect_learning.py, backend/dialogue_turn.py, backend/gliner_client.py, frontend/src/pages/AdminProvidersPage.jsx, frontend/src/components/MaskReviewPanel.jsx, backend/tests/test_detect_learning.py

Nicht den ganzen docs/-Ordner laden. Dialog-/MVP-Fachstand nicht stillschweigend festlegen.

8. Prompt für die neue Session

Den folgenden Block unverändert in eine neue Cursor-Session mit frischem Kontextfenster einfügen.

Arbeite im Repo C:\Dev\Kansho. Sprache: Deutsch.

Zuerst in den Planmodus wechseln (SwitchMode → plan). Noch keinen Code schreiben, keine Policy umbauen, nicht committen.

Auftrag: Selbstlernende Detect-Pipeline gemäß
docs/work_orders/detect_self_learning_pipeline.md

Das Dokument ist Konzept-Home. Es ersetzt guardrails.md / privacy_gateway.md nicht. Der Code hängt GLiNER und Cues noch hinter OpenRouter-Detect; decision_for_mention nagelt bei nur Identity-Hits jeden neuen Cue fest. Beides soll weg, aber erst nach Finalisierung der offenen Punkte.

Sofort laden (nur dieses Bundle):
- docs/work_orders/detect_self_learning_pipeline.md (vollständig, besonders §2, §3, §6)
- docs/architecture/functional/documentation_index.md
- docs/architecture/functional/guardrails.md (§22.4 und Invarianten)
- docs/architecture/technical/privacy_gateway.md (§9.7)
- Ist-Code: backend/dialogue_turn.py (_learning_pause), backend/detect_learning.py (decision_for_mention, apply_gliner_if_enabled, auto_resolve_ambiguous)

Danach mit mir im Planmodus §6 der Work-Order Punkt für Punkt schließen. Nicht raten. Nicht „Bevorzugte Richtung“ als Entschieden behandeln. Erst wenn §6 schriftlich entschieden ist, einen knappen Umsetzungsplan vorschlagen (erster Schnitt vs. später). Umsetzung erst nach meiner Freigabe, dann Agent-Modus.

Invarianten, die nicht zur Disposition stehen:
- Identität lokal; kein stilles Identity aus OpenRouter/GLiNER
- keine Wortliste; Sinne/Cues aus Bestätigungen
- Cue gilt pro Vorkommen, nicht lexemweit (Sushi-Tag-21)
- Stufe-1-Lehrer sieht den unveränderten Nutzersatz
- GLiNER nicht als alleiniges Detect in die Detect-URL
- Gateway nicht abschaltbar
- bestehenden GLiNER-Client/Cues/Review-UI umverdrahten, nicht löschen
- Docs additiv; kanonische Kapitel nicht kürzen

Zielbild in einem Satz: Schülerpfad lokal zuerst, Lehrer nur im Lernmodus, zwei Stufen, Mensch bei Diff und neuer Identität.