Aller au contenu
Nibiru docsv0.9.2

plugin RAG

Intégrez le texte, intégrez-le, récupérez les K premiers éléments et répondez aux questions fondées — tout cela dans une seule classe PHP.

Stable Reading time ~ 3 min Edit on GitHub

Le plugin RAG est la fonctionnalité clé du module IA pour les constructeurs de produits. Il transforme n’importe quel amoncellement de texte — vos documents d’aide, vos journaux d’erreurs, vos factures Stripe, vos tickets de support client — en une base de connaissances interrogeable en environ quatre lignes de 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]

Voilà. Aucune base de données vectorielle. Aucun SDK. Pas de conteneur latéral en Python.

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

Le stockage se fait par fichier JSON par collection. Chaque morceau est un objet avec texte + métadonnées; les vecteurs sont des Float32Array empaquetés en base64 — environ 3 Ko par morceau. Environ 10 000 morceaux s’adaptent confortablement à la mémoire.

Vous pouvez avoir un nombre quelconque de collections dans la même application. Chacune a son propre fichier JSON. Elles partagent le modèle d’incrustation et le modèle de conversation à partir de la configuration [AI].

$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

Dans 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/"
  • Aide / FAQ chat — intégrez vos articles d’aide, exposez un point de terminaison /ask.
  • Recherche de code dans l’application — intégrez application/module/, posez la question “où calculons-nous la TVA ?”
  • Assistant des documents internes — intégrez le vidage wiki de votre équipe.
  • Recherches d’historique clients — intégrez les tickets, posez la question “avons-nous déjà vu cette erreur ?”
  • Données en temps réel et à forte écriture — RAG est une capture instantanée. Pour les données en direct, écrivez un Outil que l’agent puisse appeler.
  • Corpus massifs (> 100k morceaux) — Le stockage dans des fichiers JSON commence à s’affaiblir. Passez à Qdrant / pgvector / Weaviate ; nous publierons un adaptateur une fois que nous en aurons besoin nous-mêmes.
  • Tout ce dont vous avez besoin de réponses exactes, pas de probabilités. RAG est probabiliste. Ne l’utilisez pas comme une couche de requêtes de base de données.
  • nomic-embed-text non récupéré. Le premier appel à ingestText échouera avec une erreur claire vous indiquant la commande de récupération.
  • Modèle d’incrustation incompatible. Ne mélangez pas les morceaux nomic-embed-text avec les requêtes mxbai-embed-large — espaces vectoriels différents. Si vous changez embed.model, exécutez $rag->reset() en premier.
  • Collections obsolètes. Réexécuter ingestDir ne supprime pas les doublons. Utilisez reset() puis ré-ingestez, ou maintenez un contrôle de hachage du contenu vous-même.
  • Petits morceaux. En dessous de ~80 jetons, les incrustations deviennent bruitées. Le rag.chunk_min par défaut à 120 fusionne les petits morceaux adjacents.