アーキテクチャ概要


技術スタック

レイヤー技術備考
フロントエンドReact + TypeScriptVite 推奨
フロー図レンダリングMermaid.jssecurityLevel: 'strict' + DOMPurifyでXSS対策必須
バックエンドPython + FastAPIOpenAPI自動生成
ORMSQLAlchemy + Alembicマイグレーション管理
認証JWT (python-jose) + HttpOnly Cookieロール: admin / employee。LocalStorage保存は禁止
OrchestrationLlamaIndexRAGパイプライン司令塔
ベクトルDBChromaDB単一コレクション・メタデータフィルタ方式
BM25相当PostgreSQL 全文検索 (tsvector + GIN index)SudachiPy でトークナイズ後にDBへ格納
Rerankerhotchpotch/japanese-reranker-cross-encoder-large-v1日本語対応cross-encoder(ローカル実行)
LLMOllama (gemma3:27b 推奨)ホスト直接起動(ollama serve。Metal GPU使用。詳細は下記モデル比較表を参照
Embeddingintfloat/multilingual-e5-largeホスト直接起動(FastAPI内)。Metal MPS使用。query:/passage: prefix 必須
日本語トークナイザSudachiPyBM25・全文検索のトークン分割に使用
DBPostgreSQL 16構造化データ・バージョン管理・全文検索・監査ログ
コンテナDocker + docker-composeDBのみ(PostgreSQL・ChromaDB)。named volume必須
ファイル種別検証python-magicMIMEタイプをバイナリシグネチャで検証(拡張子偽装対策)
バックエンドテストpytest + pytest-asyncio + httpx非同期テスト対応・FastAPI TestClient
テストカバレッジpytest-covカバレッジ計測・レポート出力
テスト環境管理pytest-dotenv.env.test を自動読み込み
フロントエンドテストVitest + Testing Libraryコンポーネント単体テスト(jsdom環境)
APIモック(FE)MSW(Mock Service Worker)フロントエンドテスト時のバックエンドAPIをモック

ポート対応表

サービス開発テスト備考
PostgreSQL54325433テスト用は開発DBと衝突しないよう別ポート
ChromaDB80018002テスト用は開発環境の8001と衝突しないよう別ポート
FastAPI (uvicorn)80008000テスト時は TestClient 経由のためポート不使用
Frontend (Vite dev)3000開発時のみ(本番は Nginx で配信)
Ollama1143411434テストではモック(実サーバー不要)

LLMモデル選定(Mac Studio M4 Max 48GB 前提)

利用可能メモリの試算: 48GB − システム9GB − Embedding2.5GB − Reranker2GB − FastAPI1GB ≈ LLMに使える上限 ~33GB

モデルメモリ(Q4_K_M)日本語品質tok/s概算採否
gemma3:27b~17GB★★★★★30〜40推奨(デフォルト) Google製・128K文脈・日本語精度トップクラス
qwen2.5:32b~19GB★★★★★26〜34🔁 有力な代替候補。日本語品質はgemma3と拮抗。Alibaba製・Apache 2.0
qwen3:30b~19GB★★★★★26〜34🔁 Qwen最新版(2025)。思考モード(thinking ON/OFF)あり
gemma3:12b~8GB★★★★50〜60⚡ 速度優先フォールバック。品質は27bに劣るが十分実用的
llama3.3:70b~40GB★★★★10〜15❌ 33GBを超えるため48GB環境ではメモリ不足で搭載不可
llama3.1:8b~5GB★★★70〜90❌ 速いが日本語の複雑な質問・長文理解に弱くRAG用途では非推奨

開発途中でのモデル変更について

LLMモデルは開発中・本番稼働後でも自由に変更できる。 手順は以下のみ:

# 1. 新しいモデルをダウンロード(例: gemma3:27b → qwen2.5:32b)
ollama pull qwen2.5:32b

# 2. .env の OLLAMA_MODEL を変更
OLLAMA_MODEL=qwen2.5:32b

# 3. FastAPI を再起動するだけ(DBへの影響ゼロ)
変更対象影響範囲対応作業
LLMモデル (OLLAMA_MODEL)なしollama pull.env 変更 → 再起動のみ
Embeddingモデル (EMBEDDING_MODEL)⚠️ ChromaDB 全データ無効全ドキュメントを再Ingestion必須(ベクトル空間が変わるため)

⚠️ Embeddingモデルだけは変更コストが高い。 intfloat/multilingual-e5-large は一度決めたら変えないこと。revision をconfigで固定しているのもこの理由。


ディレクトリ構成(モノレポ)

/
├── backend/
│   ├── app/
│   │   ├── main.py              # FastAPIエントリポイント・CORS設定
│   │   ├── config.py            # pydantic-settings で環境変数読み込み・起動時バリデーション
│   │   ├── database.py          # DB接続・セッション管理
│   │   ├── models/              # SQLAlchemy ORM モデル
│   │   │   ├── user.py
│   │   │   ├── document.py      # documents + document_versions
│   │   │   ├── category.py
│   │   │   ├── chat.py          # chat_sessions + chat_messages
│   │   │   └── audit.py         # audit_logs
│   │   ├── schemas/             # Pydantic スキーマ(バリデーション)
│   │   │   ├── auth.py
│   │   │   ├── user.py
│   │   │   ├── document.py
│   │   │   └── chat.py
│   │   ├── api/                 # APIエンドポイント
│   │   │   ├── auth.py          # login / logout / refresh / me / reset-password
│   │   │   ├── documents.py     # CRUD + バージョン管理
│   │   │   ├── categories.py    # カテゴリ管理
│   │   │   ├── users.py         # ユーザー管理 (admin only)
│   │   │   ├── chat.py          # POST /chat (RAG呼び出し)
│   │   │   └── health.py        # GET /health (全コンポーネント疎通確認)
│   │   ├── core/
│   │   │   ├── security.py      # JWT発行・検証・Cookie操作
│   │   │   └── dependencies.py  # require_admin / require_employee
│   │   └── rag/
│   │       ├── chroma_client.py # ChromaDBクライアント生成(環境別に切替)
│   │       ├── ingestion.py     # ドキュメント取り込み・Embedding・tsvector更新
│   │       ├── retrieval.py     # Hybrid Search(ChromaDB + PostgreSQL全文検索)+ Reranker
│   │       └── generation.py    # Ollama呼び出し・プロンプト設計・Mermaidパーサー
│   ├── tests/                   # テストコード(開発DBを汚染しない)
│   │   ├── conftest.py          # DB・AIコンポーネントの共通フィクスチャ(モック集約)
│   │   ├── unit/                # 単体テスト(AIモデルはすべてモック)
│   │   │   ├── test_security.py
│   │   │   ├── test_ingestion.py
│   │   │   └── test_retrieval.py
│   │   └── integration/         # 統合テスト(テストDB使用・AIモデルはモック)
│   │       ├── test_auth.py
│   │       ├── test_documents.py
│   │       └── test_chat.py
│   ├── alembic/                 # DBマイグレーション
│   │   └── versions/
│   ├── alembic.ini
│   ├── pyproject.toml
│   └── requirements.txt
├── frontend/
│   ├── src/
│   │   ├── __tests__/           # テストコード
│   │   │   ├── setup.ts         # MSW(Mock Service Worker)セットアップ
│   │   │   ├── mocks/
│   │   │   │   └── handlers.ts  # APIモックハンドラー
│   │   │   ├── components/      # コンポーネント単体テスト
│   │   │   └── pages/           # ページ統合テスト
│   │   ├── components/
│   │   │   ├── common/          # 共通UI部品(Button, Modal等)
│   │   │   ├── admin/           # 管理者画面コンポーネント
│   │   │   └── chat/            # チャット画面コンポーネント
│   │   ├── pages/               # ページコンポーネント
│   │   │   ├── LoginPage.tsx
│   │   │   ├── AdminDashboardPage.tsx
│   │   │   ├── DocumentListPage.tsx
│   │   │   ├── DocumentEditPage.tsx
│   │   │   ├── CategoryPage.tsx
│   │   │   ├── UserManagePage.tsx
│   │   │   └── ChatPage.tsx
│   │   ├── hooks/               # カスタムフック
│   │   ├── services/            # API呼び出し(axios等)
│   │   ├── types/               # TypeScript型定義
│   │   ├── store/               # 状態管理(Zustand等)
│   │   ├── App.tsx
│   │   └── main.tsx
│   ├── package.json
│   ├── tsconfig.json
│   └── vite.config.ts
├── scripts/
│   ├── init-env.sh          # SECRET_KEY自動生成・.env初期化
│   ├── start-dev.sh         # 開発環境起動(DB Docker + Ollama + FastAPI + Frontend案内)
│   ├── start-test.sh        # テスト環境起動(テスト用DB Docker起動 → pytest実行)
│   └── start-prod.sh        # 本番環境起動
├── docker-compose.yml       # 開発用DB(PostgreSQL・ChromaDB)
├── docker-compose.test.yml  # テスト用DB(別ポート・tmpfs使用・使い捨て)
├── docker-compose.prod.yml  # 本番用DB設定
├── .env.example             # 全環境変数の雛形
├── .env.test                # テスト環境デフォルト値(git管理可・秘匿情報なし)
└── README.md