GeminiDesktop GeminiDesktop
ガイド

ローカル sqlite-vec RAG:50 万字のノートを 200 MB ファイルで索引化

公開日 · 著者: GeminiDesktop Team

ローカル sqlite-vec RAG:50 万字のノートを 200 MB ファイルで索引化

結論から言うと: 「Gemini にローカルのメモを検索させる」RAG を作るのに、LanceDB や Chroma、ローカル Docker は必要ありません。GeminiDesktop は sqlite-vec + gemini-embedding-001(768 次元) を採用し、50 万字の Markdown ノートを 単一 200 MB の SQLite ファイル に索引化、top-5 cosine クエリは 50ms 以下で安定します —— NotebookLM Web の 300-800ms より 1 桁速い水準です。この記事はその工学的トレードオフの記録です。

ワンライナー: デスクトップアプリの RAG にベクトル DB のフル儀式は不要。バンドルされた sqlite-vec extension + 768 次元埋め込み + 2000 字チャンク + 冷索引の並列バッチで「十分に良い」体験が得られます。鍵は GUI と MCP に同じ .db ファイルを共有させ、SQLite 自前のロックで並行を捌くこと。

なぜ sqlite-vec で、LanceDB / Chroma ではないのか

デスクトップアプリ向け RAG の制約はクラウド RAG とまったく違います:

項目 sqlite-vec LanceDB Chroma PGVector
配布形態 単一 .db ファイル + Tauri bundled extension 単一ディレクトリ(複数 lance ファイル) 独立プロセス Postgres 別立て
冷起動 < 5ms(SQLite attach) 50-200ms(mmap メタデータ) 2-5s(HTTP server 起動) 1-3s(psql handshake)
バックアップ 1 ファイルをコピー ディレクトリを tar API エクスポート pg_dump
プロセス間共有 SQLite 自前ロック 可能だが複雑 シングルプロセス ネイティブ
最大規模 ~1000 万ベクトル、10 億は厳しい 1 億+ 1 億+ 10 億+

「個人のノート規模」のデスクトップアプリには、sqlite-vec が 単一ファイル・ゼロサービス・バンドル容易 の三拍子を満たします:

  • Tauri ビルド時に sqlite-vec.dylib / .dll / .so をインストーラに同梱
  • 初回起動で ~/Library/Application Support/app.geminidesktop.desktop/local_index.db を生成
  • GUI / CLI / MCP の 3 つの入口が同じファイルを共有、ポートもバックグラウンドプロセスも不要

LanceDB もデスクトップで使えますが、複数ファイルディレクトリ構造は iCloud 同期でトラブルになりやすく、原子的バックアップが難しい。Chroma はサーバープロセスが必要で、Tauri の「すべて内蔵」思想と衝突します。

768 次元 gemini-embedding-001 vs ada-002 vs BGE-small 実測

主流の埋め込みモデル 3 つを 4.2 万字の中英混在 Markdown ノートでベンチマーク:

モデル 次元 日本語/中国語 recall@5 英語 recall@5 速度(batch=100)
text-embedding-ada-002 (OpenAI) 1536 78% 88% ~1.2s(クラウドのみ)
BGE-small-zh-v1.5 (ローカル) 512 83% 72% ~0.4s(ローカル CPU)
gemini-embedding-001 768 87% 91% ~0.8s(クラウドのみ)

結論:

  • 非英語精度:gemini-embedding-001 > BGE-small > ada-002。日本語・中国語ノートが主用途なので最重要。
  • 次元選択:768 が精度/ストレージのスイートスポット。1536 は index ファイルが倍、クエリが 60% 遅い一方で精度向上は 3% 未満。
  • ローカル vs クラウド:BGE-small はゼロネットワーク用途に価値あり、将来オプションとして追加予定。MVP は「埋め込みソースを 1 つ」で複雑度を抑える。

DB には (chunk_id, source_path, chunk_text, embedding BLOB) を保存、embedding は 768 × 4 = 3072 バイトの float32 BLOB。50 万字を 2000 字切りすると約 300 チャンク(重複込み)、本文とメタデータを合わせて最終ファイルは約 200 MB になります。

チャンク戦略:2000 字 + overlap 200、なぜ semantic chunking を使わないか

一般的なチャンク戦略は 3 つ:

  1. 固定サイズ分割(2000 文字 + 200 overlap)— GeminiDesktop 採用
  2. 再帰的文字分割(LangChain 風、段落→文→文字の階層降格)
  3. セマンティックチャンク(埋め込み類似度で「話題切れ目」を探す)

なぜ MVP は一番シンプルな固定サイズか:

  • Semantic chunking は切れ目を探すのに一度 embedding を走らせる必要がある — 1 万チャンクの冷索引が固定サイズの 2-3 倍遅い
  • 再帰分割は Markdown の H2/H3 構造には優しい が、議事録やチャットログのような階層なし文書では逆に悪化
  • 固定サイズ + 200 overlap は再帰分割より recall が約 4% 落ちるだけで、実装が単純・予測可能・並列化しやすい

次期バージョンでハイブリッド化予定:デフォルトは固定サイズ、Markdown ファイルには heading-aware 再帰分割を適用。MVP の要点は「十分に良い」体験をまず出すこと。ローカルファースト設計のトレードオフ全般は NotebookLM の代替:なぜデスクトップアプリにするのか も参照してください。

冷起動ベンチマーク:10K チャンクをゼロから索引

テスト環境:M2 MacBook Air(8 コア)、100 Mbps 回線、1 万チャンク(約 20 万字)。

戦略 総時間 ボトルネック
シングルスレッド逐次 embed 186 分 ネットワーク RTT
batch=100, 並列=4 4.8 分 Gemini API QPS
batch=200, 並列=8 3.9 分(ただし 12% 確率で 429) レート制限

デフォルトは batch=100 + concurrency=4。安定性とコーヒー 1 杯分の時間のバランス。GUI は進捗と ETA を表示、Mac がスリープしなければ 20 万字は 5 分以内で索引完了。

索引中の SQLite 書き込み戦略:

  • BEGIN TRANSACTION で batch を包み、1000 行ごとに commit
  • PRAGMA synchronous=NORMAL(デスクトップなら FULL は不要)
  • PRAGMA journal_mode=WAL で読み書きが衝突しないように —— これが後の GUI + MCP 2 プロセス共有で決定的に重要

クエリベンチマーク:top-5 cosine 50ms 以下

同じ M2 MacBook Air、20 万字を索引済み:

操作 時間 割合
Query embedding(gemini-embedding-001 クラウド) 280ms 85%
sqlite-vec top-5 cosine 18ms 6%
chunk 本文取得(SQLite) 9ms 3%
合計(初回) 307ms 100%
合計(query embedding が LRU キャッシュ命中) 27ms

NotebookLM Web と比較:1 クエリあたり 300-800ms(ノートサイズ依存)、ログイン・ネットワーク・たまにスロットリングあり。GeminiDesktop のローカル RAG は embedding 以外すべてローカル、LRU 命中時は 30ms 以下 —— 「同じキーワードを繰り返し検索」の体験が質的に変わります。

LRU キャッシュ方針:直近 200 クエリの (query_text_hash, embedding_bytes) をメモリに保持、実測ヒット率は約 35%。

2 プロセス 1 つの .db:GUI + MCP 共有

GeminiDesktop のアーキテクチャは、GUI(Tauri 本プロセス)と MCP サーバー(Rust stdio 子プロセス、Claude Code / Cursor から spawn)が同じ local_index.db に同時アクセスする可能性があります。SQLite の対処:

  1. WAL モード:マルチリーダー + シングルライター並行が非ブロッキング
  2. ファイルロック:SQLite 自前の fcntl ロック、プロセスセーフ
  3. busy_timeout=5000:短時間の競合は自動で 5 秒 retry
  4. 書き込みは GUI に集約:MCP はデフォルト読み取り(rag_query)のみ、rag_index のみ書き込みで、その際はアプリ層 mutex を取得

実運用シナリオ:

  • GUI で新規ノートを索引完了 → Claude Code がすぐ rag_query → 最新データを取得、競合ゼロ
  • Claude Code が MCP 経由で rag_index を発火 → GUI の「索引済みファイル」リストがリアルタイム更新
  • クラッシュ回復:WAL の rollback journal が片方の異常終了でもデータ破損を防ぐ

200 時間以上の読み書き混合テストで破損ゼロ、デッドロックゼロ。MCP 側の実装詳細は GeminiDesktop MCP サーバー 2026:Claude Code / Cursor から Gemini ネイティブツールを直呼び を参照。

ディレクトリ構成とバックアップ

~/Library/Application Support/app.geminidesktop.desktop/
├── config.json                # API キーと設定
├── local_index.db             # sqlite-vec メイン索引
├── local_index.db-wal         # WAL ジャーナル(実行中に存在)
├── local_index.db-shm         # 共有メモリ
└── backups/
    ├── local_index.db.2026-04-15.bak
    ├── local_index.db.2026-04-16.bak
    └── local_index.db.2026-04-17.bak

バックアップ方針:

  • 自動日次バックアップ:GUI 起動時にその日分がなければバックグラウンドで VACUUM INTO を実行(ファイルコピーより安全、未 checkpoint の WAL データも処理)
  • 7 日保持:7 日超は自動削除
  • iCloud 親和:単一 .db ファイルなので ~/Documents/GeminiDesktop/ にシンボリックリンクを張れば同期、200 MB は iCloud 無料枠で許容可能

制限と次期バージョン

現バージョンの既知の制限、次版で改善予定:

  • BM25 ハイブリッド未対応:dense 検索だけだと「製品 SKU」「電話番号」のような完全一致が弱い。次期で sqlite-vec + FTS5 ハイブリッド検索を追加。
  • 多言語 rerank なし:gemini-embedding-001 は多言語だが rerank ステップがない。Cohere Rerank 3 かローカル BGE-reranker-m3 の導入を検討中。
  • 構造化メタデータフィルタが弱い:現状は source_path LIKE '%notes/2026%' の文字列マッチのみ。次期でメタデータ列と複合インデックスを追加。
  • PDF/Word パース基本のみ.md / .txt / .pdf / .docx を扱うが、複雑な表や OCR が必要な PDF は Gemini Vision フォールバックに依存。

クイックスタート

  1. GeminiDesktop をダウンロード:https://geminidesktop.app
  2. アプリを開く → 設定 → Gemini API キーを貼り付け
  3. “RAG” タブ → 索引化するフォルダを選択(~/Documents/Notes のような小さめから)
  4. 索引完了後、Claude Code で claude mcp add geminidesktop -- /Applications/GeminiDesktop.app/Contents/MacOS/GeminiDesktop mcp
  5. Claude に「ノートから XXX を探して」と言えば rag_query を自動で呼びます

よくある質問

Q1: ローカル RAG は本当にそんなに速い?

A: はい、ただし query embedding が LRU 命中した場合。初回クエリは約 300ms(ネットワーク往復は避けられない)、繰り返しクエリは 30ms 以下。NotebookLM は毎回サーバー往復なので 300-800ms が底辺です。

Q2: 50 万字で 200 MB は大きすぎない?

A: 大きくありません。50 万字 ≈ 200 ページの本、200 MB は現代の Mac/PC では無視できる大きさです。実際の課題はバックアップサイズと iCloud 同期コストで、そのためバックアップ保持は設定可能にしています。

Q3: 埋め込みを完全ローカルにできる?

A: ロードマップにあります。将来版で BGE-small-zh を任意のローカル埋め込みプロバイダとして追加(ネットワーク 0)、日本語・中国語 recall が 87% → 83% に下がるトレードオフ。高プライバシー用途には十分価値があります。

今すぐ始める