# README.md # RetrieX > Hinweis: Das System wird fachlich als **RetrieX** bezeichnet. > Im Repository existieren aus historischen Gründen noch einzelne Bezeichner wie `RAG`, `rag.zip` oder `RAG_SYSTEM_OVERVIEW.md`. ## Überblick RetrieX ist ein dokumentenbasiertes Assistenzsystem auf Basis von Retrieval-Augmented Generation. Das System beantwortet Nutzeranfragen nicht rein frei, sondern kombiniert: - versionierte Wissensdokumente - deterministische Ingest- und Indexierungslogik - hybrides Retrieval mit Routing - optionale Shopware-Live-Produktsuche - LLM-basierte Antwortformulierung - SSE-Streaming für die Browserausgabe Der aktuelle Stand ist kein generischer Chatbot, sondern eine kontrollierte Wissens- und Antwortpipeline. --- ## Technologiestack ### Backend - PHP 8.2 - Symfony 7.4 - Doctrine ORM / Doctrine Migrations - Symfony Messenger - Symfony HttpClient - Twig ### Python-Layer - SentenceTransformers - FAISS - FastAPI - uvicorn ### Zusätzliche Libraries - `fivefilters/readability.php` für URL-Inhaltsauswertung - `smalot/pdfparser` für PDF-Textgewinnung - `league/commonmark` für Markdown-Rendering --- ## Kernidee des Systems RetrieX trennt klar zwischen: 1. **Primärquellen** Dokumente, Dokumentversionen, aktive System-Prompts, Modellkonfigurationen, optionale Shopdaten 2. **Index- und Retrieval-Ebene** `index.ndjson`, `index_meta.json`, `index_runtime.json`, `vector.index`, `tags.ndjson`, `vector_tags.index` 3. **Orchestrierung** Anfrageannahme, Kontextaufbau, URL-Analyse, Retrieval, Commerce-Erkennung, Prompt-Aufbau, Streaming 4. **Ausgabe** Token-Streaming an das Frontend über Server-Sent Events --- ## Aktuell unterstützte Dokumentformate Der verifizierte aktuelle Loader unterstützt: - PDF - TXT - MD Wichtig: Im aktuellen Code-Stand ist **kein produktiver DOCX-Loader** in der eigentlichen Ingest-Pipeline sichtbar. Die README sollte deshalb bewusst nur die real verifizierten Formate nennen. --- ## Laufzeitfluss einer Anfrage Der zentrale Browser-Endpunkt ist: - `POST /ask-sse` Die Anfrage läuft im aktuellen Stand vereinfacht so: 1. `AskSseController` nimmt die Anfrage entgegen 2. `ClientIdResolver` bestimmt eine stabile Client-ID 3. Antwort wird als **SSE-Stream** geöffnet 4. `AgentRunner` orchestriert den kompletten Ablauf 5. Optional wird URL-Inhalt aus dem Prompt extrahiert 6. `RetrieverInterface` bzw. `NdjsonHybridRetriever` holt Wissenskontext 7. Optional wird Commerce-Intent erkannt und Shopware durchsucht 8. `PromptBuilder` baut den finalen LLM-Prompt 9. `OllamaClient` streamt die Modellantwort 10. Die Antwort wird chunkweise ins Frontend gesendet 11. Der Turn wird in der Gesprächshistorie persistiert --- ## Gesprächskontext `ContextService` verwaltet die Konversationshistorie dateibasiert. Eigenschaften: - Nutzerhistorie wird pro Client-ID in einer Textdatei gespeichert - abgeschlossene Turns werden append-only geschrieben - regulärer Kontext und Full-Context sind getrennt vorgesehen - der aktuelle SSE-Flow ruft `AgentRunner->run(..., true)` auf und nutzt damit **vollen Kontext** Standardlogik im aktuellen Stand: - normale Historie: letzte 20 Zeilen - voller Kontext: letzte 500 Zeilen --- ## URL-Auswertung Wenn im Prompt eine URL vorkommt, extrahiert `UrlAnalyzer` den Inhalt der **ersten** URL. Aktuelle Eigenschaften: - Timeout-basiertes Laden - `Readability`-basierte Extraktion des lesbaren Inhalts - HTML wird entfernt - Whitespace wird normalisiert - Ausgabe wird auf maximal 5000 Zeichen begrenzt Der extrahierte Text wird als zusätzlicher unterstützender Wissensblock in den finalen Prompt aufgenommen. --- ## Ingest- und Indexarchitektur ### Zielbild RetrieX nutzt eine deterministische Ingest-Architektur mit NDJSON als operativer Wissensbasis und FAISS als Vektorindex. ### Zentrale Dateien - `var/knowledge/index.ndjson` - `var/knowledge/index_meta.json` - `var/knowledge/index_runtime.json` - `var/knowledge/vector.index` - `var/knowledge/vector.index.meta.json` - `var/knowledge/tags.ndjson` - `var/knowledge/vector_tags.index` - `var/knowledge/vector_tags.index.meta.json` ### Bedeutung #### `index.ndjson` Operative Chunk-Basis des Systems: - eine JSON-Zeile pro Chunk - streamingfähig - geeignet für append und full rewrite - Grundlage für den Vector-Rebuild #### `index_meta.json` Struktur-Metadaten des Index, u. a.: - `index_version` - `created_at` - `chunk_size` - `chunk_overlap` - `embedding_model` - `embedding_dimension` - `scoring_version` - weitere Strukturfelder aus der aktiven Index-Konfiguration #### `index_runtime.json` Laufzeitdaten, u. a.: - `chunk_count` - `last_rebuild_at` - optionale Commit-Marker wie `last_tags_rebuild_at` --- ## Dokument-Lifecycle Der aktuelle Dokumentfluss ist technisch so aufgebaut: 1. Dokumentversion wird aktiviert oder ingestiert 2. Guardrails prüfen die Strukturverträglichkeit 3. alte Chunks des Dokuments werden entfernt 4. neue Chunks werden streamingfähig geschrieben 5. der komplette Vektorindex wird neu gebaut 6. Runtime-Stats werden atomar aktualisiert 7. Status der Version wird auf `INDEXED` gesetzt Wichtige Eigenschaft: - Pro Dokument gibt es fachlich eine aktive Version - Chunks sind abgeleitete Artefakte, keine Primärdaten --- ## Ingest-Services im aktuellen Stand ### `GuardrailValidator` Prüft über `IndexMetaManager`, ob der aktuelle Index strukturell zur aktiven Konfiguration passt. Wenn sich relevante Strukturparameter geändert haben, wird lokaler Ingest blockiert. ### `ChunkWriteService` Kapselt die Schreibzugriffe auf den Chunk-Bestand: - Gesamtanzahl zählen - Chunks nach `document_id` kompaktieren - neue Chunks anhängen - vollständigen Rewrite durchführen ### `VectorRebuildService` Führt den vollständigen FAISS-Rebuild aus und aktualisiert anschließend die Runtime-Metadaten. ### `IngestFlow` Orchestriert: - Dokument-Ingest - Global Reindex - Dokumentlöschung inklusive Rebuild --- ## Guardrails RetrieX schützt sich gegen strukturellen Drift. Lokaler Ingest darf nicht weiterlaufen, wenn sich z. B. diese Strukturparameter geändert haben: - Embedding-Modell - Embedding-Dimension - Chunk-Größe - Chunk-Overlap - Scoring-Version - Index-Strukturkonfiguration Dann ist ein **Global Reindex** erforderlich. --- ## Retrieval im aktuellen Stand Der aktive Retriever ist: - `App\Knowledge\Retrieval\NdjsonHybridRetriever` Wichtig: „Hybrid“ bedeutet hier im verifizierten Code nicht einfach „Keyword + Vektor“, sondern eine orchestrierte Kombination aus mehreren Retrieval-Schritten. ### Aktuelle Retrieval-Pipeline 1. Query Cleaning 2. Query Enrichment 3. Intent-Erkennung 4. Katalog-/Listenrouting 5. Tag-Routing auf Kandidatendokumente 6. globale Vektorsuche 7. optionale gescopte Vektorsuche auf Kandidatendokumente 8. Fusion der Treffer 9. Selektion der finalen Chunk-IDs 10. Laden der finalen Chunk-Texte aus NDJSON ### Verwendete Bausteine - `QueryCleaner` - `QueryEnricher` - `IntentLite` - `SalesIntentLite` - `CatalogIntentLite` - `IntentRouteResolver` - `TagRoutingService` - `VectorSearchClient` - `NdjsonChunkLookup` ### Besondere Logiken - Listenfragen werden gesondert erkannt - Kataloganfragen können direkt einen Katalogblock statt regulärer Chunks liefern - globale und gescopte Treffer werden gefused - Chunk-Selektion ist dokument- und abstandsbegrenzt --- ## Vektor-Layer ### Komponenten - `python/vector/vector_ingest.py` - `python/vector/vector_search.py` - `python/vector/vector_service.py` ### Betriebsmodus Der produktive Zugriff erfolgt primär über den HTTP-basierten Vector-Service. Service-URL im aktuellen Default: - `http://127.0.0.1:8090` ### Aufgaben des Vector-Service - Embedding-Modell laden - FAISS-Hauptindex laden - Tag-Index laden - Suchanfragen für Chunks beantworten - Suchanfragen für Tags beantworten - Reloads auf neue Indexstände ermöglichen ### Wichtige Eigenschaft Der Python-Service hält Modell und Indizes persistent im RAM, um wiederholte Suchanfragen deutlich schneller zu bedienen. --- ## Prompt-Aufbau `PromptBuilder` setzt den finalen LLM-Prompt im aktuellen Stand aus diesen Blöcken zusammen: 1. **SYSTEM** Aktiver System-Prompt aus der Datenbank 2. **CONVERSATION CONTEXT (authoritative)** Gesprächshistorie des Nutzers 3. **LIVE SHOP RESULTS (authoritative for products)** Shopware-Treffer, falls Commerce aktiv ist 4. **RETRIEVED KNOWLEDGE (supporting)** Wissens-Chunks aus dem Retriever 5. **CONTENT FROM URL (supporting)** Optional extrahierter Webinhalt 6. **USER QUESTION** Aktuelle Nutzerfrage Wichtig: Für Produktfragen behandelt das System Shopdaten explizit als **führende Quelle**. --- ## Commerce- und Shopware-Integration RetrieX besitzt im aktuellen Stand eine optionale Shopware-Store-API-Integration. ### Aktivierung Die Shop-Suche wird nur genutzt, wenn `CommerceIntentLite` eine passende Anfrage erkennt. Mögliche Zustände: - `none` - `product_search` - `advisory_product_search` ### Signale für Commerce Der Intent-Detektor reagiert u. a. auf: - Such- und Produktbegriffe - SKU-/Zahlenmuster - Preisangaben - Größenangaben - Farbangaben - beratende Formulierungen wie „passt“, „besser“, „empfiehl“ ### Aktueller Shop-Flow 1. Commerce-Intent erkennen 2. LLM erzeugt zunächst eine kurze Shop-Suchphrase 3. `ShopSearchService` ruft `CommerceQueryParser` auf 4. `ShopwareCriteriaBuilder` baut Suchkriterien 5. `StoreApiClient` ruft `/store-api/search` auf 6. Ergebnisse werden zu `ShopProductResult` gemappt 7. Ergebnisse fließen in den Prompt ein ### Wichtige Anmerkung Der aktuelle Code kombiniert also: - **heuristische Intent-Erkennung** - **LLM-unterstützte Kurzsuchphrase** - **deterministische Nachverarbeitung im Parser** - **Store-API-Suche** ### Aktuelle Shop-Parameter In `services.yaml` sind u. a. konfiguriert: - `mto.commerce.enabled` - `mto.commerce.max_shop_results` - `mto.commerce.shop_timeout` - `mto.commerce.store_api_base_url` - `mto.commerce.sales_channel_access_key` --- ## Antwort-Streaming Die Browserausgabe erfolgt per **Server-Sent Events**. ### Eigenschaften des aktuellen SSE-Flows - Output Buffer werden aktiv geleert - Cookies werden vor Streamstart weitergereicht - Chunks werden direkt als SSE `data:`-Zeilen übertragen - Zeilenumbrüche bleiben erhalten - am Ende wird ein `done`-Event gesendet Das ist im aktuellen System die bevorzugte Streaming-Variante für den Browser. --- ## Projektstruktur Die zentralen Verzeichnisse im aktuellen Stand sind: - `src/` - `config/` - `templates/` - `migrations/` - `python/` - `public/` - `var/` - `bin/` ### Wichtige Bereiche in `src/` - `Agent/` - `Commerce/` - `Context/` - `Controller/` - `Index/` - `Ingest/` - `Intent/` - `Knowledge/` - `Routing/` - `Shopware/` - `Tag/` - `Vector/` --- ## Wichtige Commands Verifizierte relevante Commands im aktuellen Stand: - `mto:agent:chat` - `mto:agent:ingest:run` - `mto:agent:ingest:version` - `mto:agent:vector:control` - `mto:agent:vector:rebuild` - `mto:agent:vector:health` - `mto:agent:tags:export` - `mto:agent:tags:rebuild` - `mto:agent:tags:job:run` - `mto:agent:tag:health` - `mto:agent:system:rebuild` - `mto:agent:test:shop-search` - `mto:agent:test-vector` - `mto:agent:user:create` ### Besonders wichtig #### Vector-Service steuern ```bash bin/console mto:agent:vector:control --status bin/console mto:agent:vector:control --install --start --reload