n8n × Supabase RAG システム – ハンズオンチュートリアル

n8n × Supabase RAG システム – ハンズオンチュートリアル

セクション1: RAGシステムとは何か?基礎知識の解説

RAGの基本概念と活用例

近年、ChatGPTをはじめとする大規模言語モデル(LLM)の進化は目覚ましいものがあります。しかし、LLMには「学習データにない最新情報には対応できない」「誤った情報をあたかも真実のように生成してしまう(ハルシネーション)」といった課題も存在します。これらの課題を解決し、より正確で信頼性の高い情報を生成するために注目されているのが、RAG(Retrieval-Augmented Generation:検索拡張生成)システムです。RAGは、LLMが回答を生成する前に、外部の知識ベースから関連情報を検索・取得し、その情報を基に回答を生成する仕組みを指します。

なぜRAGがこれほど注目されているのでしょうか。それは、RAGを導入することで、LLMが持つ知識の限界を補完し、リアルタイム性や専門性の高い情報に基づいた回答が可能になるからです。例えば、企業の最新の製品情報や社内ドキュメント、あるいは特定の分野の専門論文など、LLMの学習データには含まれていない独自の情報を活用できるようになります。これにより、顧客サポートのFAQシステムや社内ナレッジベースの検索、専門家向けのレポート生成など、多岐にわたる分野での応用が期待されています。

RAGシステムの一般的な構成要素は、主に「検索器(Retriever)」と「生成器(Generator)」の二つに分けられます。検索器は、ユーザーのクエリに基づいて関連性の高い情報を外部の知識ベース(Vector Storeなど)から取得する役割を担います。一方、生成器は、検索器が取得した情報とユーザーのクエリを組み合わせ、LLMを用いて最終的な回答を生成します。このプロセスを通じて、LLMは単に記憶している情報を出力するだけでなく、外部の最新かつ正確な情報を参照しながら、より質の高い回答を提供できるようになるのです。

セクション2: n8nとSupabaseを使ったRAGシステムの全体構成

システムのアーキテクチャと役割分担

n8nとSupabaseを組み合わせたRAGシステムは、それぞれの得意分野を活かし、効率的かつスケーラブルな構成を実現します。このシステムでは、n8nがワークフローのオーケストレーションとLLMとの連携を担い、SupabaseがVector Storeとして検索対象となる知識ベースを管理します。そして、これらを繋ぐ役割としてLangChainが重要な役割を果たします。

具体的にn8nは、RAGシステム全体の「脳」として機能します。ユーザーからのクエリを受け取り、そのクエリを処理するためのワークフローを定義します。これには、クエリの埋め込み(Embedding)生成、Supabaseへの検索リクエスト、そしてSupabaseから取得した情報をLLMに渡して回答を生成させる一連のプロセスが含まれます。n8nの強みは、様々なサービスとの連携が容易であること、そしてノーコード/ローコードで複雑なワークフローを視覚的に構築できる点にあります。

Supabaseは、このシステムにおいて「Vector Store」としての役割を担います。Vector Storeとは、テキストデータを数値ベクトルに変換(埋め込み)して保存し、類似度に基づいて高速に検索できるようにしたデータベースのことです。SupabaseはPostgreSQLをベースにしており、pgvector拡張機能を利用することで、効率的なベクトル検索を実現できます。これにより、私たちが用意したドキュメントやデータがベクトル化され、ユーザーのクエリと意味的に近い情報を素早く検索・取得することが可能になります。

LangChainは、LLMアプリケーション開発のためのフレームワークであり、n8nとSupabaseを連携させる上で非常に重要な役割を果たします。n8nにはLangChainのノードが組み込まれており、特に「LangChain Vector Store Supabase」ノードを利用することで、n8nからSupabaseのVector Storeに簡単にアクセスし、データの投入や検索を行うことができます。この連携により、n8nのワークフロー内で、Supabaseに保存されたベクトルデータに対するクエリ実行、関連情報の取得、そしてその情報を基にしたLLMへのプロンプト生成といった一連のRAGプロセスをシームレスに実現できるのです。

セクション3: n8nのセットアップとSupabase連携の手順

n8nの環境構築と基本設定

n8nを使い始めるには、まず環境をセットアップする必要があります。最も手軽な方法はDockerを利用することです。Dockerがインストールされている環境であれば、以下のコマンド一つでn8nを起動できます。これにより、ローカル環境でn8nの強力なワークフローエンジンをすぐに使い始めることができます。

docker run -it --rm --name n8n -p 5678:5678 -v ~/.n8n:/home/node/.n8n n8n/n8n

このコマンドを実行すると、n8nのコンテナが起動し、http://localhost:5678でn8nのWebインターフェースにアクセスできるようになります。初めてアクセスする際は、管理者アカウントの作成を求められますので、指示に従って設定してください。

クラウドサービスを利用する場合は、n8n CloudやAWS、Google Cloudなどのプラットフォームにデプロイすることも可能です。本ハンズオンでは、手軽に試せるDockerでのローカル環境構築を前提とします。

n8nのWebインターフェースにログインしたら、まずは新しいワークフローを作成してみましょう。左側のメニューから「Workflows」を選択し、「New Workflow」をクリックします。これにより、まっさらなキャンバスが表示され、ここに様々なノードを配置してワークフローを構築していきます。

基本的なワークフロー作成の流れは、まず「Start」ノードから始まり、その後にHTTP RequestノードやFunctionノード、そして今回のRAGシステムで重要なLangChainノードなどを繋げていきます。ノードは左側のパネルからドラッグ&ドロップで配置でき、ノード同士を線で繋ぐことでデータの流れを定義します。各ノードをクリックすると、そのノードの設定パネルが表示され、詳細な設定を行うことができます。

Supabaseプロジェクトの作成と設定

次に、RAGシステムのVector Storeとして利用するSupabaseプロジェクトを作成します。まずはSupabaseの公式サイト(https://supabase.com/)にアクセスし、アカウントを作成またはログインしてください。ログイン後、「New project」をクリックして新しいプロジェクトを立ち上げます。

プロジェクト作成時には、組織名、プロジェクト名、データベースパスワード、そしてリージョンを選択します。特にリージョンは、n8nのデプロイ場所に近いものを選ぶと、ネットワーク遅延を最小限に抑えられます。これらの設定が完了したら、「Create new project」をクリックしてプロジェクトを作成します。

プロジェクトが作成されたら、Vector Store用のテーブルを作成します。SupabaseはPostgreSQLをベースとしているため、pgvector拡張機能を利用します。まず、左側のメニューから「Database」を選択し、「Extensions」タブに移動します。ここでpgvectorを検索し、「Enable extension」をクリックして有効化します。

次に、Vector Storeとして機能するテーブルを作成します。左側のメニューから「SQL Editor」を選択し、以下のSQLクエリを実行してテーブルを作成します。この例では、documentsというテーブル名で、content(元のテキスト)、metadata(付加情報)、embedding(ベクトルデータ)の3つのカラムを持つテーブルを作成します。

CREATE TABLE documents (
  id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
  content text,
  metadata jsonb,
  embedding vector(1536) -- OpenAIのtext-embedding-ada-002の次元数
);

CREATE INDEX ON documents USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);

最後に、n8nからSupabaseにアクセスするためのAPIキーを取得します。左側のメニューから「Project Settings」を選択し、「API」タブに移動します。ここで「Project URL」と「anon public」キー、そして「service_role」キーを控えておきます。特にanon publicキーは、クライアントサイドからのアクセスに利用され、service_roleキーは、より高い権限が必要な操作(例えば、RAGシステムでのデータ投入など)に利用されます。これらの情報はn8nのSupabaseノード設定で必要になりますので、安全な場所に保管しておきましょう。

n8nでSupabase Vector Storeノードを使う方法

n8nでSupabaseをVector Storeとして利用するには、「LangChain Vector Store Supabase」ノードを使用します。このノードは、n8nのLangChain統合の一部として提供されており、Supabaseのベクトルデータベースとの連携を容易にします。

まず、n8nのワークフローキャンバスに「LangChain Vector Store Supabase」ノードを追加します。ノードをダブルクリックして設定パネルを開きます。ここで、Supabaseプロジェクトへの接続情報を入力します。

必須の設定項目:

  • Supabase Project URL: SupabaseプロジェクトのURL(例: https://your-project-ref.supabase.co
  • Supabase API Key: Supabaseのanon publicキーまたはservice_roleキー。RAGシステムでデータ投入も行う場合はservice_roleキーを使用します。
  • Table Name: 先ほど作成したVector Storeのテーブル名(例: documents
  • Content Column: テキストコンテンツが保存されているカラム名(例: content
  • Metadata Column: メタデータが保存されているカラム名(例: metadata
  • Embedding Column: ベクトルデータが保存されているカラム名(例: embedding

これらの情報を正確に入力することが、Supabaseとの正常な連携には不可欠です。特にAPIキーの入力ミスは、認証エラーの主要な原因となりますので、慎重に確認してください。

ノードの設定が完了したら、このノードを使ってデータを投入したり、クエリを実行したりできます。例えば、RAGシステムで新しいドキュメントをSupabaseに保存する場合、まず「Text Splitter」ノードなどでドキュメントをチャンクに分割し、それぞれのチャンクを「OpenAI Embeddings」ノードなどでベクトル化します。その後、そのベクトルデータと元のテキスト、メタデータを「LangChain Vector Store Supabase」ノードに渡し、「Operation」を「Add Documents」に設定してSupabaseに保存します。

基本的なクエリの流れは、「LangChain Vector Store Supabase」ノードの「Operation」を「Similarity Search」に設定し、検索したいクエリの埋め込みベクトルを入力として渡します。ノードはSupabase内で最も類似度の高いドキュメントを検索し、その結果を次のノードに渡します。この取得された関連情報が、LLMへのプロンプトに組み込まれ、より文脈に沿った回答生成に繋がるのです。

以下は、n8nの「LangChain Vector Store Supabase」ノードのJSON設定例の一部です。実際には、ワークフロー全体の中で他のノードと連携して動作します。

{
  "node": [
    {
      "parameters": {
        "supabaseProjectUrl": "={{ $env.SUPABASE_PROJECT_URL }}",
        "supabaseApiKey": "={{ $env.SUPABASE_API_KEY }}",
        "tableName": "documents",
        "contentColumn": "content",
        "metadataColumn": "metadata",
        "embeddingColumn": "embedding",
        "operation": "similaritySearch",
        "query": "={{ $json.query }}",
        "topK": 4
      },
      "name": "LangChain Vector Store Supabase",
      "type": "n8n-nodes-langchain.vectorstoresupabase",
      "typeVersion": 1,
      "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
    }
  ]
}

この設定例では、環境変数からSupabaseのURLとAPIキーを取得し、documentsテーブルに対してquery変数で指定されたクエリで類似検索を行い、上位4件の結果を取得するように設定しています。このように、n8nのノード設定は非常に柔軟で、様々なRAGのユースケースに対応できます。

セクション4: RAGシステムの動作確認とトラブルシューティング

動作確認のポイントとテスト方法

RAGシステムを構築したら、実際に意図通りに動作するかを確認することが非常に重要です。ここでは、簡単なクエリを投げて結果を確認する方法と、期待されるレスポンスの例、そして問題が起きた場合のチェックポイントを解説します。

  • 簡単なクエリを投げて結果を確認する方法: n8nのワークフローを「Execute Workflow」ボタンで実行し、テスト用のクエリを投入します。例えば、Supabaseに「n8nとは何か?」に関するドキュメントを投入している場合、「n8nの機能について教えて」といったクエリを投入してみます。ワークフローの実行結果は、各ノードの出力データとして確認できます。特に「LangChain Vector Store Supabase」ノードの出力で、関連するドキュメントが正しく取得されているかを確認しましょう。
  • 期待されるレスポンスの例: 理想的なRAGシステムでは、クエリに対してSupabaseから関連性の高いドキュメントが複数件取得され、その情報に基づいてLLMが自然で正確な回答を生成します。例えば、「n8nの機能について教えて」というクエリに対して、n8nの主要機能(ワークフロー自動化、多数のサービス連携、ローコード開発など)が記述されたドキュメントが取得され、最終的なLLMの回答にそれらの情報が反映されていることが期待されます。
  • 問題が起きた場合のチェックポイント: もし期待通りの結果が得られない場合は、以下の点をチェックしてください。
    • Supabaseへのデータ投入: まず、Supabaseのdocumentsテーブルに、検索対象となるデータが正しく投入されているかを確認します。contentカラムにテキストデータが、embeddingカラムにベクトルデータが、それぞれ適切に保存されているかを確認しましょう。
    • n8nのノード設定: 「LangChain Vector Store Supabase」ノードのSupabase Project URL、API Key、Table Name、Content Column、Metadata Column、Embedding Columnがすべて正確に設定されているか再確認します。
    • 埋め込みモデルの整合性: ドキュメントをベクトル化する際に使用した埋め込みモデル(例: OpenAIのtext-embedding-ada-002)と、クエリをベクトル化する際に使用するモデルが同じであることを確認します。異なるモデルを使用すると、ベクトル空間が異なり、類似度検索が正しく機能しません。
    • LLMへのプロンプト: 取得した関連情報が、LLMへのプロンプトに適切に組み込まれているかを確認します。情報が正しく渡されていないと、LLMは関連情報を参照せずに回答を生成してしまいます。

よくあるトラブルと対処法

RAGシステムの構築中に遭遇しやすいトラブルとその対処法をまとめました。これらのポイントを押さえておくことで、スムーズな開発に繋がります。

  • APIキーの認証エラー:
    • エラーメッセージ例: 401 UnauthorizedInvalid API key など。
    • 原因: SupabaseのAPIキーが間違っている、または権限が不足している可能性があります。
    • 対処法: n8nの「LangChain Vector Store Supabase」ノードに設定しているSupabase API Keyが、Supabaseプロジェクト設定の「API」タブで取得したキーと完全に一致しているか確認してください。特に、データ投入を行う場合はservice_roleキーが必要になることがあります。また、環境変数を使用している場合は、環境変数の設定も確認しましょう。
  • データベース接続の問題:
    • エラーメッセージ例: Connection refusedDatabase connection error など。
    • 原因: Supabase Project URLが間違っている、またはネットワークの問題が考えられます。
    • 対処法: Supabase Project URLが正しい形式(https://your-project-ref.supabase.co)で入力されているか確認します。また、n8nが動作している環境からSupabaseへのネットワーク接続が可能か、ファイアウォールなどの設定を確認してください。
  • n8nワークフローのエラー原因と解決策:
    • エラーメッセージ例: 特定のノードで赤いエラー表示、TypeErrorUndefined property など。
    • 原因: ノード間のデータの受け渡しが正しくない、またはノードの設定値が期待する型と異なる場合など。
    • 対処法: n8nのワークフロー実行履歴を確認し、エラーが発生しているノードを特定します。そのノードの入力データと出力データを詳細に確認し、期待するデータ形式と合致しているか検証します。特に、JSONデータや配列の処理でエラーが発生しやすいので、Functionノードなどでデータの整形が必要な場合があります。
  • ベクトル検索結果が期待通りでない:
    • 原因: 埋め込みモデルの不一致、データの前処理不足、またはpgvectorのインデックス設定の問題。
    • 対処法: ドキュメントとクエリの埋め込みに同じモデルを使用しているか再確認します。また、ドキュメントのチャンク分割が適切か(大きすぎず、小さすぎず)見直します。Supabaseのpgvector拡張機能が有効になっており、インデックス(例: ivfflat)が正しく作成されているかも確認しましょう。
  • LLMの回答が不正確またはハルシネーションを起こす:
    • 原因: 取得した関連情報が不足している、またはLLMへのプロンプトが不明瞭。
    • 対処法: 「LangChain Vector Store Supabase」ノードで取得されるドキュメントの数(topK)を増やしてみる、あるいは検索クエリの質を改善します。LLMへのプロンプトに、取得した関連情報を明確に含めるように調整し、LLMがその情報に基づいて回答を生成するように指示を強化します。

セクション5: まとめと次のステップ

今回のハンズオンの振り返り

今回のハンズオンチュートリアルでは、n8nとSupabaseを連携させたRAGシステムを構築する基本的な手順を学びました。RAGシステムがLLMの課題を克服し、より正確で信頼性の高い情報生成を可能にする仕組みであることを理解し、その全体構成においてn8nがワークフローのオーケストレーションを、SupabaseがVector Storeとしての役割を担うことを確認しました。特に、n8nの「LangChain Vector Store Supabase」ノードを活用することで、Supabaseのベクトルデータベースとの連携が非常にスムーズに行えることを実感いただけたかと思います。

初心者がRAGシステムを構築する上で重要な知識として、n8nの環境構築と基本的なワークフロー作成、Supabaseプロジェクトの立ち上げとpgvectorを利用したVector Storeの構築、そしてAPIキーや接続情報の正確な設定が挙げられます。これらのステップを一つ一つ丁寧に実行することで、私自身もRAGシステムの仕組みを深く理解し、実際に動くシステムを構築できる喜びを感じることができました。特に、APIキーや接続情報の入力ミスは動作不良の主要因となるため、細心の注意を払う必要があることを改めて認識しました。

このハンズオンを通じて得た知識は、RAGシステムの基盤を理解するための第一歩です。今後は、さらに複雑なドキュメントの前処理、異なる埋め込みモデルの比較、LLMへのプロンプトエンジニアリングの最適化など、様々な応用例や拡張の方向性が考えられます。例えば、特定の業界に特化した知識ベースを構築したり、リアルタイムで更新される情報をRAGシステムに組み込んだりすることで、より高度なアプリケーション開発へと繋げることができるでしょう。

【参考資料・出典】

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール