建築設計 AI アシスタント — RAG サブシステム紹介

対象範囲:RAG サブシステムのみ(PPT 生成モジュールは含みません)
私の役割:RAG パイプライン全体の実質的なオーナー(フロー設計 + 精度改善)

一、1ページで分かる概要

項目内容
プロダクト建築設計向けの総合 AI アシスタント。対話シーンでは質問の種類に応じて自動で RAG を有効化
RAG の発火場面① 類似事例の推薦 ② 建築基準・規範 ③ その他の専門知識 — 3 種類の質問をそれぞれ対応するナレッジベースにルーティング
私の役割チームメンバー。全体フレームワークは外部委託側が担当し、RAG モジュールは私が全面的に書き直して主導
主な成果比較実験により、ベクトル検索の TOP5 ヒット率を 4% から 96% に改善。Hybrid TOP1 正答率は 60% から 100% に改善
担当範囲PDF→Markdown、LLM による構造化補助、チャンク分割戦略、登録前フィルタ、Embedding 選定、Hybrid 検索の調整、コンテキスト組み立て
現在進めていること体系的な評価基盤の整備(正解付き評価セット + 自動回帰テスト)

二、業務背景と課題

2.1 プロダクトの位置付け

建築設計者は、提案作成、報告、顧客対応の過程で大量の専門知識検索を必要とする。本システムは社内向けの「建築設計総合 AI アシスタント」で、対話画面と PPT 生成画面の 2 つの入口を持つ。

2.2 対話内での RAG の発火

対話シーンでは、システムがユーザー意図を判定し、以下の 3 種類に該当した場合に RAG を有効化する。

質問の種類ごとに対応するナレッジベースへルーティングし、分野横断のノイズを避ける。

2.3 このシーン特有の難しさ

課題影響
長大な PDF + 多数の表 / 画像表が画像として保存されていることが多く、BM25 でもベクトル検索でも表内の数値を取得できない
専門用語 + 規範番号(例:GB 50108-2008)汎用 embedding は番号の識別が弱く、意味が近い別規範を取り違えやすい
単一ドメインのコーパス後述する「ベクトル空間の異方性」の問題が特に出やすい
回答には正確さと根拠が必須設計者は条文を引用するため、「だいたい合っている」回答では不十分。ハルシネーションは許容できない

三、私の役割と責任範囲

区分範囲
Owner(主担当)RAG パイプライン全体:PDF→Markdown、LLM によるクリーニング補助、チャンク分割戦略、登録前フィルタ、Embedding モデル選定、検索ロジック、コンテキスト組み立て、評価
実装・デバッグが可能LLM モジュールの呼び出しオーケストレーション、SSE ストリーミング、検索と生成の接続部分の結合調整
概要を説明できるデプロイ運用、フロントエンド、PPT モジュール(他メンバーが担当)
プロジェクト全体のフレームワークは外部委託チームが構築し、RAG モジュールはほぼ私が書き直して継続的に改善した。

四、システム構成の全体像

flowchart TB
    User[ユーザーとの対話] --> Router{意図ルーティング}
    Router -->|事例| KB1[(事例ナレッジベース)]
    Router -->|規範| KB2[(規範ナレッジベース)]
    Router -->|その他| KB3[(専門知識ナレッジベース)]

    KB1 & KB2 & KB3 --> Retrieval[RAG 検索パイプライン]
    Retrieval --> Context[コンテキスト組み立て]
    Context --> LLM[LLM 生成]
    LLM --> Response[SSE ストリーミング回答]

    subgraph データ層
      LanceDB[(LanceDB ベクトルインデックス)]
      Meili[(Meilisearch 全文インデックス)]
      MySQL[(MySQL メタデータ)]
    end

    KB1 -.-> LanceDB
    KB1 -.-> Meili
    KB2 -.-> LanceDB
    KB2 -.-> Meili
    KB3 -.-> LanceDB
    KB3 -.-> Meili

技術スタック:FastAPI(async)+ SQLAlchemy 2.0 + MySQL + LanceDB(ベクトル)+ Meilisearch(全文)+ Redis(キャッシュ / レート制御)+ Qwen text-embedding-v4(embedding)+ Qwen-plus(生成)。


五、RAG データ処理パイプライン

5.1 パイプライン全体

flowchart LR
    A[元の PDF] --> B[PDF→Markdown 解析]
    B --> C[LLM による構造化と要約]
    C --> D[ツリー構造でのチャンク分割]
    D --> E[登録前フィルタ]
    E --> F[Embedding エンコード]
    F --> G[(LanceDB)]
    E --> H[(Meilisearch)]

    style E fill:#fff3cd,stroke:#856404
    style C fill:#fff3cd,stroke:#856404

5.2 重要なステップ

Step 1 · PDF → Markdown

建築規範の文書は長大な PDF が多く、そのままベクトル化しても精度が出にくい。まず Markdown に変換して章・節・条の階層(# / ## など)を保持し、後段の構造ベースの分割に使う。

Step 2 · LLM による構造化と要約の補助

単純な PDF→MD 変換では番号階層が崩れやすく(「3.2.1」が通常段落として扱われることがある)、LLM を使うと前後文脈から構造を復元できる。

Step 3 · ツリー構造でのチャンク分割

Markdown の見出し階層から TreeNode を構築し、実体化したパス 0001/0002/0003 で親子関係を保持する。これにより、検索時に兄弟ノードや子ノードへ拡張できる。

Step 4 · 登録前フィルタ 改善点

問題の発見:テスト中、検索結果に「3.2.1」「概要」のような見出しだけの chunk や、十数文字しかない極端に短い chunk が何度も出てきた。top_k を消費するだけで、回答には寄与しない。

診断

対応:embedding 登録前にフィルタ層を追加し、次の条件に当てはまる chunk を除外した。

効果:top_k を本当に中身のある chunk に使えるようになり、検索の質が明確に向上した。

Step 5 · 二重インデックス

同じ chunk を LanceDB(ベクトル)と Meilisearch(全文)の両方に登録し、後段の Hybrid 検索の土台にした。


六、RAG 検索パイプライン

6.1 検索フロー

flowchart TB
    Q[Query] --> V[ベクトル検索 LanceDB]
    Q --> F[全文検索 Meilisearch]
    V --> Fusion{RRF 融合}
    F --> Fusion
    Fusion --> Dedup[重複除去]
    Dedup --> Threshold[動的しきい値フィルタ]
    Threshold --> Enhance[検索結果の拡張]
    Enhance --> Limit[Token 予算で制御]
    Limit --> Assemble[ツリー型コンテキスト組み立て]
    Assemble --> Out[最終 Context]

    style Fusion fill:#d4edda,stroke:#155724
    style Enhance fill:#d4edda,stroke:#155724

6.2 重要な設計とトレードオフ

設計ポイント採用方式トレードオフ
Hybrid 検索ベクトル + 全文の RRF 融合ベクトルは意味に強く、全文検索は用語に強い(「GB 50108」は必ず拾いたい)。RRF はスコア尺度に依存せず、重み付き方式より安定
検索結果の拡張ヒット後に兄弟 / 子ノードを追加取得「3.2.1 防火等級」がヒットしたら、3.2.2、3.2.3 と親節「3.2 防火設計」も自動で付けるため、回答がより完全になる。代わりにコンテキストは長くなるが、Token Limiter で制御する
3段階の重複除去ID / 内容類似度 / 親子関係Hybrid では親ノードと子ノードが同時にコンテキストへ入りやすく、冗長になりやすい
動的しきい値現在のクエリのスコア分布に応じて適応固定しきい値はクエリごとの差が大きく、「厳しすぎて取りこぼす / 緩すぎてノイズが増える」という両立しにくい問題がある
chunk 数より token 予算を優先token 数でコンテキスト長を制御LLM の制約は token ベースであり、chunk 数だけでは正確に制御できない
ツリー型コンテキスト組み立て連結時に見出しパスを保持LLM が出典の正確性を判断しやすくなり、回答時に「『xxx規範』3.2.1」のような形で根拠を示せる

七、主要ケース — Embedding モデル選定実験

「問題の発見 → 根本原因の診断 → 比較実験 → 意思決定と実装」までを一通り示せるケース。

7.1 背景

本番初期版では doubao-embedding-large-text-250515(2048 次元)を使用していた。テストの結果、規範系クエリの cosine スコアがすべて 0.87 〜 0.92 に偏って高く、正しい chunk と無関係な chunk の差がほぼ出なかった。しきい値を上げると取りこぼし、下げるとノイズが急増する状態だった。

7.2 根本原因の診断 — ベクトル空間の異方性

flowchart LR
    A[単一ドメインのコーパス] --> B[ベクトルが同じ方向に集まる]
    B --> C[cosine 類似度が全体に高く出る]
    C --> D[正解とノイズを区別できない]

学術的には anisotropy と呼ばれる。狭いドメインのコーパスでは、embedding モデルが出力するベクトルが等方的に分布せず、特定方向に偏って集まるため、cosine 距離の識別力が落ちる。

7.3 試した対応 — All-but-the-Top 後処理

方法:ベクトルの先頭 N 個の主成分(PCA)を除去し、支配的な方向を打ち消す。

結果:絶対スコアは 0.87 から 0.30 前後まで下がり、一見まともに見えたが、Score Spread(正解 chunk のスコア − TOP1 ノイズのスコア)がほぼ 0 のままで、順位付けの意味がなかった。しきい値を下げると適合率は崩れた。

結論:AbTT は緩和策にはなるが、識別力そのものは作れない。

7.4 最終案 — Qwen text-embedding-v4 へ切り替え

1024 次元。ベクトル空間がもともと等方的で、後処理なしで使えた。

7.5 比較実験の結果

正解文書が既知の建築規範系クエリ 5 問で比較。top_k=5、threshold=0.0、RRF(0.7/0.3) を固定。

指標Doubao + AbTTQwen v4
ベクトル TOP5 ヒット数(満点 25)1 / 25 (4%)24 / 25 (96%)
Hybrid TOP1 正答率(満点 5)3 / 5 (60%)5 / 5 (100%)
Score Spread≈ 0> +0.5
後処理の要否必須不要
LLM のエンドツーエンド回答正答率N/A5 / 5

7.6 ここで整理した方法論

後続の embedding 選定向けに、次の評価手順を標準化した。


八、私の具体的な貢献

領域実施内容
データ処理PDF→Markdown パイプラインの設計、LLM による章構造化と要約生成
チャンク分割戦略ツリー構造の分割器、登録前の短い塊 / 見出しのみの塊を除外するフィルタ層(反復の中で発見して改善)
Embedding 選定比較実験の設計、Score Spread 指標の定義、異方性の診断、Doubao から Qwen v4 への切り替え
検索ロジックHybrid 検索 + RRF 融合の調整、検索結果拡張の実装、コンテキスト組み立ての再設計(ツリー構造 + 見出しパス)
検索パラメータ調整top_k、threshold、融合重みをナレッジベースごとに最適化
効果検証正解付き評価セットの設計、「検索 → コンテキスト → LLM 回答」のエンドツーエンド評価
結合調整と障害対応モジュール横断の結合調整(RAG → LLM)、バグの特定と修正

九、現状の限界と次の改善

9.1 評価基盤の不足(最優先の改善項目)

現状

計画

9.2 表と画像に関する構造的な欠陥

問題:テストで見えた痛点として、一部の重要な数値が画像の表として保存されており、BM25 でもベクトル検索でも拾えない。

計画

9.3 検索品質

9.4 エンジニアリング