foundation
by nekoPhysics
README.md
# foundation
個人用の長期記憶基盤。Obsidian Vault・Claude Code のセッション履歴・会議録などを
PostgreSQL + Qdrant に取り込み、MCP (Model Context Protocol) サーバー経由で
Claude / ChatGPT 等の LLM クライアントから検索・書き込みできるようにする。
GPU を要するモデル (埋め込み・リランカ・文字起こし・OCR) は専用スケジューラに集約し、
複数サービスから排他制御された状態で共有する。
このリポジトリは個人利用向けに開発されたものの公開用コピーであり、大学 LMS 連携など
一部モジュールは公開版から除外されている。詳細は本文末尾の「注意事項」を参照。
## 目次
- [アーキテクチャ](#アーキテクチャ)
- [主要機能 (MCP ツール)](#主要機能-mcp-ツール)
- [技術スタック](#技術スタック)
- [セットアップ](#セットアップ)
- [設定](#設定)
- [ディレクトリ構成](#ディレクトリ構成)
- [注意事項](#注意事項)
## アーキテクチャ
構成要素とその役割:
```
┌─────────────────────────────────────────┐
│ Claude Code / claude.ai / ChatGPT │
└───────────────────┬───────────────────────┘
│ MCP (stdio / streamable-http)
▼
┌─────────────────────────────────────────┐
│ src/mcp_server.py (140 tools) │
│ ・OAuth 2.0 Authorization Server │
│ (src/oauth_provider.py, Google Sign-In)│
└──────┬───────────────┬──────────┬────────┘
│ │ │
▼ ▼ ▼
┌───────────┐ ┌────────────┐ ┌─────────────┐
│ PostgreSQL │ │ Qdrant │ │ gpu-scheduler│
│ (turns, │ │ (knowledge / │ │ :9400 HTTP │
│ facts, │ │ sessions │ │ FastAPI │
│ tasks...) │ │ collections)│ │ (排他キュー) │
└───────────┘ └────────────┘ └──────┬───────┘
│
┌────────────────────────┼───────────────────┐
▼ ▼ ▼
埋め込み/リランカ 音声認識/話者分離 OCR
(Ruri-v3, embedder.py / (Kotoba-Whisper, NeMo (Surya OCR)
reranker.py) TitaNet, Silero-VAD)
```
他に、以下の常駐/バッチプロセスが同じ DB / Qdrant / gpu-scheduler を共有する。
- `src/meeting_server.py` + `src/meeting_pipeline.py` (FastAPI, port 8315): 会議録音の
WebSocket ストリーミング取り込みから話者分離・構造化要約・矛盾検出までを行う。
- `src/session_watcher.py` / `src/session_ingest.py` / `src/conversation_indexer.py`:
Claude Code の JSONL セッションログを監視・解析し、ファクト抽出とベクトル化を行う。
- `src/indexer.py`: Obsidian Vault の Markdown を差分検知 → チャンク分割 → 埋め込み →
PostgreSQL/Qdrant への upsert を行う定期インデクサ。
- `src/orchestrator/`: tmux 上に Claude Code エージェントを spawn し、長期記憶を
注入した状態で走らせ、完了後に結果を回収する (`agent_*` MCP ツール群)。
- `src/dashboard_server.py` (port 8600): PostgreSQL を読み取り専用で参照する管理コンソール。
- `src/morning_digest/`: Slack/Discord/Teams 等のメッセージを DSL ルールに基づき
スコアリングし、朝刊として Discord に配信するバッチジョブ。
- `src/deep_research.py`: MCP ツール呼び出しをトリガーに Web 検索・要約を行い、
結果を Vault に保存する自律調査エンジン。
- `src/defrag.py`: 週次メンテナンス (vacuum, orphan cleanup, embedding integrity check)。
- `frontend-meeting/` (React + Vite): meeting-app 用フロントエンド。
## 主要機能 (MCP ツール)
`src/mcp_server.py` に `@mcp.tool()` で登録されている MCP ツールは 140 個 (実カウント)。
`src/mcp_categories.py` により、ツール名のプレフィックスで以下のカテゴリに分割され、
ChatGPT 等のツール数上限に合わせて複数のコネクタ (`/ops/mcp`, `/sheets/mcp`, ...) として
公開することもできる (`FOUNDATION_MCP_SPLIT=1`)。フル機能の単一エンドポイント (`/mcp`) は
Claude Code / claude.ai 向けに常時提供される。
| カテゴリ | 主なツール名プレフィックス | 内容 |
| --- | --- | --- |
| ops | `vault_*`, `reindex`, `tmux_list`, `agent_*` | Vault メンテナンス、tmux エージェント spawn/監視 |
| sheets | `sheets_*` | Google Sheets 読み書き |
| memory | `recall`, `forget_*`, `commit_memory`, `memory_*`, `rag_fullload`, `deep_research`, `citations_format`, `ingest_session`, `mf_*` | 長期記憶の検索・書込・訂正、Web 調査、MoneyForward 連携 |
| comms | `teams_*`, `discord_send` | Microsoft Teams 参照、Discord 通知 |
| tasks | `gtasks_*`, `tasks_sync`, `web_*`, `local_*`, `attachment_*`, `flight_search`, `taildrop_*`, `gpu_status`, `kakeibo_*` | Google Tasks、ローカル LLM 呼出、添付ファイル授受、航空券検索、家計簿 |
| search | `hybrid_search`, `semantic_search`, `keyword_search`, `get_note`, `get_related`, `get_session`, `read_file`, `search_facts`, `search_turns`, `list_sessions`, `list_tags`, `reminders_*`, `meeting_*`, `pdf_*` | Vault/セッションのハイブリッド検索、リマインダー、会議文字起こし、PDF OCR |
| smarthome | `smarthome_*` | HomeKit ブリッジ経由のスマートホーム操作 |
## 技術スタック
- 言語: Python 3.13 (バックエンド), TypeScript / React 19 + Vite (フロントエンド)
- MCP サーバー: `mcp` SDK (streamable-http / stdio 両対応)、独自 OAuth 2.0 Authorization Server
- Web フレームワーク: FastAPI + uvicorn (meeting-server / gpu-scheduler)
- データベース: PostgreSQL 17 (会話・ファクト・タスク等の構造化データ)
- ベクトル検索: Qdrant (knowledge / sessions コレクション、ハイブリッド検索 + RRF)
- 埋め込み/リランカ: `cl-nagoya/ruri-v3-310m` (sentence-transformers)
- 音声認識: Kotoba-Whisper (whisper.cpp 経由)、NeMo (TitaNet 話者ID / MSDD)、Silero-VAD
- OCR: Surya OCR (surya-ocr)
- LLM 呼び出し: ローカル (Ollama / llama-server, Qwen3.6 系) + 外部 OpenAI 互換
エンドポイント経由の外部モデル (任意設定)
- コンテナ: Docker Compose (postgres, qdrant, gpu-scheduler, meeting-app, caddy)
- リバースプロキシ: Caddy 2 (HTTPS, Tailscale tailnet 経由での公開を想定)
## セットアップ
### 前提
- Docker / Docker Compose v2
- NVIDIA GPU + nvidia-container-toolkit (gpu-scheduler を Docker で動かす場合)
- ホスト側で Ollama (`0.0.0.0:11434`) が起動していること
- 外部 OpenAI 互換エンドポイント (既定 `0.0.0.0:8317`、`OPENAI_COMPAT_URL` で変更可) を
使う機能を有効にする場合は、そのエンドポイントが起動していること (ローカル LLM
のみで運用する場合は不要)
- Python 3.13、Node.js 22 (ホストで直接実行する場合)
### 1. リポジトリ取得と依存インストール (ホストで直接実行する場合)
```bash
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
GPU / meeting-app の各サービスを個別に Docker ビルドする場合は
`docker/requirements-gpu.txt` / `docker/requirements-meeting.txt`
がそれぞれのイメージでインストールされる (トップレベル `requirements.txt` はホストでの
直接実行・開発用の統合版)。
### 2. PostgreSQL / Qdrant
Docker Compose 経由で起動する場合は次の手順のみで済む (`docker/init-db.sql` が
初回起動時にスキーマを自動作成する)。ホストに直接インストールする場合は
PostgreSQL 17 系と Qdrant を用意し、`config.yaml` の `database` セクションと
`config/qdrant.yaml` に合わせて設定する。
### 3. 環境変数ファイル
`docker/.env` (gitignore 対象、リポジトリには含まれない) を作成し、最低限
`POSTGRES_PASSWORD` と `DATABASE_URL` を設定する。
```bash
cat > docker/.env <<'EOF'
POSTGRES_DB=foundation
POSTGRES_USER=user
POSTGRES_PASSWORD=change-me
DATABASE_URL=postgresql://user:change-me@postgres:5432/foundation
VAULT_OUTPUT_HOST_DIR=/path/to/your/obsidian/vault
MODEL_CACHE_HOST_DIR=/path/to/huggingface/cache
EOF
```
### 4. docker-compose での起動
```bash
# 全サービスをコンテナで起動 (GPU コンテナは nvidia-container-toolkit が必要)
docker compose --env-file docker/.env up -d
# PostgreSQL/Qdrant/gpu-scheduler をホスト側 systemd 等で既に動かしている場合は
# docker-compose.override.yml で該当コンテナを無効化できる
docker compose --env-file docker/.env -f docker-compose.yml -f docker-compose.override.yml up -d
```
HTTPS 終端が必要な場合は `docker/Caddyfile.example` を `docker/Caddyfile` にコピーし、
basic_auth のハッシュ等プレースホルダを実値に置き換える (`docker/Caddyfile` は
gitignore 対象)。
### 5. Claude Code への MCP サーバー登録 (stdio)
```bash
python src/mcp_server.py # stdio モード
python src/mcp_server.py http # streamable-http + OAuth モード (claude.ai 等向け)
```
Claude Code の `mcp` 設定に、上記コマンドを stdio サーバーとして登録する。
## 設定
### config.yaml
トップレベルの `config.yaml` は個人パス (`~/Documents/obsidian/vault` 等) や
ユーザー名を汎用プレースホルダに置き換えたダミー値のみで構成されており、そのまま
利用開始できる。主な項目:
- `vault`: Obsidian Vault のルートパスと索引除外パターン
- `database`: PostgreSQL / Qdrant の接続先とコレクション定義
- `embedding` / `search.rerank`: 埋め込み・リランカモデルとハイブリッド検索のパラメータ
- `gpu_scheduler`: GPU メモリ管理の advisory 値
- `llm`: 用途別 (realtime / batch / meeting.*) の LLM モデル割当と生成パラメータ
- `whisper`: 音声認識モデルと言語設定
- `maintenance`: 週次メンテナンスのスケジュール
実運用のパス (Vault の実際の場所、モデルキャッシュの場所等) は環境変数
(`VAULT_OUTPUT_HOST_DIR` 等、docker-compose.yml 参照) または `config.yaml` 本体を
自分の環境に合わせて編集して指定する。
### 主な環境変数
| 変数 | 用途 | 既定値/備考 |
| --- | --- | --- |
| `DATABASE_URL` | PostgreSQL 接続文字列 (Docker サービス間) | 必須 (docker-compose) |
| `POSTGRES_PASSWORD` | PostgreSQL パスワード | 必須 (docker-compose) |
| `QDRANT_HOST` / `QDRANT_PORT` | Qdrant 接続先 | `localhost` / `6333` |
| `OLLAMA_URL` | ローカル LLM (Ollama) エンドポイント | `http://localhost:11434` |
| `LLAMA_SERVER_BATCH_URL` | バッチ用 llama-server エンドポイント | `http://localhost:11435` |
| `OPENAI_COMPAT_URL` | 外部 LLM 用 OpenAI 互換エンドポイント | `http://localhost:8317` |
| `GPU_SCHEDULER_URL` | gpu-scheduler の HTTP エンドポイント | `http://gpu-scheduler:9400` |
| `GPU_SCHEDULER_OWNS_EMBEDDER` | 埋め込みモデルの直接ロードを gpu-scheduler だけに限定するガード | gpu-scheduler コンテナのみ `1` |
| `VAULT_OUTPUT_DIR` | コンテナ内での Vault 出力先マウントポイント | `/output` |
| `HF_TOKEN` | HuggingFace の認証トークン (ゲート付きモデル利用時) | 任意 |
| `LOG_LEVEL` | ログレベル | `INFO` |
| `FOUNDATION_ALLOWED_EMAILS` | OAuth (streamable-http モード) の許可メールアドレス一覧 | 必須 (http モード時) |
これ以外にも `WHISPER_*` / `RRF_*` / `MEETING_V2_*` / `RERANK_*` 等、機能ごとの
チューニング用環境変数が多数存在する。既定値は各モジュールのソース (`os.getenv` 呼び出し
箇所) を参照。
## ディレクトリ構成
```
.
├── bin/ 運用スクリプト (Discord webhook 登録、通知用ラッパー等)
├── config/ Qdrant 設定 (config/qdrant.yaml)
├── config.yaml アプリケーション設定 (DB接続・モデル・スケジューラ等)
├── docker/ Dockerfile 2 種、サービス別 requirements、Caddyfile 例、init-db.sql
├── docs/ 設計・レビュー・テスト計画ドキュメント
├── frontend-meeting/ meeting-app 用フロントエンド (React + Vite)
├── src/ Python バックエンド一式
│ ├── mcp_server.py MCP サーバー本体 (140 tools)
│ ├── meeting_server.py 会議録音処理サーバー
│ ├── meeting_pipeline.py 会議処理パイプライン (v2〜v5)
│ ├── gpu_scheduler_server.py GPU タスクの排他スケジューラ
│ ├── indexer.py Vault インデクサ
│ ├── orchestrator/ tmux エージェント spawn/管理
│ ├── morning_digest/ 朝刊集約バッチ
│ └── ...
├── tests/ pytest テスト一式 (レイヤ別統合テスト、PII マスキングテスト等)
├── docker-compose.yml 本番構成 (全サービスをコンテナで起動)
├── docker-compose.override.yml ホスト常駐サービスを使う場合の上書き構成
├── requirements.txt 統合 Python 依存 (本リポジトリ整備で新規作成)
└── pytest.ini
```
## 注意事項
- 本リポジトリは個人 (1 ユーザー) の長期記憶基盤として開発されたものであり、
マルチテナント運用や不特定多数の同時利用は想定していない。OAuth の承認も
単一のメールアドレス allow-list (`FOUNDATION_ALLOWED_EMAILS`) を前提とした設計。
- 公開版では大学 LMS (TLMS) 連携モジュール等、個人・所属先に紐づく一部モジュールを
除外している。`config.yaml` や各モジュールのコメントに元機能への言及が残っている
箇所があるが、対応する実装ファイルは本リポジトリに含まれない。
- 公開版では iPhone PWA バックエンドと専用フロントエンドを除外している。
meeting-app 等の他機能が使う外部 LLM 呼び出しは、任意の外部 OpenAI 互換エンドポイント
(`OPENAI_COMPAT_URL`) を指す汎用 HTTP クライアントに一般化済み。
- 実運用には GPU (音声認識/OCR/埋め込み用)、Tailscale 等の tailnet、ローカル LLM
サーバー (Ollama / llama-server) など、このリポジトリ単体では完結しない周辺環境が
必要になる。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing