update README.md
This commit is contained in:
515
README.md
515
README.md
@@ -1,396 +1,321 @@
|
||||
# mitho AI Agent – Developer README
|
||||
Enterprise Hybrid RAG System (Symfony + NDJSON + FAISS + Persistent Vector Service)
|
||||
|
||||
Stand: Februar 2026
|
||||
Status: Produktiv stabil – Job-basierte Ingest-Architektur + Persistenter Vector-Service integriert
|
||||
# RAG-System – Technische Projektdokumentation
|
||||
**Version:** 1.0
|
||||
**Stand:** Februar 2026
|
||||
**Autor:** mitho
|
||||
**Status:** Verbindliche Referenzarchitektur (System Freeze)
|
||||
|
||||
---
|
||||
|
||||
# 1. Systemüberblick
|
||||
# 1. Ziel des Systems
|
||||
|
||||
Dieses System implementiert eine deterministische, governance-stabile
|
||||
Hybrid-RAG-Architektur mit:
|
||||
|
||||
- Symfony (PHP Backend)
|
||||
- NDJSON als Single Source of Truth
|
||||
- FAISS als Vektorindex (immer Full Rebuild)
|
||||
- Persistenter Python Vector-Service (FastAPI + Uvicorn)
|
||||
- Hybrid Retrieval (Keyword + Vektor)
|
||||
- Versioniertes Dokumentmodell
|
||||
- Job-basierte Ingest-Pipeline
|
||||
- Lock-geschützte Reindex-Operationen
|
||||
- SSE-Streaming im Frontend
|
||||
Das RAG-System dient der deterministischen, governance-stabilen Beantwortung von Nutzeranfragen auf Basis versionierter, kontrollierter Wissensquellen.
|
||||
|
||||
Grundprinzip:
|
||||
> „Wir nutzen KI nicht, um kreativ zu raten, sondern um verlässlich auf Basis Ihres Wissens zu antworten.“
|
||||
|
||||
- Keine inkrementellen Vektor-Updates
|
||||
- FAISS wird immer vollständig aus `index.ndjson` neu gebaut
|
||||
- Retrieval läuft über einen persistenten Service (kein Python-Spawn pro Anfrage)
|
||||
Das System kombiniert:
|
||||
|
||||
- Versionierte Dokumentverwaltung
|
||||
- Deterministisches Chunking
|
||||
- NDJSON als Single Source of Truth
|
||||
- Vollständigen FAISS-Rebuild
|
||||
- Hybrid Retrieval (Keyword + Vector + Tag)
|
||||
- Job-basierte Orchestrierung
|
||||
- Rollen- und Guardrail-Architektur
|
||||
- SSE-Streaming
|
||||
|
||||
---
|
||||
|
||||
# 2. Architekturprinzipien
|
||||
# 2. Architekturüberblick
|
||||
|
||||
## 2.1 Determinismus
|
||||
## 2.1 Systemebenen
|
||||
|
||||
- Gleiche Dokumente + gleiche Konfiguration → identisches `index.ndjson`
|
||||
- Gleiches `index.ndjson` → identisches FAISS
|
||||
- Gleiche Query → identisches Retrieval-Ergebnis
|
||||
### 1. Admin-Ebene (Symfony Backend)
|
||||
- Dokumentverwaltung
|
||||
- Versionierung
|
||||
- Tag-Management
|
||||
- Job-Steuerung
|
||||
- System-Prompt-Verwaltung
|
||||
- KI-Endpoint-Konfiguration
|
||||
|
||||
## 2.2 Governance
|
||||
### 2. Wissensebene
|
||||
- Dokumente (immutable)
|
||||
- DocumentVersion
|
||||
- Chunks
|
||||
- index.ndjson
|
||||
- index_meta.json
|
||||
|
||||
- Eine aktive Version pro Dokument
|
||||
- Keine impliziten Index-Änderungen
|
||||
- Strukturänderungen erzwingen Global Reindex
|
||||
- Keine Selbstmodifikation durch KI
|
||||
### 3. Vector-Ebene (Python)
|
||||
- Embedding-Modell (lokal)
|
||||
- FAISS-Index (Chunks)
|
||||
- FAISS-Index (Tags)
|
||||
- Persistenter Vector-Service
|
||||
- CLI-Fallback
|
||||
|
||||
## 2.3 Skalierbarkeit
|
||||
|
||||
- NDJSON (streamingfähig)
|
||||
- Kein RAM-basiertes JSON-Array
|
||||
- Zielgröße > 200k Chunks
|
||||
- FAISS Full Rebuild ist deterministisch
|
||||
### 4. Agent-Ebene
|
||||
- Retrieval-Fusion
|
||||
- PromptBuilder
|
||||
- SSE-Streaming
|
||||
- Chat-History-Verarbeitung
|
||||
|
||||
---
|
||||
|
||||
# 3. Wissensspeicher
|
||||
# 3. Dokumentenarchitektur
|
||||
|
||||
## 3.1 index.ndjson
|
||||
## 3.1 Primärquellen
|
||||
|
||||
Single Source of Truth.
|
||||
- Dokumente sind immutable.
|
||||
- Jede Änderung erzeugt eine neue DocumentVersion.
|
||||
- Pro Dokument existiert genau eine aktive Version.
|
||||
|
||||
- 1 JSON-Objekt pro Zeile
|
||||
- Streaming-Append
|
||||
- Deterministische Compaction by `document_id`
|
||||
## 3.2 Aktivierungsprozess
|
||||
|
||||
Beispielstruktur:
|
||||
|
||||
```json
|
||||
{
|
||||
"chunk_id": "uuid",
|
||||
"document_id": "uuid",
|
||||
"document_version_id": "uuid",
|
||||
"text": "...",
|
||||
"meta": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
Regeln:
|
||||
|
||||
- Keine JSON-Array-Datei
|
||||
- Keine Mutation einzelner Chunks
|
||||
- Nur Append + deterministische Entfernung per `document_id`
|
||||
1. Aktivierung einer Version
|
||||
2. Erstellung eines IngestJob
|
||||
3. Async-Start:
|
||||
```
|
||||
bin/console mto:agent:ingest:run <jobId>
|
||||
```
|
||||
4. IngestOrchestrator:
|
||||
- Guardrail-Validierung
|
||||
- NDJSON Compaction by document_id
|
||||
- Chunking
|
||||
- Streaming Append
|
||||
- Vollständiger FAISS-Rebuild
|
||||
- index_meta.json Update
|
||||
- Status COMPLETED/FAILED
|
||||
|
||||
---
|
||||
|
||||
## 3.2 index_meta.json
|
||||
# 4. NDJSON-Architektur
|
||||
|
||||
Strukturparameter:
|
||||
## 4.1 index.ndjson (Single Source of Truth)
|
||||
|
||||
- `index_version`
|
||||
- `embedding_model`
|
||||
- `embedding_dimension`
|
||||
- `chunk_size`
|
||||
- `chunk_overlap`
|
||||
- `scoring_version`
|
||||
- `index_format`
|
||||
- `vector_backend`
|
||||
- Streamingfähiges Format
|
||||
- Kein JSON-Array
|
||||
- Append-only mit Compaction
|
||||
- Keine vollständige RAM-Verarbeitung
|
||||
- Atomare Datei-Switches (.tmp → rename)
|
||||
|
||||
Wenn einer dieser Werte sich ändert:
|
||||
## 4.2 index_meta.json
|
||||
|
||||
→ **Global Reindex zwingend erforderlich**
|
||||
Enthält:
|
||||
|
||||
- index_version
|
||||
- embedding_model
|
||||
- embedding_dimension
|
||||
- chunk_size
|
||||
- overlap
|
||||
- scoring_version
|
||||
- index_format
|
||||
|
||||
### Guardrail-Mechanismus
|
||||
|
||||
Bei strukturellen Änderungen (Embedding, Chunking, Scoring):
|
||||
- Lokaler Ingest wird blockiert
|
||||
- Global Reindex erforderlich
|
||||
|
||||
---
|
||||
|
||||
## 3.3 FAISS
|
||||
# 5. Chunk-Management
|
||||
|
||||
Dateien:
|
||||
Verantwortlich: ChunkManager
|
||||
|
||||
- `vector.index`
|
||||
- `vector.index.meta.json`
|
||||
- `vector_tags.index`
|
||||
- `vector_tags.index.meta.json`
|
||||
Eigenschaften:
|
||||
|
||||
FAISS wird IMMER vollständig aus `index.ndjson` gebaut.
|
||||
|
||||
Keine Partial Updates.
|
||||
Kein inkrementelles Vector-Append.
|
||||
- Streaming-basiertes Schreiben
|
||||
- Deterministische Reproduktion
|
||||
- Hard Limit: 120.000 Chunks
|
||||
- Warnlimit: 100.000 Chunks
|
||||
- Kein vollständiger JSON-RAM-Load
|
||||
|
||||
---
|
||||
|
||||
# 4. Persistenter Vector-Service
|
||||
# 6. Vector-Architektur
|
||||
|
||||
Retrieval läuft nicht mehr über:
|
||||
## 6.1 Betriebsmodi
|
||||
|
||||
- Symfony Process
|
||||
- `exec()`
|
||||
- `python vector_search.py` pro Anfrage
|
||||
### A) Persistenter Vector-Service (bevorzugt)
|
||||
- Lädt Embedding-Modell einmal
|
||||
- Lädt FAISS-Indizes in RAM
|
||||
- REST-Endpunkte:
|
||||
- /search-chunks
|
||||
- /search-tags
|
||||
|
||||
Sondern über:
|
||||
### B) CLI-Fallback
|
||||
- Python-Skripte
|
||||
- Wird genutzt, falls Service nicht verfügbar ist
|
||||
|
||||
**FastAPI + Uvicorn (persistent im RAM)**
|
||||
## 6.2 Rebuild-Strategie
|
||||
|
||||
## 4.1 Eigenschaften
|
||||
|
||||
Beim Start lädt der Service:
|
||||
|
||||
- Embedding-Modell
|
||||
- Chunk-Index
|
||||
- Tag-Index
|
||||
- ID-Mappings
|
||||
|
||||
Diese bleiben dauerhaft im RAM.
|
||||
|
||||
Kein Modell-Reload pro Anfrage.
|
||||
Kein Disk-Reload pro Anfrage.
|
||||
Kein Python-Spawn pro Anfrage.
|
||||
|
||||
## 4.2 Endpoints
|
||||
|
||||
- `GET /health`
|
||||
- `POST /search-chunks`
|
||||
- `POST /search-tags`
|
||||
- `POST /reload`
|
||||
|
||||
## 4.3 Reload-Mechanismus
|
||||
|
||||
Nach Global Reindex:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8090/reload
|
||||
```
|
||||
|
||||
Lädt:
|
||||
|
||||
- Chunk-Index neu
|
||||
- Tag-Index neu
|
||||
- Modell nur wenn `embedding_model` geändert wurde
|
||||
|
||||
Kein Neustart nötig.
|
||||
Keine Downtime.
|
||||
- Immer vollständiger FAISS-Rebuild
|
||||
- Kein inkrementelles Patchen
|
||||
- Atomarer Index-Switch
|
||||
- Deterministisch und drift-sicher
|
||||
|
||||
---
|
||||
|
||||
# 5. Score-Gates (Routing-Sicherheit)
|
||||
# 7. Hybrid Retrieval
|
||||
|
||||
## 5.1 Tag-Gate
|
||||
## 7.1 Retrieval-Komponenten
|
||||
|
||||
Tags steuern Routing.
|
||||
1. Keyword-Retrieval (führend)
|
||||
2. FAISS-Chunk-Retrieval (ergänzend)
|
||||
3. Tag-Routing (Soft-Gate)
|
||||
|
||||
Empfohlener Mindestscore:
|
||||
## 7.2 Score-Fusion
|
||||
|
||||
`MIN_SCORE ≈ 0.70`
|
||||
|
||||
Schützt vor:
|
||||
|
||||
- zufälligen semantischen Treffern
|
||||
- falschem Dokumentrouting
|
||||
|
||||
## 5.2 Chunk-Gate
|
||||
|
||||
Chunks sind Kontext.
|
||||
|
||||
Weicher Gate:
|
||||
|
||||
`MIN_SCORE ≈ 0.50`
|
||||
|
||||
Optional: relativer Score zum besten Treffer.
|
||||
- Keyword hat Priorität
|
||||
- Vector ergänzt semantische Nähe
|
||||
- Tags dienen als Routing-Verstärker
|
||||
|
||||
---
|
||||
|
||||
# 6. Dokument- & Versionsmodell
|
||||
# 8. Tag-System
|
||||
|
||||
Document
|
||||
→ enthält mehrere `DocumentVersion`
|
||||
→ genau eine Version ist aktiv
|
||||
## 8.1 Entities
|
||||
|
||||
Regel:
|
||||
- Tag
|
||||
- DocumentTag
|
||||
- TagRebuildJob
|
||||
|
||||
Es darf immer nur eine aktive Version pro Dokument existieren.
|
||||
## 8.2 Trigger-Logik
|
||||
|
||||
Beim Aktivieren einer Version:
|
||||
Ein Rebuild wird ausgelöst bei:
|
||||
|
||||
- Alle anderen Versionen werden inaktiv
|
||||
- `IngestStatus → PENDING`
|
||||
- Re-Ingest via Job
|
||||
- Tag-Erstellung
|
||||
- Tag-Löschung
|
||||
- Tag-Zuweisung
|
||||
- Tag-Entfernung
|
||||
|
||||
## 8.3 Job-Mechanik
|
||||
|
||||
- Async-Start via:
|
||||
```
|
||||
php bin/console mto:agent:tags:job:run <jobId>
|
||||
```
|
||||
- Logfile unter:
|
||||
```
|
||||
var/log/tags/job_<uuid>.log
|
||||
```
|
||||
|
||||
## 8.4 Stale-Protection
|
||||
|
||||
- QUEUED-Jobs älter als 5 Minuten → FAILED
|
||||
- System kann nicht dauerhaft blockieren
|
||||
- Coalescing (max. 1 aktiver Job)
|
||||
|
||||
## 8.5 Tag-Index
|
||||
|
||||
- tags.ndjson
|
||||
- vector_tags.index
|
||||
- Vollständiger Rebuild bei Änderung
|
||||
|
||||
---
|
||||
|
||||
# 7. Ingest-Architektur (vollständig Job-basiert)
|
||||
# 9. Job-Architektur
|
||||
|
||||
Ingest läuft NIEMALS synchron im HTTP-Request.
|
||||
Statusmodell:
|
||||
|
||||
Jede Mutation am Index läuft über:
|
||||
- QUEUED
|
||||
- RUNNING
|
||||
- COMPLETED
|
||||
- FAILED
|
||||
|
||||
IngestJob → CLI Runner → IngestOrchestrator → IngestFlow
|
||||
Eigenschaften:
|
||||
|
||||
## 7.1 Job-Typen
|
||||
|
||||
- `DOCUMENT_VERSION_ACTIVATE`
|
||||
- `DOCUMENT`
|
||||
- `GLOBAL_REINDEX`
|
||||
|
||||
## 7.2 Job-Status
|
||||
|
||||
- `QUEUED`
|
||||
- `RUNNING`
|
||||
- `COMPLETED`
|
||||
- `FAILED`
|
||||
- `ABORTED`
|
||||
|
||||
CLI-Ausführung:
|
||||
|
||||
```bash
|
||||
php bin/console mto:agent:ingest:run <jobId>
|
||||
```
|
||||
- Async exec
|
||||
- LockService gegen Parallel-Ausführung
|
||||
- Self-Healing gegen blockierte Jobs
|
||||
- Logging pro Job
|
||||
|
||||
---
|
||||
|
||||
# 8. Hybrid Retrieval
|
||||
# 10. Governance & Guardrails
|
||||
|
||||
Flow:
|
||||
## 10.1 Rollen
|
||||
|
||||
User Query
|
||||
→ Keyword Retrieval
|
||||
→ Tag Vector Search
|
||||
→ Dokumentfilter
|
||||
→ Chunk Vector Retrieval
|
||||
→ Score Fusion
|
||||
→ NDJSON Lookup
|
||||
→ Context Builder
|
||||
→ LLM
|
||||
→ SSE Streaming
|
||||
- Super Admin
|
||||
- Knowledge Admin
|
||||
- Redaktion
|
||||
- Frontend-User
|
||||
|
||||
Keyword bleibt Primärsignal.
|
||||
Vector ergänzt Semantik.
|
||||
## 10.2 Schutzmechanismen
|
||||
|
||||
- Dokumente immutable
|
||||
- Keine manuelle Chunk-Manipulation
|
||||
- Versionierte Ingest-Profile
|
||||
- Versionierte System-Prompts
|
||||
- Konfigurierbare KI-Endpunkte
|
||||
- Logging & Audit-Fähigkeit
|
||||
|
||||
---
|
||||
|
||||
# 9. Locking & Concurrency
|
||||
# 11. Agent-Architektur
|
||||
|
||||
LockService verhindert:
|
||||
|
||||
- parallelen Ingest
|
||||
- gleichzeitige Reindex-Vorgänge
|
||||
- NDJSON-Korruption
|
||||
|
||||
Keine gleichzeitigen Mutationen erlaubt.
|
||||
- SSE-Streaming
|
||||
- Historienverarbeitung korrekt implementiert
|
||||
- Deterministischer PromptBuilder
|
||||
- Retrieval-Kontext explizit eingebettet
|
||||
- Kein Think-Mode-Leak
|
||||
|
||||
---
|
||||
|
||||
# 10. Vector Control (Production Safe)
|
||||
# 12. Skalierbarkeit
|
||||
|
||||
Ein zentrales Kommando steuert:
|
||||
Zielgröße:
|
||||
|
||||
- Dependency-Check
|
||||
- Auto-Install (opt-in)
|
||||
- Service Start
|
||||
- Service Stop
|
||||
- Reload
|
||||
- Status
|
||||
- Health-Check
|
||||
- PID-Management
|
||||
- >120.000 Chunks
|
||||
|
||||
## Command
|
||||
Ermöglicht durch:
|
||||
|
||||
`mto:agent:vector:control`
|
||||
|
||||
## Beispiele
|
||||
|
||||
Status:
|
||||
|
||||
```bash
|
||||
bin/console mto:agent:vector:control
|
||||
```
|
||||
|
||||
Install + Start:
|
||||
|
||||
```bash
|
||||
bin/console mto:agent:vector:control --install --start
|
||||
```
|
||||
|
||||
Stop:
|
||||
|
||||
```bash
|
||||
bin/console mto:agent:vector:control --stop
|
||||
```
|
||||
|
||||
Reload:
|
||||
|
||||
```bash
|
||||
bin/console mto:agent:vector:control --reload
|
||||
```
|
||||
|
||||
## Production-Safety
|
||||
|
||||
- PID-File unter `var/run/vector_service.pid`
|
||||
- SIGTERM Stop mit Timeout
|
||||
- Optional SIGKILL (`--force`)
|
||||
- Health-Check mit Retry-Mechanismus
|
||||
- Kein automatisches Install ohne Flag
|
||||
- NDJSON Streaming
|
||||
- Kein Full-RAM-JSON
|
||||
- Vollständiger FAISS-Rebuild
|
||||
- Persistenter Vector-Service
|
||||
- Atomare Switches
|
||||
- Locking-Mechanismen
|
||||
|
||||
---
|
||||
|
||||
# 11. CLI Commands
|
||||
# 13. Stabilitätsstatus (Freeze-Zustand)
|
||||
|
||||
- `mto:agent:ingest:run <jobId>`
|
||||
- `mto:agent:vector:control`
|
||||
- `mto:agent:test`
|
||||
- `mto:agent:chat`
|
||||
|
||||
Alle Commands unter:
|
||||
|
||||
`mto:agent:*`
|
||||
| Bereich | Status |
|
||||
|----------|--------|
|
||||
| Dokument-Ingest | Stabil |
|
||||
| NDJSON-Architektur | Enterprise-Stabil |
|
||||
| FAISS-Rebuild | Deterministisch |
|
||||
| Tag-System | Stabil mit Stale-Recovery |
|
||||
| Async-Jobs | Blockiersicher |
|
||||
| Retrieval-Fusion | Funktional |
|
||||
| SSE | Stabil |
|
||||
| Governance | Aktiv |
|
||||
|
||||
---
|
||||
|
||||
# 12. Failure Modes
|
||||
# 14. System-Freeze-Definition
|
||||
|
||||
Vector Service nicht erreichbar
|
||||
→ `vector:control --start`
|
||||
Dieses Dokument definiert den verbindlichen Referenzstand des Systems.
|
||||
|
||||
Reload Endpoint fehlt
|
||||
→ falsche Service-Version
|
||||
Ab diesem Punkt gilt:
|
||||
|
||||
index_meta mismatch
|
||||
→ Global Reindex
|
||||
|
||||
Lock aktiv
|
||||
→ Parallel-Ingest blockiert
|
||||
- Keine strukturellen Änderungen ohne explizite Freigabe.
|
||||
- Erweiterungen nur inkrementell.
|
||||
- Keine Architektur-Rewrites.
|
||||
- Determinismus und Reproduzierbarkeit sind oberstes Prinzip.
|
||||
|
||||
---
|
||||
|
||||
# 13. Non-Goals
|
||||
# 15. Zusammenfassung
|
||||
|
||||
- Kein Online-Learning
|
||||
- Keine inkrementellen FAISS Updates
|
||||
- Keine selbstverändernden Prompts
|
||||
- Kein Auto-Merging von Chunks
|
||||
- Kein Vector-Append im Runtime
|
||||
|
||||
Strukturänderungen → explizit + Reindex.
|
||||
|
||||
---
|
||||
|
||||
# 14. Zusammenfassung
|
||||
|
||||
Dieses System ist:
|
||||
Das System ist:
|
||||
|
||||
- deterministisch
|
||||
- reproduzierbar
|
||||
- drift-sicher
|
||||
- governance-stabil
|
||||
- governance-konform
|
||||
- skalierbar
|
||||
- blockiersicher
|
||||
- debugbar
|
||||
- enterprise-ready
|
||||
- job-basiert
|
||||
- versionssicher
|
||||
- persistent im Retrieval
|
||||
- ohne Spawn-Overhead
|
||||
- reload-fähig ohne Downtime
|
||||
|
||||
Wichtige Neuerungen:
|
||||
|
||||
- Persistenter Vector-Service ersetzt CLI-Spawn
|
||||
- Score-Gates verhindern falsches Routing
|
||||
- Reload-Endpoint vermeidet Neustarts
|
||||
- Production-Safe Control Command integriert
|
||||
- Vollständige Trennung von Ingest und Runtime
|
||||
Es erfüllt die Anforderungen an ein kontrolliertes, reproduzierbares RAG-System mit klarer Trennung zwischen Wissensquelle, Index, Retrieval und Generierung.
|
||||
Reference in New Issue
Block a user