RAG プラグイン
テキストをインジェストし、埋め込み、上位K件を取得し、基づいた質問に答える—すべて1つのPHPクラスで行います。
RAG プラグインは、製品ビルダーにとって AI モジュールのキーフィーチャーです。これにより、ヘルプドキュメント、エラーログ、Stripe の請求書、カスタマーサポートチケットなど、任意のテキストの山が、大体 4 行の PHP コードで検索可能な知識ベースに変換されます。
3分間、端から端まで
Section titled “3分間、端から端まで”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]それだけです。ベクトルデータベースはありません。SDKはありません。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ストレージはコレクションごとに1つのJSONファイルです。各チャンクはtextとmetadataを含むオブジェクトで、ベクトルはbase64エンコードされたFloat32Arrayです — 各チャンク約3 KBです。約10,000個のチャンクはメモリに十分に収まります。
複数のコレクション
Section titled “複数のコレクション”同じアプリケーション内に任意の数のコレクションを持つことができます。それぞれが独自のJSONファイルを持ちます。これらは[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()]);API リファレンス
Section titled “API リファレンス”$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チューニングの調整項目
Section titled “チューニングの調整項目”application/module/ai/settings/ai.ini に:
[AI]embed.model = "nomic-embed-text" ; or mxbai-embed-large for higher qualityrag.top_k = 6 ; chunks injected into the chat callrag.chunk_target = 600 ; tokens per chunk (target)rag.chunk_min = 120 ; smaller chunks mergedrag.chunk_max = 900 ; larger paragraphs split on sentencesrag.storage_path = "/../../application/module/ai/cache/rag/"使用する場合
Section titled “使用する場合”- ヘルプ / FAQ チャット — お手伝い記事をインジェストし、
/askエンドポイントを公開します。 - アプリ内コード検索 —
application/module/をインジェストし、「VAT をどこで計算しているのか?」と尋ねます。 - 内部ドキュメントアシスタント — チームのウィキダンプをインジェストします。
- 顧客履歴検索 — チケットをインジェストし、「このエラーは以前に見ましたか?」と尋ねます。
使用しない場合
Section titled “使用しない場合”- リアルタイム、書き込みが重いデータ — RAG はスナップショットです。ライブデータの場合、エージェントが呼び出す Tool を作成してください。
- 大量のコーパス (> 100k チャンク) — JSON ファイルストレージが不十分になります。Qdrant / pgvector / Weaviate に移行します;自分自身が必要になったらアダプターを公開します。
- 正確な回答が必要な場面、確率的な回答ではなく RAG は確率的です。データベースクエリレイヤーとして使用しないでください。
一般的な落とし穴
Section titled “一般的な落とし穴”nomic-embed-textがプルされていません。 最初のingestText呼び出しは、プルコマンドを指す明確なエラーで失敗します。- 埋め込みモデルの不一致です。
nomic-embed-textチャンクとmxbai-embed-largeクエリを混在させないでください — 違うベクトル空間です。embed.modelを変更する場合は、まず$rag->reset()を実行してください。 - 古いコレクションです。
ingestDirの再実行は重複を削除しません。reset()を使用してから再インジェストするか、コンテンツハッシュチェックを自分で維持してください。 - 小さなチャンクです。 約80トークン未満の場合、埋め込みがノイジーになります。デフォルトの
rag.chunk_min = 120は小さな隣接チャンクをマージします。
次に何が来るか
Section titled “次に何が来るか”- エージェントプラグイン → ツール用、検索ではありません。
- トレーニング nibiru-coder → チャットの半分をフレームワークの声で返答させます。