メインコンテンツへ移動
AIチュートリアル

ゼロから構築するAdaptive-RAG ECカスタマーサポート:適応型検索・意図認識・注文ツールの実践

このチュートリアルでは、Adaptive-RAG ECカスタマーサポートをローカルで実行し、動的検索、複数ラウンドの証拠補完、忠実度検証、JevとDeepSeekによる意図認識を学びます。さらに、ポリシーに関する質疑応答、注文照会、有人確認、テスト評価、Dockerデプロイも体験できます。

ゼロから構築するAdaptive-RAG ECカスタマーサポート:適応型検索・意図認識・注文ツールの実践

プロジェクト概要

Adaptive-RAG ECカスタマーサポートは、複数条件のポリシー問い合わせを対象としたインテリジェントなカスタマーサポートプロジェクトです。証拠不足、根拠のない回答、複雑な質問を一度の検索で完全に取得できないといった問題の解決を主な目的としています。バックエンドは FastAPI と LangGraph、フロントエンドは React で構成されています。ユーザーの意図と質問の複雑さに応じて、直接回答、ナレッジ検索、追加検索、ツール実行、有人確認、回答拒否の間で処理経路を動的に選択できます。

このプロジェクトは、ローカルデモ、Adaptive RAG ワークフローの学習、エンジニアリング検証に適しています。ポリシーソースの引用、デモ注文の照会、確認待ち操作、会話メモリ、SSE 応答に対応していますが、注文データと配送データは実際の業務データではありません。

現在の API はクライアントから渡された user_id を直接受け付けており、実際の本人確認はまだ行っていません。信頼できる本人認証、TLS、アクセス制御を導入せずに、プロジェクトをそのままインターネットへ公開しないでください。

リクエストの処理方法

ユーザーが Web ページまたは HTTP API から質問を送信すると、リクエストは入力ガード、意図識別、複雑度ルーティングを順に通過します。その後、適切な処理分岐が選択され、回答生成、忠実度チェック、会話メモリの更新、引用の返却が行われます。

ユーザー → Web / HTTP API → 入力ガード
     → 意図識別 → 複雑度ルーティング
       ├─ 直接回答
       ├─ 検索 → 再ランキング → 必要に応じて追加検索
       ├─ 計画 → ツール実行 / 有人確認
       └─ 回答拒否
     → 生成と忠実度チェック → 会話メモリ → 回答と引用

意図識別にはデフォルトの DeepSeek を使用できるほか、TypeSafe Jev に切り替えることもできます。ただし、Jev が置き換えるのは意図分類ノードだけです。複雑度判定、クエリ書き換え、タスク計画、回答生成、忠実度チェック、メモリ要約など、その他の LLM ノードは引き続き DeepSeek が担当します。

主な機能

  • 適応型ルーティング:業務上の意図と質問の複雑さを組み合わせ、直接回答、単一ターン検索、マルチターン検索、ツール実行、回答拒否を選択します。
  • ハイブリッド検索:BM25 と密ベクトル検索を組み合わせ、RRF で結果を統合し、Cross-Encoder による再ランキングも有効化できます。
  • 証拠の強化:クエリ書き換え、証拠不足時の追加検索、回答の忠実度チェック、自動修正に対応します。
  • 2種類の意図バックエンド:デフォルトでは DeepSeek を使用し、Jev の構造化 choice インターフェースで定義済みの 14 種類の業務意図を識別することもできます。
  • ドキュメント処理:Markdown を直接サポートします。オプション依存関係とシステムツールをインストールすると、PDF、Office、OCR ドキュメントも解析できます。
  • 構造化チャンク:通常のテキストにはデフォルトで 500 文字のウィンドウと 60 文字のオーバーラップを使用します。認識された表は個別のチャンクに分け、タイトル、セクション、ソースなどのメタデータを保持します。
  • 業務ツール:注文関連のデモツールを提供し、権限チェック、フォールバック、有人確認、冪等性の仕組みを備えています。MCP ツールを接続することもできます。
  • エンジニアリング機能:会話メモリの圧縮、構造化ログ、Prometheus メトリクス、ヘルスチェック、自動テストを含みます。

実行環境の準備

基本要件

  • Python 3.11 以上。
  • Web フロントエンドを実行する場合は、Node.js 20.19+ または 22.12+ と npm を用意してください。
  • デフォルトのローカルモードでは SQLite とメモリ検索コンポーネントを使用するため、事前に Docker を起動する必要はありません。

Windows PowerShell のインストール手順

リポジトリをクローンしてプロジェクトのルートディレクトリに移動したら、仮想環境を作成し、開発依存関係をインストールし、設定ファイルをコピーしてデモデータを生成します。

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
Copy-Item .env.example .env
.\.venv\Scripts\python.exe -m scripts.seed_demo

プロジェクトのルートディレクトリにすでに .env が存在する場合は、元のファイルを保持してコピーコマンドをスキップしてください。その後、FastAPI を起動します。

.\.venv\Scripts\python.exe -m uvicorn app.asgi:app --reload --host 127.0.0.1 --port 8000

macOS と Linux

macOS または Linux では、仮想環境を作成して有効化し、対応するインストールコマンドを実行します。

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
python -m scripts.seed_demo
python -m uvicorn app.asgi:app --reload --host 127.0.0.1 --port 8000

モデルとローカルサービスの設定

プロジェクトのルートディレクトリにある .env を開きます。次の設定を優先的に確認してください。

  • DEEPSEEK_API_KEY:DeepSeek ワークフローとデフォルトの意図分類を有効にします。実際の API 呼び出しには料金が発生する場合があります。
  • INTENT_BACKEND:デフォルトの deepseek またはオプションの jev を設定できます。
  • JEV_API_KEY:Jev による意図分類を有効にする場合に必要です。
  • JEV_MODEL:現在のプロジェクトのデフォルト値は jev-1.13.0 です。
  • DATABASE_URL:デフォルトでは sqlite+aiosqlite:///./data/local/app.db を使用します。
  • KNOWLEDGE_DIR:デフォルト値は knowledge です。このディレクトリ内のナレッジドキュメントは起動時にデータベースへ登録されます。
  • LOCAL_EMBEDDING_ENABLED:ローカル意味ベクトル機能を制御します。
  • CROSS_ENCODER_ENABLED:ローカル再ランキング機能を制御します。
  • REDIS_URL と QDRANT_URL:オプションの外部キャッシュおよびベクトルサービスを設定します。

DeepSeek のキーを設定しなくても、オフラインのデモロジックは利用できます。ただし、回答品質は実際のモデルモードとは異なります。すべての変数については、設定リファレンス と 環境ファイルの例 を確認してください。

React チャット画面の起動

バックエンドプロセスを実行したまま、別のターミナルでフロントエンドディレクトリに移動します。

cd frontend
npm ci
npm run dev

http://127.0.0.1:5173 にアクセスするとチャット画面を開けます。開発サーバーは /api リクエストをローカルマシンの 8000 ポートへプロキシします。

フロントエンドはソース引用、ローカルの会話一覧、操作確認カードに対応しています。バックエンドは回答の検証が完了した後、SSE を通じて内容を分割送信します。npm run build を実行して frontend/dist を生成すると、FastAPI はそのディレクトリを検出し、ルートパスからフロントエンドページを提供します。

基本的な使い方:返品・交換ポリシーの問い合わせ

まず、サービスの状態を確認します。

次に、PowerShell から複数のポリシー条件を含む質問をチャット API に送信します。

$payload = @{
    message = "カスタムマグカップが7日を過ぎていますが、品質に問題があります。返品できますか?"
    user_id = "u_demo"
} | ConvertTo-Json

Invoke-RestMethod `
    -Uri "http://127.0.0.1:8000/api/v1/chat" `
    -Method Post `
    -ContentType "application/json; charset=utf-8" `
    -Body ([System.Text.Encoding]::UTF8.GetBytes($payload))

システムはまず返品・交換に関連する意図を識別し、質問の複雑さに応じてポリシードキュメントを検索するかどうかを判断します。初回の証拠が不十分な場合、ワークフローはクエリを書き換えて追加検索を実行できます。回答生成後には、回答が検索された証拠に忠実かどうかも確認し、利用可能なソース引用を返します。

HTTP API のほか、バックエンドの実行中に次のコマンドを実行してターミナルクライアントを使用することもできます。

python -m app.cli

基本的な使い方:デモ注文の照会と操作

scripts.seed_demo はデモ注文を明示的に作成します。API の起動だけではこれらのデータは自動的に書き込まれないため、初回実行時にデータ初期化をスキップしないでください。デモユーザーは u_demo で、利用可能な注文は次のとおりです。

  • ORD10001:発送済み、商品はノイズキャンセリングヘッドホン。
  • ORD10002:配達済み、商品はカスタムマグカップ。
  • ORD10003:支払い済み・未発送、商品は T シャツ。

たとえば、チャット画面に 注文 ORD10003 をキャンセル と入力します。確認が必要な操作を実行すると、システムは pending_action を返す場合があります。確認リクエストには応答に含まれる session_id を指定し、pending_action.action_id を confirm_action_id に設定する必要があります。Web ページでは確認カードを使ってこのフローを完了できます。

確認待ちの操作は、デフォルトでサーバープロセス内に 15 分間保存されます。サービスの再起動や、別のプロセスへのリクエスト切り替え後には、操作を再度開始する必要がある場合があります。具体的なフィールドと API 形式については、API リファレンス を参照してください。

高度な設定:Jev による意図識別の有効化

意図分類ノードを TypeSafe Jev に切り替えるには、ローカルの .env に次の設定を追加または変更します。

INTENT_BACKEND=jev
JEV_API_KEY=your_jev_api_key
JEV_ENDPOINT=https://api.typesafe.ai/v1/systemone
JEV_MODEL=jev-1.13.0
JEV_TIMEOUT_SECONDS=10
JEV_MAX_RETRIES=2
JEV_INTENT_APPLY_OVERLAY=true

DEEPSEEK_API_KEY=your_deepseek_api_key

保存後、バックエンドを再起動します。Jev は HTTP インターフェース経由で接続するため、専用 SDK をインストールする必要はありません。返却結果は Pydantic による検証を経て、統一された分類結果へ変換されます。

Jev のキーがない場合、リクエストが失敗した場合、またはレスポンスが不正な場合、システムは既存の IntentClassifier にフォールバックします。フォールバック経路では、設定済みの DeepSeek を優先して使用し、オフラインまたはモデル呼び出しに失敗した場合はルール分類を継続して使用します。再試行可能なエラーには指数バックオフを使用し、現在の実装では JEV_MAX_RETRIES は最大試行回数を表します。

JEV_INTENT_APPLY_OVERLAY は、Jev による分類が成功した後のルールベースの補正を制御し、デフォルトで有効になっています。このオプションは、フォールバック分類器自身のオーバーレイは制御しません。デフォルトの意図分類に戻すには、INTENT_BACKEND を deepseek に戻してください。

高度な設定:検索とドキュメント解析の強化

ローカルベクトル検索とリランキングの依存関係をインストール

.\.venv\Scripts\python.exe -m pip install -e ".[rerank]"

rerank の依存関係は、ローカルの密ベクトルモデルと Cross-Encoder に使用されます。デフォルトのベクトルモデルは BAAI/bge-small-zh-v1.5、デフォルトのリランキングモデルは BAAI/bge-reranker-base です。初回の読み込み時にはモデルの重みがダウンロードされる場合があります。モデルを利用できない場合、システムはフォールバックするため、完全なモデル構成と同等の効果は得られません。

拡張ドキュメント解析の依存関係をインストール

.\.venv\Scripts\python.exe -m pip install -e ".[docs]"

docs の依存関係は、Unstructured によるドキュメント解析に使用されます。PDF、OCR、Office ファイルを処理する場合は、Poppler、Tesseract と中国語言語パック、LibreOffice のインストールも必要になる場合があります。詳しい要件は 解析と検索の説明を参照してください。

知識チャンクの ID は、ドキュメントのパスとチャンク番号から生成されます。パスと分割結果が変わらない場合、再登録しても ID の一貫性を維持できます。ファイルの移動、内容の編集、またはチャンク分割戦略の変更後は、過去の参照が同じ内容を指し続けることは保証されません。

Docker で完全なサービスを起動

API、PostgreSQL、Redis、Qdrant、ビルド済み Web フロントエンドを同時に実行する場合は、まずローカルの .env を準備してから、次を実行してください。

docker compose up --build

起動後、http://127.0.0.1:8000 にアクセスします。Compose のデータベースパスワードとポートマッピングは、ローカルデモのみを対象としています。インターネット公開前には、デモ用パスワードの変更、データベースとキャッシュのポート制限、信頼できる認証と TLS の有効化、堅牢な永続化および運用計画の策定が必須です。

テスト、静的チェック、評価

プロジェクトのルートディレクトリで、バックエンドのテストと品質チェックを実行します。

.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\python.exe -m ruff check app eval tests
.\.venv\Scripts\python.exe -m mypy
.\.venv\Scripts\python.exe -m eval.runner --task retrieval

フロントエンドのテストとビルドコマンドは、frontend ディレクトリで実行する必要があります。

npm test
npm run build

テスト設定では、ローカルモデルのキーを分離し、テスト用データベースを使用します。実モデルを使った評価を個別に実行する前に、モデルとネットワークの設定を確認してください。外部モデルの呼び出しには料金が発生する場合があります。

Jev と DeepSeek の意図分類を比較

2 種類のモデルのローカルキーを設定した後、同じサンプルと同じオーバーレイ条件で比較を実行できます。

.\.venv\Scripts\python.exe -m eval.compare_intent --backend both --limit 10 --no-overlay --output data/local/intent-comparison.json

レポートには、正解率、P50 および P95 レイテンシ、フォールバック回数、ルールによるカバー回数が含まれます。--no-overlay は両方の分類器でルールによる補正を無効にし、モデル自体の分類結果を確認しやすくします。この引数を削除すると、オーバーレイ適用後の効果を比較できます。

現在の意図データセットは開発用データセットであり、正解率にはフォールバックサンプルが含まれます。そのため、Jev 単独モデルの汎化能力を直接示すものではありません。過去の評価結果も、現行バージョンで再検証済みであることを意味せず、実際の業務効果を保証するものでもありません。

実用的なエンジニアリングのアドバイス

  1. まずデフォルトのローカルモードでフローを検証する:SQLite とメモリ検索コンポーネントで基本的なデモを実行できるため、最初から外部データベースやベクトルサービスを導入する必要はありません。
  2. 意図モデルとワークフローモデルを分けて考える:Jev に切り替えても、他の DeepSeek ノードは置き換わりません。完全なオンラインワークフローを実行する場合は、引き続き DeepSeek の設定が必要です。
  3. ヘルスエンドポイントで問題を切り分ける:/api/v1/health はプロセスの確認に使用し、/api/v1/ready は依存関係の準備状況の確認に適しています。
  4. チャンク分割戦略の変更は慎重に行う:パス、テキスト内容、またはチャンク分割パラメータの変更は、チャンク ID や過去の参照に影響する可能性があります。
  5. プロセス内の確認状態に依存しない:デフォルトの確認待ち操作の有効期間は 15 分 בלבדで、再起動やマルチプロセスの切り替えによって失われる場合があります。
  6. 機密データを保護する:.env、実際のキー、ローカルデータベース、ログ、ユーザーがアップロードしたドキュメント、個人資料を GitHub に登録しないでください。
  7. 外部へのデータ送信を確認する:外部モデルやリモート MCP を使用する前に、リクエスト内容に外部送信すべきでないユーザー情報が含まれていないことを確認してください。
  8. ナレッジベースの更新を計画する:現在のシステムは起動時に全件登録を行いますが、完全な増分削除フローはまだ提供していません。

プロジェクトディレクトリの概要

  • app/api:HTTP API と SSE。
  • app/agents:LangGraph の実行グラフとワークフローノード。
  • app/retrieval:解析、チャンク分割、検索、融合、リランキング。
  • app/providers:モデルとベクトルサービスのアダプター。
  • app/tools:業務ツール、ツール登録、権限制御。
  • app/mcp:MCP ツール連携。
  • app/memory:会話メモリと圧縮。
  • app/guardrails:入力と回答のチェック。
  • app/observability:ログとメトリクス。
  • frontend:React と TypeScript によるチャットインターフェース。
  • knowledge:ポリシー関連のナレッジドキュメント。
  • tests と eval:自動テスト、評価データ、実行器。

まとめ

Adaptive-RAG の EC カスタマーサービスは、比較的完全なインテリジェント客服のエンジニアリングフローを示しています。まず意図の識別と複雑度の判定を行い、必要に応じてハイブリッド検索、複数ターンの証拠補足、ツール呼び出し、人による確認、忠実度検証を組み合わせます。まずは SQLite、デモ用注文データ、オフラインロジックを使ってすばやく体験し、その後、DeepSeek、Jev、ローカルベクトルモデル、Cross-Encoder、拡張ドキュメント解析、Docker サービスを段階的に有効化できます。

実際の業務に導入する前に、認証、実際の注文システムとの統合、確認状態の永続化、ナレッジベースの増分メンテナンス、キー管理、本番レベルのネットワークセキュリティを重点的に補完する必要があります。プロジェクトは MIT License を採用しています。詳しいアーキテクチャと制限については、アーキテクチャと実行フロー、検索設計、制限とロードマップを参照してください。