PROD欧州主権の BaaS プラットフォームダッシュボードを開く →

ネイティブAI · 10 分読み取り

チュートリアル: Postgres および pgvector を使用した RAG パイプライン

Affane Daylami · Fondateur · 2026年4月13日

ブログに戻る

Postgres 上で RAG パイプラインを構築するには、通常、テキスト スライサー、埋め込み呼び出し、pgvector テーブル、類似性クエリなどのいくつかの部分を自分で組み立てる必要があります。これは古典的な LangChain + PGVectorchain です。 Aurabase では、このパイプラインはサーバー側にすでに存在しています。2 つの呼び出し ragIngest() と rag() がこれを置き換えますが、標準の PostgreSQL と pgvector に依存しており、独自のベクター ベースを追加する必要はありません。

この英語のテキストはフランス語のオリジナルから自動的に生成されたもので、まだレビューされていません。
このページは自動翻訳されました。英語版が正式です。

The native RAG is part of thenative AI integrated into the Aurabasebackend, alongside NL2SQL: not a third-party service to be assembled on top of a general base. Prerequisites to follow this tutorial: an existing Aurabase project, a configured LLM provider (OpenAI or Google Gemini for embeddings, one of the three native providers for generation), and a project API key.

必需品
  • Aurabase RAG パイプラインは、ドキュメントのインデックスを作成する ragIngest() と、クエリを実行して応答を生成する rag() という 2 つの呼び出しで構成されます。チャンク化、埋め込み、ベクトル検索はサーバー側で管理されます。
  • 内部的には標準の PostgreSQL と pgvector です。ディメンション クラス (768、1536、3072) ごとに 1 つのベクトル列とクラスごとに部分的な HNSW インデックスを持つ embeddings テーブルです。
  • チャンキングでは実際のトークナイザー (tiktoken o200k) を使用し、構成可能なオーバーラップと大きなドキュメントの爆発防止ガードを備えています。
  • 取得されたコンテンツは、プロンプトに挿入される前に無効化されます。つまり、タグをエスケープしてシステム命令を偽装しようとするドキュメントは、明示的に解除されます。
  • OpenAI と Gemini のみが Aurabase 側でエンベディングを生成します。 Anthropic/Claude にはパブリックな埋め込み API がありません。最終応答を生成するために予約されたままです。
#
コンセプト

この RAG パイプラインの仕組み

パイプラインは 5 つの段階で行われます。取り込まれると、テキストは分割され、各チャンクがバッチでベクトル化されて保存されます。クエリを実行すると、コサイン類似度によって保存されたチャンクと比較して質問が順番にベクトル化され、最も近いスニペットが生成モデルに送信されるプロンプトに挿入されます。

チャンキング(tiktoken)→エンベディング(バッチ)→pgvectorストレージ(HNSW)→類似検索→拡張生成

運用環境で重要なアーキテクチャの詳細: 埋め込みプロバイダーまたは生成プロバイダーへのネットワーク呼び出し中に Postgres 接続は保持されません。 DB トランザクションは、外部呼び出しの前に終了し、外部呼び出し後に再び開きます。これにより、サードパーティのネットワーク遅延のために共有 PgBouncer バックエンドがブロックされることはありません。

#
ステップ1

プロジェクトを作成する

一般的な自己ホスト型 pgvector とは異なり、このパイプライン用に CREATE EXTENSION vector を実行したり、テーブルを自分で作成したりする必要はありません。プロジェクトの embeddings スキーマとそのベクトル列および HNSW インデックスは、プロジェクトの作成時に自動的にプロビジョニングされます。

terminalbash
# Aurabase アカウント + CLI
npm i -g @aurabase/cli
aura login

# プロジェクトを作成し、このフォルダーにリンクします
aura projects create mon-assistant --engine postgres
aura link --project-id <uuid-du-projet>

# リンクされたプロジェクトの API キーを取得します
aura projects api-keys

埋め込みプロバイダーは、プロジェクト側 (スタジオ → IA → サプライヤー) で一度構成されます。ベクトルの有効次元、つまり embeddingsテーブルで使用される列を決定するのはこのプロバイダーです。

#
ステップ2

ragIngest() を使用してドキュメントにインデックスを付ける

ドキュメントのインデックスを作成するには 1 回の呼び出しで十分です。テキストは複数のチャンクに分割され、各チャンクがベクトル化されて、要求された名前空間に格納されます。分割には、スペースによる単純な分割ではなく、実際のトークナイザー (tiktoken、エンコード o200k_base) が使用され、一部のアジア言語のようにスペースのないテキストでも正しいままになります。

app/api/ingest/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { content, metadata } = await req.json()

  const { data, error } = await aura.ai.ragIngest({
    namespace: 'docs-produit',
    content,
    metadata,
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data) // { ID、チャンク }
}

生の HTTP では、同等のルートは POST /v1/ai/{project_id}/rag/ingestで、プロジェクトの API キーによって認証されます。

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/rag/ingest \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "docs-produit",
    "content": "Le texte complet de votre document ici...",
    "metadata": { "source": "guide-utilisateur.pdf" }
  }'

デフォルトでは、取り込みは冪等です。ドキュメント識別子は自動的に導出されます (コンテンツの SHA-256 ハッシュ、または指定した場合は metadata.document_id)。同じコンテンツを再取り込むと、既存のチャンクが複製されるのではなく置き換えられるため、定期的な同期ジョブを安全に再実行できます。

#
ステップ3

実際に Postgres に導入されるもの

ここには独自の魔法はありません。ベクトルを受け取るテーブルは通常の Postgres テーブルで、ディメンション クラスごとに 1 つの vector 列と、列ごとに部分的な HNSW インデックス (そこに設定されている行でのみアクティブです) があります。簡略化した実際の定義は次のとおりです。

プロジェクトのプラットフォーム図(簡略化)sql
create table embeddings (
  id               uuid primary key default gen_random_uuid(),
  project_id       text not null,
  namespace        text not null,
  content          text not null,
  embedding_768    vector(768),
  embedding_1536   vector(1536),
  embedding_3072   vector(3072),
  embedding_model  text,
  dims             int,
  metadata         jsonb default '{}'::jsonb,
  created_at       timestamptz not null default now()
);

-- ディメンションクラス別の部分的なHNSWインデックス
create index idx_embeddings_vec_1536 on embeddings
  using hnsw (embedding_1536 vector_cosine_ops)
  where embedding_1536 is not null;

-- 2000 次元を超えると、HNSW はベクトル型をサポートしません。
-- クラス3072のhalfvecにキャスト
create index idx_embeddings_vec_3072 on embeddings
  using hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  where embedding_3072 is not null;

各検索では、インデックスの vector_cosine_ops および halfvec_cosine_ops 演算子クラスの対象となるコサイン距離演算子 (<=>) とベクトルが比較されます。 HNSW と IVFFlat のリコール/レイテンシーのトレードオフの詳細については、HNSW のインデックス作成に特化した記事 を参照してください。。埋め込みディメンション自体の選択については、 の比較 768 vs 1536 vs 3072を参照してください。

#
ステップ4

rag() を使用してクエリを実行し、応答を生成する

クエリ側では、rag() は、質問のベクトル化、名前空間の類似性による検索、拡張プロンプトの構築、および生成モデルの呼び出しを、クライアント側の 1 回のネットワーク ラウンド トリップで連鎖させます。

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.rag({
    question,
    namespace: 'docs-produit',
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

応答には、実際に使用されるプロバイダーとともに、生成された応答とそのソースが含まれます。

回答(抜粋)json
{
  "data": {
    "answer": "D'après la documentation, ...",
    "sources": [
      { "id": "...", "content": "...", "similarity": 0.87 }
    ],
    "model": "claude-3-5-sonnet",
    "tokens": 412,
    "provider": "anthropic",
    "fallback_used": false
  }
}

取得したコンテンツがそのままシステム プロンプトに挿入されることはありません。これは信頼性の低いデータ (ユーザーアップロード、インデックス付きページ) です。たとえば、セクション終了タグとその後に続く誤った指示を含むドキュメントは、組み立て前に無力化され、その山括弧は括弧に置き換えられ、テキストは保持されますが、構造は解除されます。

別のモデルで索引付けされたコーパス

名前空間が空でなくても rag() が何も見つからなかった場合、応答には誤解を招く沈黙ではなく明示的な警告が含まれます。コーパスはおそらく別のモデルまたは別の埋め込み次元でインデックス付けされています。 POST /v1/ai/{project_id}/rag/{namespace}/reindexを介してインデックスを再作成します。

#
比較

LangChain と手作りの pgvector から: 何が変わるのか

LangChain を使用して PostgreSQL 上に RAG チャットボットをすでに構築している場合は、基盤となるデータベースを変更することなく、各手動ブリックにサーバー側で管理される同等の機能が用意されています。

テキストを分割する自分で設定する RecursiveCharacterTextSplitterragIngest(): 統合された tiktoken チャンキング、デフォルトで 512 トークン / 64 オーバーラップ
埋め込みOpenAIEmbeddings への手動呼び出し、バッチ制限の管理自動的にバッチ処理される組み込みの一時的な再試行
ベクトルストレージpgvector テーブル + HNSW インデックスを自分で作成して移行するプロジェクトごとにプロビジョニングされたスキーマとインデックス
検索 + プロンプトPGVector.similarity_search() を使用してプロンプトを手動で組み立てますrag(): 1 回の呼び出しで検索と拡張生成を実行
回復されたコンテンツプロンプトにそのまま挿入される組み立て前の構造タグの自動無効化

この種の手動アセンブリを使用して Supabase 上に構築された既存のプロジェクトを移行していますか?残りのバックエンド (スキーマ、RLS ポリシー、SDK) の移行ロジックについては、 Supabase から Aurabase への移行ガイドで説明されています。

#
生産

本番環境に入る前に知っておくべき設定と制限

コストと遅延に直接影響する 3 つの設定は、すべて aura-aiサービス コードで検証されています。一時的な埋め込み呼び出し (ネットワーク障害、プロバイダー エラー 429) の試行回数はデフォルトで 3 回で、ベース バックオフは 100 ミリ秒です。大きなドキュメントは、単一の大規模ドキュメントで失敗することなくサプライヤーの API 上限を尊重するために、デフォルトで 2048 チャンクに制限されたサブバッチに埋め込まれます。ガードレール (デフォルトで 10,000 チャンク、構成可能) は、異常な数のチャンクを生成するドキュメントの取り込みを明示的に拒否します。

検索側では、HNSW 候補リストのサイズが max(64, top_k × 4)に自動的に調整されます。つまり、リクエストする結果が増えるほど、インデックスはより多くの候補を探索して再現率を維持します。コーパスに特定のプロファイルがある場合は、環境変数を介して固定値を使用することができます。

異なるモデルのベクトル空間が互いに比較されることはありません。各検索は現在の埋め込みモデルに限定されたままであり、モデルを変更するには、結果の一貫性を損なうサイレントスイッチではなく、明示的な再インデックス付けが必要です。

#
正直さ

注意すべき電流制限

埋め込みディメンションは、サポートされる 3 つのクラス (768、1536、または 3072) のいずれかに該当する必要があります。別のディメンションを返すプロバイダーは明示的なエラーで拒否され、切り捨てられたりサイレント キャストされることはありません。

埋め込みの生成は、3 つのネイティブ プロバイダーのうち、OpenAI または Google Gemini 経由でのみ利用できます。 Anthropic/Claude はパブリックの埋め込み API を公開していないため、このパイプラインの最終応答を生成するためにのみ使用され、ベクトル化には決して使用されません。

JavaScript SDK は、rag() 呼び出しの top_k および threshold オーバーライドをまだ公開していません。これらは直接 HTTP で引き続きアクセスでき、それぞれ [1, 50] と [0, 1] に制限されていますが、現在のように aura.ai.rag() からはアクセスできません。デフォルトの類似性しきい値 (0.3) は意図的に許容されています。プロンプト内の無関係なソースを避けるために、密度の高いコーパスに絞り込みます。

#
さらに進んでください

さらに進むには

RAG は、非構造化コンテンツ (ドキュメント、メモ、チケット) に関する質問をカバーします。リレーショナルデータに関する質問の場合、Aurabase のネイティブ NL2SQL は、質問を検証済みの SQL に直接変換します。上記の HNSW パラメータとディメンション クラスの詳細については、HNSW インデックスに関する記事 、埋め込みディメンションの比較 および 、を参照してください。完全な API リファレンスは、 RAG および pgvector ドキュメント および AI ゲートウェイ ドキュメントのままです。

#
よくある質問

よくある質問

pgvector 拡張機能と HNSW インデックスを自分で管理する必要がありますか?+
いいえ。埋め込みスキーマ、pgvector 拡張機能、および部分的な HNSW インデックス (ディメンション クラスごとに 1 つ: 768、1536、3072) は、プロジェクトの作成時に自動的にプロビジョニングされます。 ragIngest() を直接呼び出してから、rag() を呼び出します。コーパスに特定のプロファイルがある場合、インデックスの微調整 (ef_search、iterative_scan モード) はサーバー側で引き続きアクセスできます。
自分のユースケースではどの埋め込みディメンションを選択すればよいですか?+
Aurabase は、サプライヤーから返されたディメンションを、サポートされている 3 つのクラス (768、1536、および 3072) に対して検証します。選択は、設定されている埋め込みモデルによって異なります (たとえば、OpenAI の text-embedding-3-small は 1536 ディメンションを生成します)。また、埋め込みディメンションに特化した比較で詳しく説明されている再現率、コスト、ストレージ サイズの間の妥協点が含まれます。

導入の準備はできていますか?

5 分でバックエンドが完成します。

クレジット カードは不要 · 500 MB 無料 · 50,000 MAU