# RetrieX – Installationsanleitung

Stand: 15.04.2026  
Quelle: aktuelle `rag.zip` (Single Source of Truth)

Diese Anleitung beschreibt die **codebasierte Neuinstallation** des aktuellen Systems. Sie ersetzt ältere Installationsstände. Alle Angaben unten wurden an den tatsächlich vorhandenen Dateien, Services, Commands und Pfaden aus dem ZIP ausgerichtet.

---

## 1. Architektur des aktuellen Stands

RetrieX besteht aktuell aus diesen Hauptbausteinen:

- **Symfony 7.4** auf **PHP 8.2+**
- **Doctrine ORM + Doctrine Migrations**
- **MariaDB/MySQL** als operative Datenbank
- **Python-Vektorlayer** mit `faiss-cpu`, `sentence-transformers`, `fastapi`, `uvicorn`
- **Ollama-kompatibler LLM-Endpunkt** über `AI_LLM_API_URL`
- **NDJSON + FAISS** im Dateisystem unter `var/knowledge`
- **Adminoberfläche** für Dokumente, Ingest-Profile, System Prompt, Modellkonfiguration und Jobs
- **SSE-Streaming** für den Browser-Chat

Wichtige Betriebsordner im aktuellen Code:

- `var/knowledge/` → NDJSON, FAISS-Indizes, Uploads
- `var/log/` → System-, Agent- und Ingest-Logs
- `var/run/` → PID-Dateien des Python-Services
- `var/locks/` → Ingest-Lock
- `python/vector/` → Python-Control-, Search- und Service-Skripte

---

## 2. Wichtige Korrekturen gegenüber älteren Installationsständen

Die frühere `INSTALL.md` passt nicht mehr zum aktuellen Code. Für den aktuellen Stand gelten insbesondere diese Punkte:

- Der Wissensspeicher liegt unter **`var/knowledge/`**, nicht unter `var/vector/`.
- Der Python-Code liegt unter **`python/vector/`**, nicht unter `vector/`.
- Die Python-Abhängigkeiten kommen aus der Datei **`requirements.txt` im Projektroot**.
- Der korrekte Rebuild-Befehl ist **`mto:agent:system:rebuild --hard`**, nicht `mto:agent:ingest:global`.
- Das LLM-Modell kommt **nicht** mehr aus einer `AI_LLM_MODEL`-Umgebungsvariable, sondern aus der **aktiven ModelGenerationConfig** in der Adminoberfläche.
- Für den Chat sind **zwingend** nötig:
    - ein **aktiver System Prompt**
    - eine **aktive ModelGenerationConfig**
    - mindestens ein erfolgreich indexiertes Dokument für wissensbasiertes Retrieval
- Die Upload-UI erwähnt mehrere Dateitypen, der aktuelle Extractor-Code unterstützt jedoch **faktisch nur PDF**.

---

## 3. Systemvoraussetzungen

## 3.1 Betriebssystem

Empfohlen:

- Ubuntu 22.04 LTS oder neuer
- Debian 12 ist ebenfalls passend

Für lokale Entwicklung sind auch macOS oder Linux-Container-Setups möglich.

---

## 3.2 PHP

Erforderlich:

- **PHP 8.2 oder höher**

Benötigte bzw. praktisch notwendige Extensions aus dem aktuellen Projektstand:

- `ctype`
- `curl`
- `dom`
- `iconv`
- `libxml`
- `pdo`
- `pdo_mysql`
- `mbstring`
- `zip`

Prüfen:

```bash
php -v
php -m
```

---

## 3.3 Composer

Prüfen:

```bash
composer --version
```

Falls Composer nicht global vorhanden ist, kann lokal installiert werden. Für den regulären Betrieb ist ein globaler Composer aber sinnvoll.

---

## 3.4 Datenbank

Der aktuelle Projektstand ist praktisch auf **MariaDB/MySQL** ausgerichtet.

Empfohlen:

- **MariaDB 10.11.x**

Beispielinstallation:

```bash
sudo apt install mariadb-server
```

Beispiel für Datenbank und Benutzer:

```sql
CREATE DATABASE db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'db'@'%' IDENTIFIED BY 'db';
GRANT ALL PRIVILEGES ON db.* TO 'db'@'%';
FLUSH PRIVILEGES;
```

Hinweis:
Die mitgelieferte `.env` enthält derzeit noch eine PostgreSQL-Placeholder-URL. Für den realen Betrieb muss `DATABASE_URL` auf **MariaDB/MySQL** gesetzt werden.

---

## 3.5 Python

Erforderlich:

- **Python 3.10 oder höher**
- `python3-venv`
- `python3-pip`

Installation:

```bash
sudo apt install python3 python3-venv python3-pip
```

Prüfen:

```bash
python3 --version
```

---

## 3.6 Ollama oder kompatibler Generate-Endpunkt

RetrieX spricht den LLM-Endpunkt über `AI_LLM_API_URL` an. Erwartet wird ein **Ollama-kompatibler `/api/generate`-Endpoint**.

Beispiel mit Ollama:

```bash
curl -fsSL https://ollama.com/install.sh | sh
```

Ein Modell muss lokal vorhanden sein, zum Beispiel:

```bash
ollama pull qwen3
```

oder ein projektspezifisches Modell, falls vorhanden.

Verfügbarkeit prüfen:

```bash
curl http://127.0.0.1:11434/api/tags
```

Wichtig:
Welches Modell tatsächlich benutzt wird, bestimmt später die **aktive ModelGenerationConfig im Admin**, nicht eine `.env`-Variable.

---

## 3.7 Optional: Shopware Store API

Der Commerce-Pfad ist im aktuellen Code **standardmäßig aktiviert**. Für produktbezogene Anfragen nutzt das System optional die Shopware Store API.

Dafür werden diese Variablen verwendet:

- `SHOPWARE_STORE_API_BASE_URL`
- `SHOPWARE_SALES_CHANNEL_ACCESS_KEY`
- `SHOPWARE_STORE_API_MAX_RESULT`

Wenn keine Shopware-Suche gewünscht ist, sollte der Commerce-Pfad vor produktivem Einsatz bewusst deaktiviert oder sauber konfiguriert werden.

---

## 4. Projekt bereitstellen

ZIP entpacken und ins Projekt wechseln:

```bash
unzip rag.zip -d retriex
cd retriex
```

Alternativ über Repository-Checkout, falls das Projekt aus Git bereitgestellt wird.

---

## 5. PHP-Abhängigkeiten installieren

```bash
composer install --no-interaction
```

Für Produktion:

```bash
composer install --no-dev --optimize-autoloader --no-interaction
```

Erst nach diesem Schritt funktionieren `bin/console` und die Symfony-Commands.

---

## 6. Umgebung konfigurieren

## 6.1 Grundregel

Lokale oder serverbezogene Overrides sollten in **`.env.local`** gepflegt werden, nicht direkt in der committeten `.env`.

---

## 6.2 Minimale `.env.local`

Beispiel für einen lokalen oder servernahen MariaDB-Betrieb:

```env
APP_ENV=prod
APP_SECRET=change-me

DATABASE_URL="mysql://db:db@127.0.0.1:3306/db?serverVersion=10.11.0-mariadb&charset=utf8mb4"
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0

AI_LLM_API_URL=http://127.0.0.1:11434/api/generate
AI_LLM_TIMEOUT=600
AI_HISTORY_DIR=var/agent-history
AI_DEBUG=false
AI_LOG_PROMPT=false
AI_LOG_CONTEXT=false

SHOPWARE_STORE_API_BASE_URL="https://example.invalid"
SHOPWARE_SALES_CHANNEL_ACCESS_KEY="replace-me"
SHOPWARE_STORE_API_MAX_RESULT=25
```

Hinweise:

- `APP_ENV=prod` ist im aktuellen `.env` bereits voreingestellt.
- `DATABASE_URL` muss auf MariaDB/MySQL zeigen.
- `AI_LLM_API_URL` muss auf einen funktionierenden `/api/generate`-Endpoint zeigen.
- `AI_LLM_TIMEOUT=600` ist mit dem aktuellen Code konsistent.
- `AI_LLM_MODEL` wird **nicht** verwendet.

---

## 6.3 Shopware deaktivieren, wenn nicht benötigt

Im aktuellen Code ist `mto.commerce.enabled` in `config/services.yaml` auf `true` gesetzt. Wer die Shopware-Suche nicht einsetzen will, sollte vor produktivem Einsatz bewusst einen dieser Wege wählen:

1. gültige Shopware-Zugangsdaten hinterlegen, oder
2. `config/services.yaml` gezielt anpassen und Commerce deaktivieren.

Für reine Wissens- und Dokumentinstallation ist die Shopware-Anbindung nicht zwingend, sollte aber nicht unklar halbkonfiguriert bleiben.

---

## 7. Datenbank initialisieren

Migrationen ausführen:

```bash
php bin/console doctrine:migrations:migrate --no-interaction
```

Damit werden unter anderem diese zentralen Tabellen angelegt:

- `user`
- `document`
- `document_version`
- `ingest_job`
- `system_prompt`
- `ingest_profile`
- `model_generation_config`
- `knowledge_tag`
- `document_tag`
- `tag_rebuild_job`

---

## 8. Python-Umgebung aufbauen

## 8.1 Virtuelle Umgebung anlegen

```bash
python3 -m venv .venv
source .venv/bin/activate
```

---

## 8.2 Python-Abhängigkeiten installieren

Manuell:

```bash
pip install --upgrade pip
pip install -r requirements.txt
```

Alternativ nach angelegter `.venv` über den Symfony-Wrapper:

```bash
php bin/console mto:agent:vector:control --install
```

Wichtig:
Der Wrapper erwartet bereits eine existierende `.venv`. Er erzeugt sie **nicht** selbst.

---

## 9. Vector Service starten

Start:

```bash
php bin/console mto:agent:vector:control --start
```

Status prüfen:

```bash
php bin/console mto:agent:vector:control --status
```

Optionaler Reload:

```bash
php bin/console mto:agent:vector:control --reload
```

Der Service startet aktuell standardmäßig auf:

- Host: `0.0.0.0`
- Port: `8090`

Der PHP-Code spricht standardmäßig gegen:

- `http://127.0.0.1:8090`

---

## 10. Admin-Benutzer anlegen

Ohne Admin-Benutzer lässt sich das System nicht fertig konfigurieren.

CLI-Befehl:

```bash
php bin/console mto:agent:user:create
```

Der Command fragt interaktiv ab:

- E-Mail
- Passwort
- Rolle

Für die Erstinstallation ist typischerweise sinnvoll:

- `ROLE_SUPER_ADMIN`

---

## 11. Anwendung starten

Für einen einfachen lokalen Test:

```bash
php -S 127.0.0.1:8000 -t public
```

Danach sind typischerweise relevant:

- Chat-Frontend: `http://127.0.0.1:8000/`
- Admin-Login: `http://127.0.0.1:8000/admin/login`

Für Produktion sollte stattdessen ein regulärer Webserver genutzt werden, zum Beispiel Nginx + PHP-FPM.

---

## 12. Pflicht-Initialisierung im Admin

Nach der technischen Grundinstallation ist das System **noch nicht vollständig betriebsbereit**. Es müssen im Admin zwingend Inhalte angelegt werden.

## 12.1 System Prompt anlegen und aktivieren

Pfad im Admin:

- `/admin/system/prompt`

Ohne aktiven System Prompt wirft der PromptBuilder zur Laufzeit einen Fehler.

---

## 12.2 ModelGenerationConfig anlegen und aktivieren

Pfad im Admin:

- `/admin/model-config/`

Ohne aktive ModelGenerationConfig schlägt das Retrieval fehl, weil `NdjsonHybridRetriever` explizit eine aktive Konfiguration verlangt.

Sinnvolle Minimalwerte für einen stabilen Start:

- Modellname: exakt wie im Ollama-Endpunkt verfügbar, z. B. `qwen3:latest`
- Streaming: aktiv
- Temperature: `0.2` bis `0.4`
- Top K: `40`
- Top P: `0.9`
- Repeat Penalty: `1.1`
- num_ctx: `8192`
- Retrieval Max Chunks: `25`
- Retrieval Vector Top K: `25`

---

## 12.3 Optional: Ingest-Profil anlegen

Pfad im Admin:

- `/admin/ingest-profiles/`

Wenn kein Profil aktiv ist, fällt das System auf die Parameter aus `config/services.yaml` zurück:

- Chunk Size: `800`
- Chunk Overlap: `100`
- Embedding Model: `intfloat/multilingual-e5-base`
- Embedding Dimension: `768`
- Scoring Version: `1`

Das ist für einen ersten Start ausreichend. Ein eigenes Ingest-Profil ist also **optional**, solange man die Fallback-Werte bewusst akzeptiert.

---

## 13. Erste Dokumente ingestieren

## 13.1 Wichtiger Format-Hinweis

Die Upload-Maske nennt mehrere Formate, aber der aktuelle Extractor-Code enthält nur einen **`PdfExtractor`**. Für einen sicheren Erstbetrieb sollten daher aktuell **nur PDF-Dateien** hochgeladen werden.

---

## 13.2 Erstes Dokument hochladen

Pfad im Admin:

- `/admin/documents/new`

Beim Upload passiert im aktuellen Code folgendes:

1. Datei wird nach `var/knowledge/uploads` verschoben.
2. Dokument und Version 1 werden in der DB angelegt.
3. Die neue Version wird aktiv gesetzt.
4. Ein Ingest-Job vom Typ `DOCUMENT_VERSION_ACTIVATE` wird erstellt.
5. Der Job wird **asynchron per `exec()`** gestartet.

---

## 13.3 Wenn `exec()` deaktiviert ist

Der Admin-Flow für Upload, Aktivierung und Löschen setzt im aktuellen Code Hintergrundstarts über `exec()` voraus.

Ist `exec()` serverseitig deaktiviert, werden Jobs zwar angelegt, aber nicht automatisch ausgeführt. In diesem Fall muss der Job manuell gestartet werden:

```bash
php bin/console mto:agent:ingest:run <jobId>
```

Die `jobId` ist in der Job-Ansicht im Admin nachvollziehbar.

---

## 14. Rebuild und Konsistenzprüfung

## 14.1 Vollständiger System-Rebuild

Sobald aktive Dokumente vorhanden sind, kann ein vollständiger Rebuild ausgeführt werden:

```bash
php bin/console mto:agent:system:rebuild --hard
```

Dieser Ablauf umfasst aktuell:

1. globalen Reindex der aktiven Dokumente
2. Tag-Export und Tag-Index-Rebuild
3. Reload des Vector Service
4. Health-Checks

Wichtig:
Der Befehl bricht absichtlich ab, wenn **keine aktiven Dokumente** vorhanden sind.

---

## 14.2 Vector Health prüfen

```bash
php bin/console mto:agent:vector:health
```

Mögliche gesunde Zustände:

- `OK_EMPTY` → noch keine Wissensdaten vorhanden
- `OK` → NDJSON und FAISS konsistent

---

## 14.3 Tag Health prüfen

```bash
php bin/console mto:agent:tag:health
```

---

## 15. Wichtige Commands im aktuellen Stand

```bash
php bin/console mto:agent:user:create
php bin/console mto:agent:vector:control --install
php bin/console mto:agent:vector:control --start
php bin/console mto:agent:vector:control --status
php bin/console mto:agent:vector:control --reload
php bin/console mto:agent:vector:rebuild
php bin/console mto:agent:vector:health
php bin/console mto:agent:ingest:run <jobId>
php bin/console mto:agent:ingest:version <versionId> <userId>
php bin/console mto:agent:system:rebuild --hard
php bin/console mto:agent:tags:export
php bin/console mto:agent:tags:rebuild
php bin/console mto:agent:tag:health
php bin/console mto:agent:chat
php bin/console mto:agent:test:shop-search "deine Anfrage"
```

---

## 16. Minimaler Go-Live-Check

Eine Installation ist im aktuellen Stand erst dann wirklich lauffähig, wenn alle folgenden Punkte erfüllt sind:

- Composer-Abhängigkeiten installiert
- Datenbankmigrationen erfolgreich durchgelaufen
- `.env.local` korrekt gesetzt
- `.venv` vorhanden und Python-Abhängigkeiten installiert
- Vector Service läuft auf Port `8090`
- Admin-Benutzer existiert
- aktiver System Prompt vorhanden
- aktive ModelGenerationConfig vorhanden
- mindestens ein PDF erfolgreich ingestiert
- `mto:agent:vector:health` liefert `OK` oder `OK_EMPTY`
- Chat-Frontend und Admin-Login sind erreichbar

---

## 17. Häufige Fehlerbilder

## 17.1 `No active system prompt configured.`

Ursache:
Es existiert kein aktiver System Prompt.

Lösung:
Im Admin unter `/admin/system/prompt` eine Version speichern und aktivieren.

---

## 17.2 `No active ModelGenerationConfig found.`

Ursache:
Es existiert keine aktive Modellkonfiguration.

Lösung:
Im Admin unter `/admin/model-config/` eine Konfiguration anlegen und aktivieren.

---

## 17.3 Vector Service startet nicht

Typische Ursachen:

- `.venv` fehlt
- Python-Pakete fehlen
- Port `8090` ist schon belegt
- `uvicorn` ist nicht in der virtuellen Umgebung installiert

Prüfen:

```bash
php bin/console mto:agent:vector:control --status
```

---

## 17.4 Rebuild bricht mit „no active documents found“ ab

Ursache:
Es wurde noch kein aktives Dokument erfolgreich angelegt.

Lösung:
Zuerst ein PDF hochladen und ingestieren, danach den Rebuild erneut starten.

---

## 17.5 Upload klappt, Ingest startet aber nicht

Ursache:
`exec()` ist auf dem Server deaktiviert.

Lösung:
Job manuell mit `mto:agent:ingest:run <jobId>` starten oder Serverkonfiguration anpassen.

---

## 17.6 Dokument-Ingest schlägt bei Nicht-PDF fehl

Ursache:
Der aktuelle Code enthält nur einen `PdfExtractor`.

Lösung:
Für den aktuellen Stand ausschließlich PDFs ingestieren oder Extractor-Layer erweitern.

---

## 18. Empfohlene Produktionshinweise

Für stabilen produktiven Betrieb sind sinnvoll:

- Nginx oder Apache vor Symfony/PHP-FPM
- eigener Service-Start für den Python-Vector-Service
- eigener Service für Ollama
- Backup von Datenbank und `var/knowledge/`
- Monitoring der Logs unter `var/log/`
- bewusstes Governance-Handling für Ingest-Profile, System Prompts und Model-Konfigurationen

---

## 19. Ergebnis

Nach erfolgreicher Installation bietet der aktuelle Stand von RetrieX:

- dokumentenbasierte Wissensverwaltung
- versionierte Dokumente
- asynchronen Ingest über Jobs
- NDJSON als Wissensspeicher
- FAISS-basiertes Retrieval
- optionales Tag-Routing
- optionalen Shopware-Commerce-Pfad
- browserbasierten SSE-Chat
- Symfony-Adminoberfläche für Betrieb und Governance
