---
title: "RAG-Erweiterung"
description: "Text einlesen, eingebettet, Top-K abrufen und fundierte Fragen beantworten – alles in einer PHP-Klasse."
---

Das RAG-Plugin ist die Killerfunktion des KI-Moduls für Produktbauer. Es verwandelt jede Menge Text – Ihre Hilfedokumentationen, Ihre Fehlerprotokolle, Ihre Stripe-Rechnungen, Ihre Kundensupport-Tickets – in eine abfragbare Wissensbasis in etwa vier Zeilen PHP.

## Drei Minuten, von Anfang bis Ende
```php
use Nibiru\Module\Ai\Ai;

$ai  = new Ai();
$rag = $ai->rag('product-help');     // a named collection

$rag->ingestDir(__DIR__ . '/help/'); // walks .md/.txt/.php under help/
$rag->ingestText('FAQ entry…', ['source' => 'faq-12']);

echo $rag->ask('How do I cancel my subscription?');
// → grounded answer, citing chunks like [1] [2] [3]
```
Das ist alles. Keine Vektordatenbank. Kein SDK. Kein Python-Sidecar.

## Wie es funktioniert
```
ingestText / ingestFile / ingestDir
        ↓
   chunk → embed (Ollama nomic-embed-text)
        ↓
   pack vectors → JSON file at cache/rag/<collection>.json
        ↓
ask(question) → embed question → cosine top-K → chat with chunks as context
```
Speicherung erfolgt durch eine JSON-Datei pro Sammlung. Jeder Chunk ist ein Objekt mit `text` und `metadata`; Vektoren sind als base64-gepackte Float32Array gespeichert – etwa 3 KB pro Chunk. ~10.000 Chunks passen komfortabel in den Speicher.

## Mehrere Sammlungen

Sie können eine beliebige Anzahl von Sammlungen in der gleichen App haben. Jede hat ihre eigene JSON-Datei. Sie teilen das Einbettungsmodell und das Chatmodell aus der `[AI]`-Konfiguration.
```php
$docs    = $ai->rag('docs');
$tickets = $ai->rag('support-tickets');
$logs    = $ai->rag('error-logs');

$docs->ingestDir(__DIR__ . '/help/');
$tickets->ingestText($ticket->body, ['ticket_id' => $ticket->id]);
$logs->ingestText($exception->__toString(), ['ts' => time()]);
```
## API-Referenz
```php
$rag = $ai->rag('name');                    // get/create a named collection

// --- Ingestion ---
$rag->ingestText($text, $metadata = []);    // single chunk
$count = $rag->ingestFile('path');          // returns chunks added
$count = $rag->ingestDir('dir', ['md','txt','php']); // recursive

// --- Querying ---
$hits = $rag->search('query', $k = null);   // [{score, text, metadata}, …]
$answer = $rag->ask('question', $k = null); // top-K → chat call

// --- Maintenance ---
$rag->reset();                              // forget everything (deletes file)
$n = $rag->size();                          // number of chunks
```
## Einstellungsregler

In `application/module/ai/settings/ai.ini`:
```ini
[AI]
embed.model        = "nomic-embed-text"   ; or mxbai-embed-large for higher quality
rag.top_k          = 6                    ; chunks injected into the chat call
rag.chunk_target   = 600                  ; tokens per chunk (target)
rag.chunk_min      = 120                  ; smaller chunks merged
rag.chunk_max      = 900                  ; larger paragraphs split on sentences
rag.storage_path   = "/../../application/module/ai/cache/rag/"
```
## Wann es verwendet werden sollte

- **Hilfe / FAQ Chat** — Laden Sie Ihre Hilfesätze ein und stellen Sie einen `/ask` Endpunkt zur Verfügung.
- **In-app Code-Suche** — Laden Sie `application/module/` ein und fragen Sie sich "Wo berechnen wir die Mehrwertsteuer?"
- **Assistent für interne Dokumente** — Laden Sie den Wiki-Dump Ihres Teams ein.
- **Kundengeschichtensuchungen** — Laden Sie Tickets ein und fragen Sie sich "Haben wir diesen Fehler schon einmal gesehen?"

## Wann es NICHT verwendet werden sollte

- **Echtzeit, schreibintensive Daten** — RAG ist ein Snapshot. Für lebende Daten schreiben Sie ein [Tool](/en/ai/module/agent/), das der Agent aufrufen kann.
- **Massive Korpora (> 100k Chunks)** — Die Speicherung in JSON-Dateien beginnt zu knarzen. Wechseln Sie zu Qdrant / pgvector / Weaviate; wir veröffentlichen einen Adapter, sobald wir einen für uns selbst benötigen.
- **Alles, wo Sie *genaue* Antworten benötigen und nicht nur *wahrscheinliche* Antworten.** RAG ist probabilistisch. Verwenden Sie es nicht als Datenbankabfrageebene.

## Häufige Fallen

- **`nomic-embed-text` wurde nicht abgerufen.** Der erste Aufruf von `ingestText` schlägt mit einem klaren Fehler fehl, der Sie auf den Pull-Befehl hinweist.
- **Modellkonflikt beim Einbetten.** Verwenden Sie keine `nomic-embed-text`-Blöcke zusammen mit `mxbai-embed-large`-Abfragen – unterschiedliche Vektorräume. Wenn Sie `embed.model` ändern, führen Sie zuerst `$rag->reset()` aus.
- **Veraltete Sammlungen.** Das erneute Ausführen von `ingestDir` entfernt keine Duplikate. Verwenden Sie `reset()` und fügen Sie dann erneut ein, oder überprüfen Sie selbst eine Inhalts-Hash-Erkennung.
- **Kleine Blöcke.** Unter etwa 80 Token werden die Einbettungen störend. Der Standardwert von `rag.chunk_min = 120` führt kleine benachbarte Blöcke zusammen.

## Was kommt als nächstes?

- [Agent-Plugin →](/de/kI/modul/agent/) für Werkzeuge, nicht für Abruf.
- [Trainingsnibiru-coder →](/de/kI/modul/trainings/) um den Chat so zu gestalten, dass er halb in der Stimme des Frameworks antwortet.
