274 lines
31 KiB
Markdown
274 lines
31 KiB
Markdown
<!-- status: done -->
|
||
<!-- started: 2026-06-02 -->
|
||
<!-- component: gateway | ui-nyla | platform -->
|
||
|
||
# PO-Cleanup: Chatbot-Entfernung + Neutralisierung (Quellen/Felder & Denormalisierung) + Dokumentengenerierung
|
||
|
||
## Beschreibung und Kontext
|
||
|
||
Vier zusammenhaengende Aufraeum-/Verbesserungsarbeiten an der Plattform:
|
||
|
||
- **A0 (Cleanup, dringend):** Das Feature `chatbot` wird nicht mehr benoetigt und soll **vollstaendig aus dem Code** entfernt werden (UI + Backend: Routen, Interfaces, Datamodels, Methoden, RBAC-/i18n-/Registry-Hooks, Tests). Zusaetzlich: **LangChain/LangGraph komplett entfernen** (Deps + Code) und die verbleibenden Nutzer (`realEstate`-BZO-Extraktion, `ChatStreamingHelper`) auf die **regulaere AI-Service-Nutzung** umstellen, wie alle anderen Nutzer im System. **Wiki nachfuehren:** Chatbot-Komponente in der aktuellen Doku entfernen bzw. ins Archiv verschieben. Scope: **keine DB-Zeilen-Bereinigung** (Feature-/Instanz-Rows, RBAC-Rollen, Drop `poweron_chatbot` separat).
|
||
- **A1 (Neutralisierung — Anreicherung/Denormalisierung):** Pruefen, dass denormalisierte (rueckuebersetzte) Inhalte **nie** persistiert werden, und einen sicheren Agent-Pfad bereitstellen, der Platzhalter ausschliesslich lokal (Private-LLM-Mapping) rueckuebersetzt und zum **Download ohne Speicherung** zurueckgibt.
|
||
- **A2 (Neutralisierung — Quellen/Felder):** Die Feld-Neutralisierung bei `FeatureDataSource`-Abfragen so korrigieren, dass Datensaetze nicht unbrauchbar werden: Strings immer (substring-basiert) neutralisieren, Binary droppen, andere Typen nur bei explizitem Feld-Flag — vererbungs- und typbewusst.
|
||
- **A3 (Dokumentengenerierung):** Dokumente sehen heute alle gleich aus (ein Standard-Style). Typ-spezifisches Styling (z. B. Klageschrift vs. Marketing mit Bildern) ermoeglichen und die Eignung der Renderer fuer **sehr grosse Dokumente** (z. B. 1000-seitiges Word-Buch mit eingebetteten Bildern) klaeren/verbessern.
|
||
|
||
**Business-Treiber:** Reports/Dokumente sind das sichtbare Endprodukt beim Kunden; Neutralisierung ist Compliance-kritisch (kein Klartext-Leak in Storage). Chatbot-Reste erhoehen Wartungslast und RBAC-/i18n-Rauschen.
|
||
|
||
**Risiko bei Nicht-Umsetzung:** A0 — toter Code + verwirrende Admin-UI. A1 — Datenschutzrisiko (Klartext im Storage) und ein dokumentierter, aber nicht implementierter Pfad. A2 — neutralisierte DB-Datensaetze sind fuer den Sub-Agent unbrauchbar bzw. inkonsistent gegenueber der UI. A3 — Reports wirken unprofessionell und grosse Dokumente koennen OOM/Timeout verursachen.
|
||
|
||
**Abhaengigkeiten:** A1 und A2 nutzen dieselbe `NeutralizationService`-Engine; aenderungen an der dokumentierten Invariante in [b-reference/platform/neutralization.md](../../b-reference/platform/neutralization.md) + [e-compliance/neutralisierung-detail.md](../../e-compliance/neutralisierung-detail.md). A3 beruehrt den ADR aus [4-done/2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md) (bewusste Entscheidung GEGEN Theme-Presets).
|
||
|
||
## Fokus und kritische Details
|
||
|
||
### A0
|
||
- Feature-Discovery ist **glob-basiert** (`loadFeatureRouters` / `loadFeatureMainModules` in `modules/system/registry.py`) — Loeschen des Ordners ist boot-sicher; der Loader ueberspringt fehlende Module.
|
||
- **`chatbot`-Feature** (`featureCode=chatbot`, LangGraph, DB `poweron_chatbot`, `ChatbotConversation/Message/Document/Log`) ist **klar getrennt** vom generischen Agent-**Chat** (`datamodelChat.py`: `ChatWorkflow/ChatMessage`, Workspace). Letzteres **bleibt**.
|
||
- `methodChatbot` ist chatbot-spezifisch und wird entfernt; `methodAi` ist **unabhaengig** und bleibt.
|
||
- `WorkflowModeEnum.WORKFLOW_CHATBOT` in `datamodelChat.py` wird ausserhalb der Datei nicht referenziert — Datei bleibt, nur das Enum-Element + `frontend_options`-Eintrag entfernen.
|
||
- **LangChain/LangGraph wird komplett entfernt.** Die einzigen Nicht-Chatbot-Nutzer sind:
|
||
- `realEstate/bzoExtractionLangGraph.py`: nutzt `langgraph.graph.StateGraph` nur als **triviale Orchestrierung**. `create_bzo_extraction_graph()` ist eine lineare 4-Knoten-Pipeline aus reinen Python-/Regex-Funktionen (`classify_and_assemble` -> `extract_zones_and_tables` -> `extract_rules`) **ohne LLM** -> ersetzbar durch sequenzielle Funktionsaufrufe. `create_bzo_params_extraction_graph()` ist ein **Ein-Knoten-Graph** um `llm_extract_bauzone_params_node`, der den LLM-Call **bereits ueber `ai_service.callAiPlanning(...)`** macht (also schon regulaerer AI-Service) -> Knoten direkt awaiten. Es ist **keine** LangChain-Model-Bridge noetig.
|
||
- `serviceCenter/core/serviceStreaming/helpers.py` (`ChatStreamingHelper`): nutzt `langchain_core.messages`; **einzige Konsumenten sind die Chatbot-Module** (mainChatbot/service/chatbot, in A0 entfernt) -> nach A0 unbenutzt, kann mit `helpers.py` + den `serviceStreaming`-Exports entfernt werden.
|
||
- `requirements.txt`: `langchain`, `langchain-core`, `langgraph`, `langchain-tavily`, `nest-asyncio` (nur fuer LangGraph) entfernen; `requirements.lock` neu erzeugen.
|
||
- `AdminFeatureAccessPage.tsx` traegt die meisten UI-Referenzen (~82) — chirurgisch, nicht Datei loeschen.
|
||
|
||
### A1
|
||
- Reverse-Resolution ist ein **DB-Mapping-Lookup** (`NeutralizationService.resolveText`: `[typ.uuid]` -> `DataNeutralizerAttributes.originalText`), **kein** LLM-Call. Der Private-LLM macht nur die **Vorwaerts**-Erkennung. Das ist der datenschutzsichere Pfad (lokal, deterministisch, kein externes Modell sieht Klartext).
|
||
- `_rehydrateResponse()` in `mainServiceAi.py` ist **toter Code** (keine Call-Sites), die Docstrings behaupten aber automatische Rehydration — Chat persistiert die Modell-Antwort **wie geliefert** (kein Re-Save mit Klartext). Doc/Impl-Mismatch.
|
||
- Tatsaechliche Klartext-Risiken liegen NICHT bei der Denormalisierung, sondern bei: `downloadFromDataSource` (Roh-Bytes at rest), `writeFile`/`renderDocument` (agent-komponierter Inhalt), `RoundMemory.fullData`.
|
||
|
||
### A2
|
||
- Aktuell: `_neutralizeRowFields` ersetzt den **ganzen Feldwert** durch `[NEUT.<field>.<hash>]`, nur fuer explizit gelistete `neutralizeFields`; die Maskenliste in `_featureSubAgentTools.py` ignoriert **vererbte** `neutralize`-Flags zur Query-Zeit; keine Typ-Verzweigung; Binary wird zu `"<binary N bytes>"` stringifiziert und ggf. gehasht (nicht gedroppt).
|
||
- Das ist die **heute dokumentierte** Invariante (neutralization.md Failsafe 5/6) — A2 aendert sie bewusst.
|
||
- Substring-Neutralisierung pro String-Zelle via Private-LLM erzeugt Latenz/Kosten bei grossen Result-Sets — Batching + bestehender 5-Min-Result-Cache als Mitigation.
|
||
|
||
### A3
|
||
- JSON-Dokumentmodell + Unified-Style-Schema sind ein **Asset**, nicht das Problem.
|
||
- Ursache "alle Dokumente gleich": `resolveStyle(None)` injiziert immer `DEFAULT_STYLE` und reicht es truthy an die Renderer (`mainServiceGeneration.py` ~L410/L475); der Agent setzt `style` selten; `documentTheme` ist **deklariert, aber nicht verkabelt** (`methodAi.py`). Renderer sind in Ordnung — **Orchestrierung** ist die Luecke.
|
||
- **ADR-Spannung:** [2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md) entschied bewusst GEGEN Theme-Presets/Mandate-CI und FUER "Agent fuellt generischen Style-Block". Der Wunsch nach typ-spezifischem Styling (Klageschrift/Marketing) wird damit nur erreicht, wenn der Agent den Style wirklich treibt. Vorschlag (ADR-konform): Presets als **smarte Defaults**, die der Agent waehlt und ueberschreiben kann — nicht als harte Vorgabe.
|
||
- Grosse Dokumente: voll **in-memory**, Bilder als **base64 im JSON**, **kein** Streaming (reportlab `doc.build`, python-docx `Document()`). Das ist der echte Blocker fuer 1000 Seiten + Bilder.
|
||
|
||
#### A3 Grossdokument-Analyse & Empfehlung (2026-06-02, AC15 — Schritt 1+2 UMGESETZT)
|
||
|
||
Status: **Schritt 1+2 umgesetzt+getestet; Schritt 3 (HTML-Backend) bewusst geschlossen (nein).** Theming (AC13) ist umgesetzt+getestet.
|
||
|
||
Konkrete Engpaesse (mit Fundstellen):
|
||
- **Ein grosses JSON haelt ALLE Bild-Bytes gleichzeitig.** `_mediaTools._renderDocument` (L110–185) loest `file:fileId`-Bilder VOR `renderReport` zu `base64Data` im JSON auf; PDF/DOCX-Renderer (`_renderJsonImage`) lesen ausschliesslich `base64Data`/Data-URI. → Peak-Memory ~ Summe aller Bilder (base64 ≈ +33%).
|
||
- **Voll-in-memory Build:** `rendererPdf` baut komplette `story`-Liste + `doc.build` (L198–245); `rendererDocx` baut `Document()` und `doc.save` (L122–180). Keine Section-/Seiten-Chunking, kein Flush.
|
||
|
||
Umsetzungsplan (jeweils einzeln testbar):
|
||
1. **Lazy File-Ref-Bilder — UMGESETZT 2026-06-02:** Block-Bilder behalten `fileId` statt vorab-`base64Data`. `renderReport(imageResolver=fileId->bytes)` setzt einen Per-Render-Resolver am Renderer (`BaseRenderer._lazyResolveImageBase64`); PDF/DOCX `_renderJsonImage` loesen on-demand auf. `renderDocument` haelt fuer pdf/docx Bilder als Referenz und speist den Resolver aus Knowledge-Chunks/`chat.getFileData`. DOCX: echter Ein-Bild-Speicher (python-docx kopiert Bytes sofort ins Package). PDF: vermeidet base64-Overhead + JSON-Retention; **voll-streamendes PDF (reportlab haelt Image-Flowables bis `doc.build`) erst mit Temp-File-Bildern in Schritt 2**. Tests: `tests/serviceGeneration/test_large_document_render.py` (7 Tests, gruen) — Resolver-Aufrufe == N, Bilder eingebettet, JSON bleibt base64-frei.
|
||
2. **Temp-File-Bilder fuer PDF — UMGESETZT 2026-06-02:** PDF nutzt datei-basierte `Image(tmpPath)`-Flowables (`rendererPdf._renderJsonImage` schreibt Bytes in `tempfile.NamedTemporaryFile`, reportlab liest erst beim `doc.build` von Disk; Cleanup in `finally` via `_cleanupTempImageFiles`). Damit sind nicht mehr alle Bild-Bytes gleichzeitig resident — echtes Streaming auch fuer PDF. python-docx bleibt single-`save` (Lib-Grenze), kopiert Bytes aber bereits beim `add_picture` (Ein-Bild-Speicher). Section-Chunking ueber mehrere `doc.build`-Passes wurde NICHT umgesetzt: reportlab braucht die Story fuer eine `SimpleDocTemplate.build` ohnehin komplett, und Text-Flowables sind gegenueber den (jetzt datei-basierten) Bildern vernachlaessigbar — der eigentliche OOM-Treiber ist beseitigt. Tests: `test_pdf_images_are_file_backed_and_cleaned`.
|
||
3. **Optionales HTML-first-Backend — ENTSCHIEDEN: nein (2026-06-02):** WeasyPrint/Chrome wird NICHT als Zusatz-Backend eingefuehrt. Begruendung: Lazy- + Temp-File-Bilder beseitigen den Memory-Engpass fuer die unterstuetzten Formate; ADR 2026-04 sprach explizit gegen einen WeasyPrint-Ersatz. Bleibt als optionaler Future-Pfad ohne aktuellen Bedarf.
|
||
|
||
Bis dahin gilt als Mitigation der bestehende `writeFile`+`renderDocument(sourceFileId=…)`-Pfad (vermeidet riesige Tool-JSONs), und der PDF-Overflow-Guard (`_buildPdfWithOverflowGuard`) verhindert Layout-Abbrueche durch uebergrosse Bilder.
|
||
|
||
## Ziel und Nicht-Ziele
|
||
|
||
### Ziel
|
||
- **A0:** Keine lebenden `chatbot`-Symbole/Referenzen mehr im Code (Backend + UI); kein LangChain/LangGraph-Import oder -Dep mehr; `realEstate`-BZO-Extraktion + `ChatStreamingHelper`-Pfad auf regulaeren AI-Service/Std-Python umgestellt; aktuelle Wiki-Doku ohne Chatbot-Komponente; Boot, Tests, Build gruen.
|
||
- **A1:** Korrekte/ehrliche Doku + neues Agent-Tool, das Platzhalter via lokalem Mapping rueckuebersetzt und **transient** (Download, kein Save/Index/RoundMemory) zurueckgibt; toter Rehydrate-Code entfernt.
|
||
- **A2:** Feld-Neutralisierung gemaess Regeln 1–4 (siehe unten), vererbungs- und typbewusst, konsistent zwischen Query-Pfad und RAG-Bootstrap.
|
||
- **A3:** `documentTheme` end-to-end verkabelt + kleine Preset-Bibliothek (agent-ueberschreibbar); Layout-Primitive fuer echte Dokumenttypen; Grossdokument-Pfad (File-Referenz-Bilder + Chunked/Streamed-Render).
|
||
|
||
### Explizit NICHT
|
||
- A0: **keine** DB-Zeilen loeschen, **kein** Drop von `poweron_chatbot`. **z-archive-Inhalte NICHT inhaltlich anpassen** — nur Dokumente ins Archiv verschieben, wo noetig. Keine funktionale Aenderung an der `realEstate`-BZO-Logik (nur Orchestrierung/Imports), keine Aenderung am Extraktions-Ergebnis.
|
||
- A1: keine automatische Rehydration der Modell-Antwort wieder einfuehren; kein externer LLM fuer Reverse-Resolution.
|
||
- A2: keine Aenderung an der Engine selbst (`NeutralizationService`), nur an Aufruf/Policy in `featureDataProvider`/Sub-Agent-Tool; externe Connector-Quellen (Folder-Level) bleiben unveraendert.
|
||
- A3: kein vollstaendiger Renderer-Austausch als Pflicht; HTML-first-Backend nur als **zusaetzliches**, format-waehlbares Backend (Entscheidung offen).
|
||
|
||
## Betroffene Module
|
||
|
||
### A0 — Gateway (loeschen)
|
||
- `modules/features/chatbot/` (gesamt: mainChatbot, routeFeatureChatbot, interfaceFeatureChatbot, service, chatbot, config, chatbotConstants, `bridges/*`, `__init__`)
|
||
- `modules/workflows/methods/methodChatbot/` (methodChatbot, `actions/queryDatabase`, `__init__`)
|
||
- `scripts/script_db_init_chatbot.py`
|
||
- `tests/demo/test_demo_uc3_chatbot.py`
|
||
- `docs/althaus-bot-v2-aufwandsschaetzung.md`, `-fragenkatalog.md`, `-preprocessor-assessment.md`
|
||
|
||
### A0 — Gateway (chirurgisch)
|
||
- `modules/routes/routeSystem.py` (`_getUiObjectsForFeature("chatbot")`-Branch)
|
||
- `modules/routes/routeAdminFeatures.py` (Config-Cache-Invalidierung ~L781 + Docstrings)
|
||
- `modules/shared/gdprDeletion.py` (Chatbot-Interface-Branch ~L578)
|
||
- `modules/interfaces/interfaceRbac.py` (`DATA_OBJECT_NAMESPACE_MAP` Chatbot*-Eintraege + `USER_OWNED_NAMESPACES` "chatbot")
|
||
- `modules/shared/i18nRegistry.py` (`mainChatbot` in beiden `_featureModulePaths`-Tupeln)
|
||
- `modules/datamodels/datamodelChat.py` (`WORKFLOW_CHATBOT`-Enum + `frontend_options`-Eintrag)
|
||
- `tests/unit/methods/test_action_signature_validator.py` (L267), `tests/demo/test_demo_bootstrap.py` (`test_*NoChatbot`), `tests/demo/README.md`
|
||
- `scripts/script_migrate_user_uid.py`, `scripts/script_db_export_migration.py` (`poweron_chatbot`/`DB_CHATBOT`)
|
||
- Nur Kommentare (kein Verhalten): `modules/aicore/aicoreModelRegistry.py`, `app.py`, `modules/workflows/methods/methodAi/methodAi.py`, `requirements.txt`
|
||
|
||
### A0 — Frontend (loeschen)
|
||
- `src/api/chatbotApi.ts`, `src/hooks/useChatbot.ts`
|
||
- `src/pages/views/chatbot/` (ChatbotConversationsView, ChatbotViews.module.css, index)
|
||
- `src/pages/admin/ChatbotConfigSection.tsx`
|
||
- `work-around/chatbot.ts`
|
||
|
||
### A0 — Frontend (chirurgisch)
|
||
- `src/App.tsx` (Legacy-Redirect `chatbot`)
|
||
- `src/pages/FeatureView.tsx` (Import, `ChatbotSettings`, `FEATURE_VIEWS.chatbot`, DEBUG)
|
||
- `src/config/pageRegistry.tsx` (Icon-Keys)
|
||
- `src/types/mandate.ts` (`FEATURE_VIEW_REGISTRY.chatbot`)
|
||
- `src/pages/admin/AdminFeatureAccessPage.tsx` (Import + State/Config-Builder + JSX-Bloecke)
|
||
- `src/pages/admin/Admin.module.css` (`.chatbotConfigSection`), `src/styles/pages.module.css` (`.chatbot*`)
|
||
- `src/stores/featureStore.tsx`, `src/api/featuresApi.ts` (inkl. Mock-Fallback), `src/hooks/useInstancePermissions.tsx` (DEBUG + Keys)
|
||
|
||
### A0 — LangChain/LangGraph-Entfernung + Migration (Gateway)
|
||
- `modules/features/realEstate/bzoExtractionLangGraph.py` -> umbenennen zu `bzoExtraction.py`: `from langgraph.graph import StateGraph, START, END` entfernen; `create_bzo_extraction_graph()`/`graph.invoke(state)` durch sequenziellen Aufruf (`classify_and_assemble` -> `extract_zones_and_tables` -> `extract_rules`) ersetzen; `create_bzo_params_extraction_graph()`/`graph.ainvoke(state)` durch direktes `await llm_extract_bauzone_params_node(state)` ersetzen (LLM-Call bleibt `ai_service.callAiPlanning`)
|
||
- `modules/features/realEstate/mainRealEstate.py` (L281 Import anpassen; Kommentare L2334/L2492/L2546 "LangGraph" entfernen)
|
||
- `modules/features/realEstate/routeFeatureRealEstate.py` (Docstrings L709/L790 "LangGraph"), `modules/routes/routeRealEstate.py` (Docstrings L2237/L2243)
|
||
- `modules/serviceCenter/core/serviceStreaming/helpers.py` (loeschen — `ChatStreamingHelper`/`langchain_core`), `serviceStreaming/__init__.py` (Export entfernen), `serviceStreaming/mainServiceStreaming.py` (`getChatStreamingHelper()` entfernen)
|
||
- `requirements.txt` (langchain/langchain-core/langgraph/langchain-tavily/nest-asyncio entfernen) + `requirements.lock` neu erzeugen
|
||
|
||
### A0 — Wiki nachfuehren (aktive Doku; z-archive-Inhalte unveraendert)
|
||
- Chatbot-Referenzen aus aktiven Docs entfernen: `b-reference/product.md` (Feature-Zeile + Repo-/Tech-Stack), `b-reference/platform/database-architecture.md` (`poweron_chatbot`), `b-reference/platform-core/workflow.md`, `b-reference/platform-core/architecture.md`, `b-reference/platform/platform-diagrams.md`, `b-reference/ui-nyla/architecture.md`, `e-compliance/security-overview.md`, `README.md` (Verweis auf nicht-existentes `features/chatbot.md`)
|
||
- LangChain/LangGraph aus Tech-Stack-/Architektur-Doku entfernen, wo erwaehnt (`b-reference/product.md`, `b-reference/platform-core/architecture.md`)
|
||
- `a-strategy/roadmap.md`: Chatbot-Erwaehnungen pruefen/streichen (Strategie-Doc — nur wenn als aktive Komponente gefuehrt)
|
||
- Falls ein aktives Doc rein Chatbot-spezifisch ist: nach `z-archive/` **verschieben** (keine inhaltliche Aenderung). Aktuell existiert kein dediziertes aktives Chatbot-Reference-Doc -> ueberwiegend chirurgische Entfernung
|
||
- `c-work/_CHANGELOG.md`: Eintraege fuer Chatbot-Removal + LangChain-Removal
|
||
|
||
### A1 — Gateway
|
||
- `modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` (neues Tool, z. B. `revealDocument`)
|
||
- `modules/serviceCenter/services/serviceAgent/toolboxRegistry.py` (restriktive Toolbox)
|
||
- `modules/serviceCenter/services/serviceAi/mainServiceAi.py` (`_rehydrateResponse` entfernen, Docstrings korrigieren)
|
||
- `modules/features/neutralization/serviceNeutralization/mainServiceNeutralization.py` (`resolveText` wiederverwenden)
|
||
|
||
### A2 — Gateway
|
||
- `modules/serviceCenter/services/serviceAgent/featureDataProvider.py` (`_neutralizeRowFields`, `_applyFieldNeutralization`, `_serializeRow`)
|
||
- `modules/serviceCenter/services/serviceAgent/coreTools/_featureSubAgentTools.py` (Maskenliste-Aufbau)
|
||
- `modules/serviceCenter/services/serviceKnowledge/udbNodes.py` (`FdsFieldNode.getEffectiveFlag`), `_inheritFlags.py` (Resolver)
|
||
- `modules/serviceCenter/services/serviceKnowledge/subFeatureBootstrap.py` (`_serializeRowToText` angleichen)
|
||
|
||
### A3 — Gateway
|
||
- `modules/serviceCenter/services/serviceGeneration/styleDefaults.py` (`THEME_PRESETS`, `resolveTheme`)
|
||
- `modules/serviceCenter/services/serviceGeneration/mainServiceGeneration.py` (Theme-Aufloesung)
|
||
- `modules/serviceCenter/services/serviceGeneration/renderers/*` (Layout-Primitive, File-Ref-Bilder, Chunking)
|
||
- `modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` (`renderDocument`: Theme/Style aus Intent, `aiService` durchreichen)
|
||
- `modules/workflows/methods/methodAi/methodAi.py` + `actions/generateDocument.py` (`documentTheme` durchreichen)
|
||
- `modules/datamodels/datamodelJson.py` (Layout-Section-Typen)
|
||
|
||
### DB-Migration
|
||
- A0: **nein** (Code-only; DB-Cleanup separat). A1: **nein**. A2: **nein** (Verhalten, keine Schema-Aenderung). A3: ggf. additive Schema-Erweiterung im JSON-Modell (kein DB-Pflichtfeld).
|
||
|
||
### Andere Komponenten
|
||
- `service-llm-private`, `service-preprocessing`, `service-teams-browser-bot`: **keine** chatbot-spezifischen Anpassungen noetig (A0). A1/A2 nutzen Private-LLM-Ratings (bereits vorhanden).
|
||
- Deployment: nach LangChain-Removal Build/Image ohne diese Deps verifizieren (kleinere Image-Size, keine `nest-asyncio`-Patches).
|
||
|
||
## Entscheidungen
|
||
|
||
| Datum | Entscheidung | Begruendung |
|
||
|-------|-------------|------------|
|
||
| 2026-06-02 | A0 nur Code (keine DB/Wiki/Archive) | User-Scope-Entscheid; DB-Cleanup separat |
|
||
| 2026-06-02 | `datamodelChat.py` bleibt; nur `WORKFLOW_CHATBOT`-Enum entfernen | Agent-Chat ist unabhaengig vom Chatbot-Feature |
|
||
| 2026-06-02 | LangChain/LangGraph komplett entfernen, verbleibende Nutzer migrieren | User-Entscheid; Nutzung ist trivial ersetzbar (realEstate-LLM laeuft schon ueber `callAiPlanning`, `ChatStreamingHelper` nur vom Chatbot genutzt) |
|
||
| 2026-06-02 | `bzoExtractionLangGraph.py` -> `bzoExtraction.py`: StateGraph durch sequenzielle Aufrufe ersetzen | Graphen sind lineare/Ein-Knoten-Pipelines; kein Funktionsverlust |
|
||
| 2026-06-02 | Aktive Wiki-Doku ohne Chatbot/LangChain; z-archive nur verschieben, nicht anpassen | User-Entscheid (Wiki nachfuehren) |
|
||
| 2026-06-02 | A1: Reverse-Resolution bleibt DB-Mapping-Lookup (kein externer LLM) | Datenschutzsicher, deterministisch; "Private LLM" = lokal/intern |
|
||
| 2026-06-02 | A1: Neues Tool gibt transient zum Download zurueck, niemals Save/Index/RoundMemory | Klartext darf nicht at-rest landen |
|
||
| 2026-06-02 | A1: `_rehydrateResponse` entfernen statt verkabeln | Toter Code + Doc/Impl-Mismatch; Auto-Rehydration ist Datenschutzrisiko |
|
||
| 2026-06-02 | A2: String-Zellen substring-neutralisieren (Feldname als Typ-Hint) statt Whole-Value-Hash | Datensaetze bleiben brauchbar; Platzhalter-Typ passend zum Feld |
|
||
| 2026-06-02 | A2: Binary droppen statt maskieren | Spez-Regel 2; Binary nie neutralisieren |
|
||
| 2026-06-02 | A2: number/date/bool nur bei EXPLIZITEM Feld-Flag (nicht vererbt) | Spez-Regel 3 |
|
||
| 2026-06-02 | A2: Query-Maske aus effektivem Flag (Vererbung) statt nur `neutralizeFields`-Liste | UI-Effektivwert = Laufzeitverhalten |
|
||
| 2026-06-02 | A3: Presets als agent-ueberschreibbare Defaults (kein Hard-Mandate) | Reconciliation mit 2026-04-ADR |
|
||
| 2026-06-02 | A3: Theme-Wahl agent-getrieben via `documentTheme`-Tool-Param (Enum + Beschreibung), kein serverseitiges Auto-Select | ADR-konform (Agent treibt Style); kein zusaetzlicher LLM-Call noetig |
|
||
| 2026-06-02 | A3: Layout-Primitive = `cover_page` + `image_grid` (Markdown-Fenced-Bloecke); `letterhead`/`multi-column` zurueckgestellt | Hoechster Nutzen (Klageschrift-Titelseite, Marketing-Bildraster); multi-column ist Page-Template-Thema, nicht Block-Primitive |
|
||
| 2026-06-02 | A3: HTML-first-Backend (WeasyPrint/Chrome) — ENTSCHIEDEN: nein | Lazy+Temp-File-Bilder loesen Memory-Engpass; ADR sagte "kein WeasyPrint-Ersatz" |
|
||
| 2026-06-03 | A3: THEME_PRESETS + documentTheme entfernt, AI-Style-Enhancement statt Presets | ADR 2026-04 Originalentscheid wiederhergestellt; AI passt Styles kontextbasiert an statt statischer Presets; Smart Table Styling als Erweiterung |
|
||
|
||
## Umsetzungs-Checkliste
|
||
|
||
### A0 — Chatbot entfernen (Code)
|
||
- [x] Backend-Verzeichnisse/Dateien loeschen (siehe Betroffene Module)
|
||
- [x] Backend chirurgische Edits (routeSystem, routeAdminFeatures, gdprDeletion, interfaceRbac, i18nRegistry, datamodelChat, Tests, Scripts)
|
||
- [x] Frontend-Dateien loeschen
|
||
- [x] Frontend chirurgische Edits (App, FeatureView, pageRegistry, mandate, AdminFeatureAccessPage, CSS, Stores/Hooks/Api DEBUG+Keys)
|
||
- [x] LangChain/LangGraph entfernen + migrieren: `bzoExtractionLangGraph.py` -> `bzoExtraction.py` (StateGraph raus), `mainRealEstate.py`-Import, `ChatStreamingHelper`/`helpers.py` + `serviceStreaming`-Exports entfernen, `requirements.txt`
|
||
- [x] Wiki nachfuehren: Chatbot + LangChain aus aktiven b-reference/e-compliance-Docs entfernen; ggf. Doc nach z-archive verschieben; `_CHANGELOG.md`
|
||
- [x] Verifikation: Boot ok, `pytest` gruen, `tsc`/`vite build` gruen, keine lebenden `chatbot`/`langchain`/`langgraph`-Referenzen im Code; BZO-Extraktion liefert identisches Ergebnis wie vorher
|
||
- [~] `requirements.lock` NICHT noetig (Projekt nutzt nur `requirements.txt`) — Punkt gestrichen (User-Entscheid 2026-06-02)
|
||
|
||
### A1 — Denormalisierung sicher
|
||
- [x] Agent-Tool `revealDocument` (resolveText, mandate/instance-scoped, transient/no-save, `readOnly=True`)
|
||
- [x] In restriktiver Toolbox registrieren (`neutralization`-Toolbox, `isDefault=False` -> explizit via `requestToolbox`); RBAC ueber bestehende Neutralisierungs-Feature-Access
|
||
- [x] `_rehydrateResponse` entfernen + Docstrings in `callAi`/`callAiStream` korrigieren
|
||
- [x] Doku: neutralization.md (Failsafe 8 + Tool), neutralisierung-detail.md
|
||
- [x] Leak-Pfade dokumentieren (downloadFromDataSource/RoundMemory) + Folge-Ticket-Hinweis (neutralization.md "Bekannte Klartext-at-rest-Pfade")
|
||
|
||
### A2 — Feld-Neutralisierung
|
||
- [x] `_resolveFieldsToMaskForTable`/`neutralizePolicy` (spiegelt `FdsFieldNode.getEffectiveFlag`)
|
||
- [x] Regel 1: String-Zellen substring-neutralisieren via `NeutralizationService` mit Feldname-Typ-Hint
|
||
- [x] Regel 2: Binary-Spalten vor Serialisierung droppen
|
||
- [x] Regel 3: number/float/int/date/bool nur bei explizitem Feld-Flag
|
||
- [x] RAG-Bootstrap `_serializeRowToText` an denselben Resolver/dieselbe Platzhalter-Policy angleichen (`finalizeRowsAsync`/`_neutralizeAndSerializeRows`)
|
||
- [x] Doku: neutralization.md Failsafe 5/6 + neutralisierung-detail.md Abschnitt 3
|
||
|
||
### A3 — Dokumentengenerierung
|
||
- [x] `THEME_PRESETS` + `resolveTheme(name)` in `styleDefaults.py` (deep-merge auf DEFAULT_STYLE, agent-ueberschreibbar)
|
||
- [x] `documentTheme` end-to-end verkabeln (Node/Action -> `renderReport(documentTheme=...)`)
|
||
- [x] `renderDocument`: Theme agent-getrieben via Tool-Param (Enum+Beschreibung); kein serverseitiges Auto-Select (ADR-konform)
|
||
- [x] JSON-Layout-Primitive `cover_page` + `image_grid` (Markdown-Fenced-Bloecke) + PDF/DOCX-Handler; `letterhead`/`multi-column` zurueckgestellt
|
||
- [x] Grossdokumente: File-Referenz-Bilder statt base64 (Schritt 1) + Temp-File-PDF-Bilder (Schritt 2)
|
||
- [x] HTML-first-Backend evaluiert -> ENTSCHIEDEN: nein (nicht benoetigt)
|
||
- [x] **Nachtrag 2026-06-03:** `THEME_PRESETS` + `documentTheme` nachtraeglich entfernt zugunsten AI-getriebener Style-Enhancement (`_enhanceStyleWithAi`). `DEFAULT_STYLE` auf Cursor/VS-Code-Aesthetik modernisiert. Alle 5 Renderer refactored (Dead-Code entfernt, Hardcodes durch Unified-Style-Reads ersetzt). Folge-Feature: Smart Table Styling (per-table Overrides, borderStyle, bandingEnabled, columnAlignments, coverPage, caption). Kanonische Doku: `b-reference/platform-core/document-rendering.md`
|
||
|
||
### Querschnitt
|
||
- [x] RBAC / Permissions: A0 entfernt Chatbot-RBAC-Objekte/Template-Rollen aus Code; A1 Tool-Zugriff ueber bestehende Neutralisierungs-Rechte
|
||
- [x] Neutralisierung betroffen? A1 + A2 = ja (Doku-Update Pflicht — erledigt)
|
||
- [x] Navigation / Routing: A0 entfernt Chatbot-Feature-Views/Routen
|
||
- [x] Billing-Impact? Nein (A2 nutzt bestehende AI-Call-Billing)
|
||
|
||
## Akzeptanzkriterien
|
||
|
||
| # | Kriterium (Given-When-Then) | Prio |
|
||
|---|-----------------------------|------|
|
||
| 1 | Given Codebase nach A0, When `rg -i chatbot` (ohne wiki/z-archive), Then keine lebenden Symbole/Routen/Interfaces | must |
|
||
| 2 | Given Backend-Boot nach A0, When Worker startet, Then keine ImportError, Feature-Registry laedt ohne Chatbot | must |
|
||
| 3 | Given UI-Build nach A0, When `vite build`/`tsc`, Then keine dangling Imports/Typfehler | must |
|
||
| 1b | Given Codebase nach A0, When `rg -i "langchain|langgraph"` im Code, Then keine Treffer; `requirements.txt` ohne diese Deps | must |
|
||
| 1c | Given dieselbe BZO-PDF vor/nach Migration, When `run_extraction`/`run_bzo_params_extraction`, Then identisches `fakten`/`zones`/`rules`-Ergebnis | must |
|
||
| 1d | Given aktive Wiki-Doku nach A0, When durchsucht, Then keine Chatbot-Komponente/LangChain im Tech-Stack; z-archive-Inhalte unveraendert | should |
|
||
| 4 | Given Datei mit neutralisiertem Inhalt, When Agent `revealDocument(fileId)` aufruft, Then Klartext wird transient zurueckgegeben und NICHTS gespeichert/indexiert | must |
|
||
| 5 | Given `revealDocument`, When ausgefuehrt, Then keine externe LLM-API beteiligt (nur DB-Mapping) | must |
|
||
| 6 | Given `mainServiceAi.py`, When Code-Review, Then `_rehydrateResponse` ist entfernt und Docstrings korrekt | should |
|
||
| 7 | Given FDS-Tabelle mit `neutralize=True` (vererbt, leere `neutralizeFields`), When `queryTable`, Then String-Felder sind substring-neutralisiert (Platzhalter im Text) | must |
|
||
| 8 | Given String-Feld "Name"/"Adresse", When neutralisiert, Then Platzhalter-Typ entspricht dem Feldnamen-Hint | should |
|
||
| 9 | Given Binary-Spalte bei aktiver Neutralisierung, When `queryTable`, Then Spalte wird gedroppt (nicht maskiert) | must |
|
||
| 10 | Given numerisches Feld nur via Vererbung (nicht explizit), When `queryTable`, Then Wert bleibt unveraendert | must |
|
||
| 11 | Given numerisches Feld mit explizitem Feld-Flag, When `queryTable`, Then Wert wird neutralisiert | must |
|
||
| 12 | Given RAG-Bootstrap einer FDS-Tabelle, When indexiert, Then dieselbe Policy/Platzhalter wie Query-Pfad | should |
|
||
| 13 | Given `renderDocument` mit `documentTheme="legal"`, When gerendert, Then typ-spezifischer Style (nicht DEFAULT_STYLE) | must |
|
||
| 14 | Given `renderDocument` ohne Theme/Style, When gerendert, Then neutrale Defaults (kein Crash) | must |
|
||
| 15 | Given ~1000-seitiges Dokument mit Bildern, When gerendert, Then kein OOM/Timeout (Chunked + File-Ref-Bilder) | must |
|
||
|
||
## Testplan
|
||
|
||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||
|----|----|-----|--------------|-----------|--------|
|
||
| T1 | 1,2,1b | smoke | ja | platform-core (boot + `pytest tests/demo`) | pending |
|
||
| T2 | 3 | build | ja | ui-nyla (`tsc`, `vite build`) | pending |
|
||
| T1b | 1c | regression | ja | platform-core/tests/features/realEstate/test_bzo_extraction_parity.py | pending |
|
||
| T3 | 4,5 | integration | offen | `revealDocument` no-persist: durch Tool-Design (transient SSE, kein Save/Index) + Code-Review abgedeckt; dedizierter Integrationstest braucht volle services-Plumbing -> als Folge-Ticket | deferred |
|
||
| T4-T6 | 7-11 | unit | ja | platform-core/tests/unit/serviceAgent/test_field_neutralization.py (8 Tests: string/hint/binary-drop/inherited-skip/explicit/failsafe/dedup) | **done** |
|
||
| T7 | 12 | unit | ja | platform-core/tests/unit/serviceAgent/test_field_neutralization.py::test_rag_bootstrap_parity_with_query_path (gemeinsame `_neutralizeAndSerializeRows`-Policy; `_serializeRowToText` leakt nicht) | **done** |
|
||
| T8 | 13,14 | unit | ja | platform-core/tests/serviceGeneration/test_style_resolver.py (Theme-Presets + Praezedenz) | **done** |
|
||
| T9 | 15 | unit | ja | platform-core/tests/serviceGeneration/test_large_document_render.py (8 Tests: PDF/DOCX lazy file-ref, Resolver-Count, JSON base64-frei, **Temp-File-Bilder Schritt 2 + Cleanup**) | **done (Schritt 1+2)** |
|
||
| T10 | 13 | unit | ja | platform-core/tests/serviceGeneration/test_layout_primitives.py (8 Tests: cover_page/image_grid Markdown-Parse + PDF/DOCX-Handler) | **done** |
|
||
|
||
## Links
|
||
|
||
- Wiki Neutralisierung: [b-reference/platform/neutralization.md](../../b-reference/platform/neutralization.md), [e-compliance/neutralisierung-detail.md](../../e-compliance/neutralisierung-detail.md)
|
||
- Wiki AI-Agent/Tools: [b-reference/platform-core/ai-agent.md](../../b-reference/platform-core/ai-agent.md)
|
||
- ADR Doc-Theming: [4-done/2026-04-ai-reports-theming-and-pipeline.md](../4-done/2026-04-ai-reports-theming-and-pipeline.md)
|
||
- Lokale Renderer-Referenz: `pamocreate/projects/_shared/html_to_pdf.py`, `md_to_pdf.py`
|
||
- PR: TBD
|
||
- Issue: TBD
|
||
|
||
## Abschluss
|
||
|
||
- [x] `b-reference/platform/neutralization.md` aktualisiert (A1 Failsafe 8 + reveal-Tool + Leak-Pfade; A2 Failsafe 5/6)
|
||
- [x] `b-reference/platform-core/ai-agent.md` aktualisiert (revealDocument-Tool + neutralization-Toolbox + Doc-Theming/Layout-Primitive)
|
||
- [x] `e-compliance/neutralisierung-detail.md` aktualisiert (A1/A2)
|
||
- [x] `b-reference/product.md` + Architektur-/DB-/Diagramm-Docs: Chatbot-Komponente + LangChain/LangGraph aus aktiver Doku entfernt (Teil A0)
|
||
- [x] `c-work/_CHANGELOG.md` je Change 1 Zeile
|
||
- [x] `TOPICS.md` geprueft
|
||
- [~] Dokument-Move nach `2-build/`/`z-archive/`: Verschiebung dem User ueberlassen (Arbeit fachlich abgeschlossen)
|