技術ノート・セキュリティ
検証方法(E2E)
GET /healthで全コンポーネント(DB・ChromaDB・Ollama)がokを返すことを確認- Ollama が起動し日本語で回答できることを確認
- PDF(就業規則サンプル)をアップロード → Ingestion ステータスが
completedになる content_tsvカラムにトークンが格納されていることを確認- 社員チャット画面から「育児休暇の手続きは?」と質問
- テキスト回答 + Mermaid フロー図(手順フロー)がブラウザに表示される
- Mermaid.js の
securityLevel: 'strict'が有効で、XSSペイロードが無害化されることを確認 - 管理者が規約を更新 → バージョン履歴に旧版が残る → 復元操作が可能
- audit_logs に各操作が記録されていることを確認
must_change_password=trueのユーザーで初回ログイン → パスワード変更画面に強制リダイレクト
技術的検討・注意点
MacのDockerコンテナ内GPUについて(重要)
Mac上のDockerはLinux VMを経由するため、Metal GPU・Neural EngineにはDockerコンテナからアクセスできない。 この制約により、AIコンポーネントをDockerコンテナ内で動かすと以下のパフォーマンス劣化が生じる:
結論: Ollama・FastAPI(Embedding/Reranker含む)はホスト直接起動が必須。 Mac Studio M4 Max はメモリ帯域 546 GB/s により、LLM推論・Embedding ともに M4 Pro(273 GB/s)の約2倍の速度を発揮する。
MPS(Metal Performance Shaders)利用時の注意
- PyTorchのMPS対応は進んでいるが、一部演算は未対応
PYTORCH_ENABLE_MPS_FALLBACK=1を設定することで、未対応演算を自動的にCPUで補完する- この設定がないとMPS非対応演算でエラーが発生する可能性がある
DockerボリュームのI/O性能
- bind mount(
./path:/container/path)はVirtioFS経由で3〜30倍遅化する → 絶対に使用しない - named volumeを必ず使用する(
postgres_data、chromadb_data) - PostgreSQL・ChromaDBのデータはNASに置かない(NFS越しのI/Oがボトルネックになる)
- NASはPDF等の元ファイルのみ格納する
macOSサーバーとしての運用設定
- スリープ無効化必須(社内サーバーとして常時稼働させるため)
- NASのマウント方式はNFSを推奨(SMBは長時間接続で不安定になる場合がある)
- Mac Studioを社内LAN固定IPに設定する
開発・テスト環境の分離
テスト実行時に開発DBを汚染しないよう、環境を完全に分離する。
ChromaDBクライアントの環境別切替(rag/chroma_client.py):
採用方針: Docker + HttpClient(本番に近い構成でテスト) テスト環境でも
docker-compose.test.ymlのchromadb-test(ポート8002)を起動し、 本番と同じHttpClient経由で接続する。.env.testのCHROMA_PORT=8002で切り替え。
テストフィクスチャの構成(tests/conftest.py):
pyproject.toml のpytest設定:
vite.config.ts のtest設定:
MSW セットアップ(frontend/src/__tests__/setup.ts):
セキュリティ設計
ローカル動作の担保
multilingual-e5-largeは初回起動時にHugging Faceからダウンロード、以後はローカルキャッシュを使用(HF_HOME=~/.cache/huggingface)- モデルのrevisionをconfigで固定し、更新によるベクトル空間のズレを防ぐ
- Ollama モデルは
ollama pull gemma3:27bで事前ダウンロード - ChromaDB はサーバーモードでDockerのnamed volumeに永続化
日本語対応(重要度:最高)
multilingual-e5-largeはquery:/passage:prefix の付与が 必須(なしでは精度が大幅低下)- BM25相当はPostgreSQL全文検索(tsvector + GIN)+ SudachiPy で実現(ChromaDBのBM25非対応を回避)
- Rerankerは日本語対応モデル (
hotchpotch/japanese-reranker-cross-encoder-large-v1) を使用 - チャンクサイズ512tokenは日本語で約300〜400文字相当に注意
セキュリティ
- パスワードは bcrypt でハッシュ化
- JWT は HttpOnly Cookie で管理(LocalStorage禁止・XSSによるトークン窃取防止)
- Mermaid.js は
securityLevel: 'strict'+ DOMPurify でXSSリスクを軽減 - バックエンドでMermaid構文の許可リスト検証を実施
- ファイルアップロードは python-magic でバイナリシグネチャ検証(拡張子偽装対策)
- レート制限(slowapi)で
POST /chatのDoS対策 - プロンプトインジェクション対策:入力500文字上限・区切り文字の強化・ロギング
- SECRET_KEY は起動時に強度チェック(空・32文字未満・デフォルト値で起動拒否)
スケーラビリティ・運用性
- v1.0はシングルテナント(企業ごとに独立インスタンス)
- ChromaDB は単一コレクション + メタデータフィルタ方式(カテゴリ別複数コレクション方式は管理コスト大のため不採用)
- Embeddingモデルのバージョンを固定してChromaDBとの整合性を保つ
- Ingestion非同期処理はPhase 1〜6ではFastAPI BackgroundTasks、本番スケール時はCelery + Redisへの移行を検討
- PostgreSQL と ChromaDB のバックアップは同一タイムスタンプで取得(両DBの整合性確保)
- 監査ログ(audit_logs)で法務・コンプライアンス要件に対応
- 将来のロードマップ:マルチテナント対応・カテゴリ単位アクセス制御・管理者承認型FAQ機能(v1.1〜)・セマンティックキャッシュ(v1.5〜)
Ingestion整合性
- ChromaDB削除失敗時はDBロールバックし、整合性を優先
- Ingestion中のチャットは旧インデックスで回答(可用性優先)
- 管理画面からIngestion再実行ボタンで手動リトライ可能
- バージョン復元時は旧チャンク削除 → 新チャンク登録をセットで実行