Zum Inhalt springen
Nibiru docsv0.9.2

RAG-Erweiterung

Text einlesen, eingebettet, Top-K abrufen und fundierte Fragen beantworten – alles in einer PHP-Klasse.

Stable Reading time ~ 3 min Edit on GitHub

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.

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.

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.

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.

$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()]);
$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

In application/module/ai/settings/ai.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/"
  • 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?”
  • Echtzeit, schreibintensive Daten — RAG ist ein Snapshot. Für lebende Daten schreiben Sie ein Tool, 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.
  • 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.