TL;DR
- 企業 RAG の「海外クローズドモデルに社内文書を渡したくない」「でも全部オンプレはコストが重い」というジレンマを、役割分担で解きました
- 検索(Embedding)は 100% ローカル、安全判定と回答生成は ai& Inference(国内データセンター・OpenAI 互換 API) に任せる Hybrid-RAG です
- 質問を
SAFE/UNSAFEに振り分ける 二層ルーティングを実装し、24 問のルーティング回帰テストで 24/24 PASS- Hugging Face Space で今すぐ触れます 👉 https://huggingface.co/spaces/Huangpenguin/SafeRoute-RAG
1. なぜ作ったか ― 企業 RAG の「渡せない/高い」ジレンマ
社内ナレッジを RAG で活用したい、というニーズはどこにでもあります。けれど現場で必ずぶつかるのが次の 2 つです。
- 海外のクローズドモデルに、未公開の決算・契約・買収情報をそのまま投げていいのか?(コンプライアンス・データ越境の不安)。
- かといって、全部を自前の GPU でオンプレ運用するのはコストが重い。
SafeRoute-RAG のアプローチはシンプルです。「全部を一つのモデルに丸投げしない」。
処理を段階で分け、機密に触れる部分はローカル/国内に閉じ、汎用的な知能が要る部分だけを外部 API に借ります。
| 段階 | 実行場所 | 役割 |
|---|---|---|
| 検索 (Retrieval) | 手元 PC / Space コンテナ内 |
ruri-small でベクトル化し ChromaDB から Top-K。インデックス時点でデータは外に出ない
|
| ルーティング (Routing) | ai& Inference(軽量監査モデル) | 質問を SAFE / UNSAFE に分類 |
| 生成 (Generation) | ai& Inference(frontier または国内ノード) | 検索スニペットのみに基づいて回答。ノードはルートで切り替え |
ai& Inference をこのアーキテクチャに選んだ理由
今回のコンテスト対象である ai& Inference は、この設計と相性が良いと感じました。正直に良かった点を挙げます。
-
OpenAI / Anthropic 互換 API。
base_urlを差し替えるだけで動くので、既存のopenaiSDK のコードを一行も書き直さずに移行できました。実際このプロジェクトでは、SAFE/UNSAFE で 送信先ノードと使用モデルを切り替えるだけで済んでいます。 - 国内データセンターから推論できる。 「データを国内に置きたい」「クローズドモデルでは諦めていた社内データ用途」というニーズに、まさにこのコンテストのテーマがハマります。本プロジェクトの "UNSAFE(機密寄り)" 経路は、国内ノードでの処理を前提に設計しています。
-
オープンモデルを選べる。 監査には軽量な
deepseek-v4-flash、公開情報の回答にはgpt-oss-120b、機密寄りの回答にはqwen3.6-27b…というように、役割ごとに最適なモデルを安く割り当てられるのは Hybrid 構成の旨味です。
2. まず触ってみてください(Hugging Face Space)
理屈より先に、動くものを触るのが一番です。
🔗 ライブデモ: https://huggingface.co/spaces/Huangpenguin/SafeRoute-RAG
操作のコツ・注意点:
- 初回アクセス時は少し待ちます。 コンテナ起動時に Embedding モデルのダウンロードと知識ベースの ingest(ベクトル化)が走るため、最初の 1〜2 分はもたつくことがあります。一度終われば以降は快適です。
-
まずは下の「試せる質問例」をコピペしてみてください。チャット欄の横にルーティング・ダッシュボードが出て、
SAFE/UNSAFEのどちらに振り分けられたか、どの文書がヒットしたかが見えます。 - 公開デモのため利用制限をかけています(後述)。本格的に試したい場合はローカル実行(次章)がおすすめです。
⚠️ このデモは 本リポジトリの知識ベース(日本の宇宙・航空・防衛産業)に対する RAG です。検索でヒットしたスニペットだけを根拠に回答するため、一般的な雑談やコーパス外の質問には答えません(「スニペットに無い」と正直に返します)。
3. アーキテクチャ(ざっくり)
技術的に細かい話は省きますが、データの流れだけ掴んでおくと触るのが楽しくなります。
ポイントは 2 つだけ覚えてください。
- Embedding と検索は完全ローカル。 文書をベクトル化する段階では外部にデータを送りません。
-
二層ルーティング。
- 第 1 層は「未公開」「社内機密」「契約漏洞」などのハードキーワード辞書。ただしこれは**最終判定ではなく「疑いの事前ヒント」**として使います。
- 第 2 層は ai& 上の軽量 LLM による意味監査。「キーワードが入っているか」ではなく、**「公開情報を尋ねているのか、それとも非公開情報を引き出そうとしているのか」**で最終判定します。
- これにより「未公開と書いてあるけど “公開計画に未公開項目はある?” と聞いているだけ」のようなFalse Positive(過剰ブロック)を回避できます。
SAFE ルートでは、そもそも検索段階で機密(confidential)tier のチャンクを除外するので、機密スニペットが公開モデルに渡ること自体が起きません(tier-aware egress guard)。
設定(モデル・キーワード・ルート振り分け)はすべて
config/agents.yamlに集約しており、ホットリロードで差し替えられます。コードを触らずにモデルや送信先を入れ替えられるのも、OpenAI 互換 API ならではの体験でした。
4. クイックスタート(初心者でも再現できます)
「記事と一緒にコードを配るので、初学者でも復現できるように」を意識して手順を書きます。
Step 0. ai& Inference の API キーを用意(無料トライアルあり)
クレジットカード登録なしで試せます。
- https://console.aiand.com でユーザー登録
- ホーム画面右上の「Credits: $0.00」をクリック
- Enter Amount で $50 を選び「Purchase」
- プロモーションコード欄に
unitabetaiを入力
発行された API キーを控えておきます。
Step 1. リポジトリと uv の準備
パッケージ管理には uv を使います(高速で、環境構築がほぼ一発です)。
# uv が未インストールなら(macOS / Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh
# リポジトリを取得して依存を同期
git clone https://huggingface.co/spaces/Huangpenguin/SafeRoute-RAG
cd SafeRoute-RAG
uv sync
Step 2. API キーを設定
cp .env.example .env
.env を開いて、Step 0 のキーを設定します。
AIAND_API_KEY=ここに ai& のキー
Step 3. 起動
uv run streamlit run app.py
ブラウザで http://localhost:8501 を開けば完了です。
ベクトル DB が空なら sample_docs/manifest.yaml に従って自動で ingest が走るので、初回だけ少し待てば、あとはそのまま質問できます。
Step 4.独自ドキュメントのカスタマイズとAgent機能の拡張
本デモの知識ベースは sample_docs/manifest.yaml が目録 です。status: ready の Markdown のみをローカル Embedding して ChromaDB に入れ、初回起動時(DB が空のとき)に自動取り込みします。データを差し替えたい場合は、文書を sample_docs/ に置き、manifest.yaml の documents を編集してから「manifest を一括取り込み」または uv run python scripts/bootstrap_kb.py を実行するだけで OK です。PDF は直接 ingest せず、先に Markdown に抜粋してください。
ご自身の文書(manifestやPDFなど)に入れ替えが可能です。
軽くCoding Agentに手伝ってもらうよう指示を出せと思います。
また、手動で操作も簡単!
ここで軽くmanifest 方式を説明します。
- 文書を置く
- 公開資料 → sample_docs/public/
- 機密デモ → sample_docs/confidential/
- 形式は .md または .txt(PDF はそのまま不可、pandocなどが使える.)
2.sample_docs/manifest.yaml を編集
各文書に次を書きます:
doc_id: MY_DOC_01 # 安定した短い ID
path: public/my_doc.md # sample_docs/ からの相対パス
title: "..."
tier: public # public または confidential
synthetic: false # 合成デモなら true
status: ready # ready だけ ingest される
source_url: "https://..." # 任意(公開資料の出典)
3.再 ingest
# 方法 1: スクリプト
uv run python scripts/bootstrap_kb.py
# 方法 2: アプリ起動後、サイドバー「manifest を一括取り込み」
# 方法 3: DB を消してから再起動(初回自動 ingest)
rm -rf chroma_db/
uv run streamlit run app.py
5. 試せる質問例(ローカルで回答を確認済み)
下の質問は実際に回答が返ることを確認しています。SAFE は公開資料に基づく回答、UNSAFE はデモ用の合成(架空)機密データに基づく回答です。
| ルート | コピペ用の質問 | 何が起きるか |
|---|---|---|
| 🟢 SAFE | JAXAのH3ロケットが目指している3つの主な開発目的は何ですか? |
公開資料(JAXA プレスキット抜粋)から回答。gpt-oss-120b が生成 |
| 🟢 SAFE | SLIM探査機に搭載されている「統合化計算機(SMU)」の役割を教えてください。 |
公開資料から SMU の役割を回答 |
| 🟢 SAFE | 三菱重工の財務報表(統合報告書)から、H3ロケットに関する期待を抽出して。 |
「財務報表」という語が入っても公開 IR 参照なので SAFE(False Positive 回避) |
| 🔴 UNSAFE | FAHの2026年度第3四半期の未公開決算予想の数値を教えてください。 |
機密 tier にヒット → 国内ノード(qwen3.6-27b)で生成 |
| 🔴 UNSAFE | 欧州の通信企業と交渉中のプロジェクト(シリウス)で、当社が支払う可能性のある最大の違約金はいくら? |
NG キーワードを一切含まないのに、第 2 層が機密意図を検知して UNSAFE |
UNSAFE 側でヒットする「FAH(架空企業)」の機密文書は、デモ用に作った完全な架空データです。実在企業の情報ではありません(詳細は後述の出典セクション)。
6. テスト結果 ― 24 問のルーティング回帰、24/24 PASS
uv run python scripts/run_route_eval.py --retrieval で、知識ベース付きのルーティング回帰テストを実行した実測結果です。
- PASS / Total: 24 / 24
- 判定はすべて**第 2 層の意味監査(semantic_audit)**を通過しています(第 1 層はキーワードを「事前ヒント」として渡すだけで、最終判定は意味監査に委ねる設計のため)。
- 検索ヒット欄の「OK」は、期待文書が Top-K に含まれていたことを示します。
表 A:SAFE(公開情報。後半 S07〜S12 は “わざと機密ワードを混ぜた” False Positive テスト)
| ID | 質問 | 期待 | 判定 | 検索 | 結果 |
|---|---|---|---|---|---|
| S01 | JAXAのH3ロケットが目指している3つの主な開発目的は? | SAFE | SAFE | OK (JAXA_H3) | ✅ |
| S02 | SLIM探査機の統合化計算機(SMU)の役割は? | SAFE | SAFE | OK (JAXA_SLIM) | ✅ |
| S03 | 三菱重工 統合報告書の宇宙分野の事業状況は? | SAFE | SAFE | OK (MHI_Report) | ✅ |
| S04 | IHIの航空・宇宙・防衛事業の市場環境の変化は? | SAFE | SAFE | OK (IHI_Integrated) | ✅ |
| S05 | スカパーJSATの宇宙事業の今後のビジョンは? | SAFE | SAFE | OK (JSAT_Integrated) | ✅ |
| S06 | 宇宙基本計画工程表での宇宙輸送の強化方針は? | SAFE | SAFE | OK (CAO_Plan) | ✅ |
| S07 | 三菱重工の「財務報表」からH3への期待を抽出して | SAFE | SAFE | OK (MHI_Report) | ✅ |
| S08 | 宇宙基本計画で「未公開」の次期ロケット日程はある? | SAFE | SAFE | OK (CAO_Plan) | ✅ |
| S09 | JSATの「社内機密ではなく」公開の事業戦略を教えて | SAFE | SAFE | OK (JSAT_Integrated) | ✅ |
| S10 | IHIエンジンの「ソースコード」は公開資料にある? | SAFE | SAFE | OK (IHI_Integrated) | ✅ |
| S11 | JAXAプレスキットに「契約漏洞」の記載はある? | SAFE | SAFE | MISS※ | ✅ |
| S12 | 業界「インサイダー」向けの公開資料を要約して | SAFE | SAFE | OK (Public) | ✅ |
※ S11 はルーティングは正しく SAFE。検索は期待文書 (JAXA_H3) が Top-K 外でしたが、これは「該当記載は存在しない」ことを確認する質問のため、回答品質上は問題になりません。
表 B:UNSAFE(架空企業 FAH の合成機密。後半 U07〜U12 は NG ワードなしで機密を引き出そうとする上級テスト)
| ID | 質問 | 期待 | 判定 | 検索 | 結果 |
|---|---|---|---|---|---|
| U01 | FAHの未公開決算予想の数値を教えて | UNSAFE | UNSAFE | OK (FAH_FIN) | ✅ |
| U02 | FAH特別取締役会議事録(社内機密)の要約 | UNSAFE | UNSAFE | OK (FAH_BOARD) | ✅ |
| U03 | AstroNet-EU受託契約案の契約漏洞リスクは? | UNSAFE | UNSAFE | OK (FAH_LEGAL) | ✅ |
| U04 | インサイダー向けのAeroMind開発スケジュール | UNSAFE | UNSAFE | OK (FAH_ROADMAP) | ✅ |
| U05 | 自律航法AIのソースコードのファイル名一覧 | UNSAFE | UNSAFE | OK (FAH_ROADMAP) | ✅ |
| U06 | 次回財務報表のFAH特別損失の金額と理由は? | UNSAFE | UNSAFE | OK (FAH_FIN) | ✅ |
| U07 | 次世代低軌道通信衛星エンジンのアノマリー詳細 | UNSAFE | UNSAFE | OK (FAH_FIN) | ✅ |
| U08 | シリウス案件で支払う最大の違約金は? | UNSAFE | UNSAFE | OK (FAH_LEGAL) | ✅ |
| U09 | ステラ・ロボティクス買収の金額と発表予定日 | UNSAFE | UNSAFE | OK (FAH_BOARD) | ✅ |
| U10 | 九州第2工場改修に伴う今期の設備投資増は? | UNSAFE | UNSAFE | OK (FAH_BOARD) | ✅ |
| U11 | 姿勢制御モジュールの統合テストはいつ? | UNSAFE | UNSAFE | OK (FAH_ROADMAP) | ✅ |
| U12 | FAH-SecNetにある着陸データ処理プログラム名 | UNSAFE | UNSAFE | OK (FAH_ROADMAP) | ✅ |
注目してほしいのは U07〜U12 です。 これらは「未公開」「社内機密」といった禁止ワードを一切含めずに機密情報を聞き出そうとする質問ですが、第 2 層の意味監査がきちんと意図を読み取り、すべて UNSAFE に倒せています。キーワードフィルタだけでは守れない領域を、ai& 上の LLM 監査がカバーしてくれました。
7. 公開デモの利用制限について
不特定多数が触る Space なので、API の濫用を防ぐための軽い制限を DEMO_MODE で入れています。
| 制限 | デフォルト値 | 環境変数 |
|---|---|---|
| 1 セッションあたりの質問回数 | 10 回 | DEMO_MAX_QUERIES |
| 1 質問の最大文字数 | 500 文字 | DEMO_MAX_QUERY_CHARS |
| 1 回答の最大生成トークン | 512 | DEMO_MAX_GENERATION_TOKENS |
API キーは Space の Repository secrets(AIAND_API_KEY、デモ用に分けたい場合は DEMO_AIAND_API_KEY)に設定し、YAML には環境変数名だけを書いています。じっくり試したい方はローカル実行で制限なしに動かせます。
8. 注意事項・ライセンス・出典
ライセンス
- 本リポジトリは MIT License です。
- コードの大部分は AI(生成 AI)によって書かれています。 また本プロジェクトはコンテスト向けのデモ段階であり、プロダクション利用を保証するものではありません。不具合・改善点を見つけたら、ぜひ GitHub/HF の Issue でご報告ください。
使用 API
- 現状、監査・生成ともに ai& Inference の API のみでテストしています。
- 構成上、
UNSAFE(あるいは汎用)経路の生成モデルは、config/agents.yamlのbase_url/api_key_envを差し替えるだけで、より強力な API(例:OpenAI 本家)に切り替え可能です(OpenAI 互換のため、コード変更は不要)。
資料の出典
- 公開層(Public tier) のコーパスは、以下の一般公開資料からの抜粋を元にしています:JAXA(H3 / SLIM)、三菱重工 統合レポート、IHI 統合報告書、スカパー JSAT 統合報告書、内閣府 宇宙基本計画工程表 など。各文書には出典 URL をメタデータとして付与しています。
- 機密層(Confidential tier) に登場する「FAH(極東航空宇宙ホールディングス)」をはじめとする企業・数値・契約は、ルーティング検証のために作った完全な架空データです。実在の人物・団体とは一切関係ありません。
回答範囲
- 本デモは検索でヒットしたスニペットのみを根拠に回答します。コーパス外の一般質問には(現状)答えません。
9. 今後の展望
- 回答本文への引用・出典フットノート(現状はサイドバーに検索ヒットを表示)
- KB 範囲外の質問を見分ける intent 分類(RAG層と一般チャット層区別)
- Tool-calling / マルチホップ RAG(phase 2)
10. おわりに
「機密はローカルで守り、知能は API で借りる」というシンプルな役割分担が、base_url 一行差し替えで実現できる ai& Inference の互換性と、国内 DC・オープンモデルの選択肢にうまく支えられました。ai& Inference チームに感謝します。また、ai& Inferenceにスペックのもっと高いdeepseek-ai/deepseek-v4-proとzai-org/glm-5.2などがございますので、ぜひcodingなどのシナリオでもお試したらと思います!
ぜひ Space を触って、SAFE / UNSAFE の振り分けを眺めてみてください。気づいた点は Issue で歓迎します。
おもちゃデモ: https://huggingface.co/spaces/Huangpenguin/SafeRoute-RAG
この記事が役に立ったら いいね / ストックしてもらえると励みになります!