---
title: "RAG プラグイン"
description: "テキストをインジェストし、埋め込み、上位K件を取得し、基づいた質問に答える—すべて1つのPHPクラスで行います。"
---

RAG プラグインは、製品ビルダーにとって AI モジュールのキーフィーチャーです。これにより、ヘルプドキュメント、エラーログ、Stripe の請求書、カスタマーサポートチケットなど、任意のテキストの山が、大体 4 行の PHP コードで検索可能な知識ベースに変換されます。

## 3分間、端から端まで
```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]
```
それだけです。ベクトルデータベースはありません。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個のチャンクはメモリに十分に収まります。

## 複数のコレクション

同じアプリケーション内に任意の数のコレクションを持つことができます。それぞれが独自のJSONファイルを持ちます。これらは`[AI]`設定から埋め込みモデルとチャットモデルを共有します。
```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 リファレンス
```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
```
## チューニングの調整項目

`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/"
```
## 使用する場合

- **ヘルプ / FAQ チャット** — お手伝い記事をインジェストし、`/ask` エンドポイントを公開します。
- **アプリ内コード検索** — `application/module/` をインジェストし、「VAT をどこで計算しているのか？」と尋ねます。
- **内部ドキュメントアシスタント** — チームのウィキダンプをインジェストします。
- **顧客履歴検索** — チケットをインジェストし、「このエラーは以前に見ましたか？」と尋ねます。

## 使用しない場合

- **リアルタイム、書き込みが重いデータ** — RAG はスナップショットです。ライブデータの場合、エージェントが呼び出す [Tool](/en/ai/module/agent/) を作成してください。
- **大量のコーパス (> 100k チャンク)** — JSON ファイルストレージが不十分になります。Qdrant / pgvector / Weaviate に移行します；自分自身が必要になったらアダプターを公開します。
- **正確な回答が必要な場面、確率的な回答ではなく** RAG は確率的です。データベースクエリレイヤーとして使用しないでください。

## 一般的な落とし穴

- **`nomic-embed-text` がプルされていません。** 最初の `ingestText` 呼び出しは、プルコマンドを指す明確なエラーで失敗します。
- **埋め込みモデルの不一致です。** `nomic-embed-text` チャンクと `mxbai-embed-large` クエリを混在させないでください — 違うベクトル空間です。`embed.model` を変更する場合は、まず `$rag->reset()` を実行してください。
- **古いコレクションです。** `ingestDir` の再実行は重複を削除しません。`reset()` を使用してから再インジェストするか、コンテンツハッシュチェックを自分で維持してください。
- **小さなチャンクです。** 約80トークン未満の場合、埋め込みがノイジーになります。デフォルトの `rag.chunk_min = 120` は小さな隣接チャンクをマージします。

## 次に何が来るか

- [エージェントプラグイン →](/ja/ai/module/agent/) ツール用、検索ではありません。
- [トレーニング nibiru-coder →](/ja/ai/module/training/) チャットの半分をフレームワークの声で返答させます。
