このプロジェクトについて

# QMD - Query Markup Documents QMDは、個人のナレッジベース、ドキュメント、会議メモ、その他Markdownベースのコンテンツ向けに設計されたオンデバイス検索エンジンです。完全にローカルで動作し、BM25全文検索、ベクトル意味検索、LLMベースのリランキングを組み合わせて、データを外部サービスに送信せずに高品質な結果を提供します。 ## 主な機能 - **ハイブリッド検索パイプライン**: BM25 (FTS5)、ベクトル類似度検索、LLMリランキングを組み合わせます。クエリ展開は、適切なバックエンドにルーティングされる型付きサブクエリ(キーワード用の`lex`、密ベクトル用の`vec`、仮想的なドキュメント埋め込み用の`hyde`)を生成し、Reciprocal Rank Fusion (RRF) で融合し、LLMでリランキングします。 - **コンテキストツリー**: コレクションに階層的なコンテキストを追加できます(例: `qmd://notes` → 「個人メモとアイデア」)。これは一致するドキュメントと一緒に返され、LLMがより適切なコンテキスト判断を行うのに役立ちます。 - **ローカルモデル**: HuggingFaceからダウンロードされたGGUFモデルを使用し、ローカルにキャッシュします。デフォルトの埋め込みモデルは`embeddinggemma-300M-Q8_0`(約300MB)です。カスタムモデルは`QMD_EMBED_MODEL`環境変数で設定できます(多言語コーパス用など)。 - **AST対応チャンキング**: コードファイル(TypeScript、JavaScript、Python、Go、Rust)向けのオプションのtree-sitterベースのチャンキングにより、高品質なチャンクを生成します。他のファイルタイプでは正規表現ベースのチャンキングを使用します。 - **MCPサーバー**: クエリ、ドキュメント取得、バッチ取得、ステータスチェックのためのツールを備えたModel Context Protocolサーバーを公開します。stdioおよびHTTPトランスポートをサポートし、セキュリティ機能(DNSリバインディング攻撃を防ぐオリジン/ホスト検証)を備えています。 - **SDK**: 検索、ドキュメント取得、コンテキスト管理、クエリ展開のためのメソッドを持つTypeScript/JavaScript SDKを介したプログラムによるアクセスを提供します。 ## クイックスタート ```sh # Install globally (Node or Bun) npm install -g @tobilu/qmd # or bun install -g @tobilu/qmd # Create collections qmd collection add ~/notes --name notes qmd collection add ~/Documents/meetings --name meetings # Add context qmd context add qmd://notes "Personal notes and ideas" # Generate embeddings qmd embed # Search qmd search "project timeline" # Fast keyword search qmd vsearch "how to deploy" # Semantic search qmd query "quarterly planning process" # Hybrid + reranking (best quality) ``` ## CLIコマンド - `qmd collection add <path> --name <name> [--mask <glob>]` — コレクションを追加します - `qmd collection show <name>` — コレクションの詳細を表示します - `qmd collection include/exclude <name>` — コレクションの包含/除外を切り替えます - `qmd collection update-cmd <name> '<command>'` — 更新コマンドを設定します - `qmd embed [--chunk-strategy auto]` — ベクトル埋め込みを生成します - `qmd search <query> [-c <collection>] [--json] [--files] [--min-score <n>]` — キーワード検索 - `qmd vsearch <query>` — 意味検索 - `qmd query <query>` — リランキング付きハイブリッド検索 - `qmd get <path|docid>` — ドキュメントを取得します - `qmd multi-get <glob>` — 複数のドキュメントを取得します - `qmd mcp [--http] [--port <n>] [--host <addr>] [--daemon]` — MCPサーバーを起動します - `qmd status` — インデックスの健全性とMCPステータスを表示します ## MCPサーバー 公開ツール: - `query` — 型付きサブクエリ、RRF融合、オプションのリランキングによる検索 - `get` — パス、docid、または行範囲でドキュメントを取得 - `multi_get` — グロブ、カンマ区切りリスト、またはdocidによる一括取得 - `status` — インデックスの健全性とコレクション情報 HTTPトランスポート(デフォルトポート8181)が提供するもの: - `POST /mcp` — MCP Streamable HTTP - `POST /query`(エイリアス `/search`) — MCPプロトコルを使わない構造化検索 - `GET /health` — 生存確認 セキュリティ: ループバック以外の`Origin`ヘッダーを持つリクエストは拒否されます(403)。`Host`検証によりDNSリバインディングを防ぎます。環境変数`QMD_ALLOWED_ORIGINS`と`QMD_ALLOWED_HOSTS`で許可されるオリジン/ホストを拡張できます。 ## SDKの使用法 ```js const { QmdStore } = require('@tobilu/qmd') const store = new QmdStore({ dbPath: './qmd.db', collections: { notes: { path: '/path/to/notes' } } }) // Simple search (auto-expanded) const results = await store.search({ query: 'authentication flow' }) // Structured query with typed sub-queries const results2 = await store.search({ queries: [ { type: 'vec', query: 'why do database connections time out under load' }, { type: 'lex', query: 'connection timeout' } ], collections: ['docs', 'notes'] }) // Disable reranking for speed const fast = await store.search({ query: 'auth', rerank: false }) // Metadata filtering const published = await store.search({ query: 'typescript', filter: { key: 'topics', operator: 'all', value: ['typescript'] } }) // Direct backend access const bm25Results = await store.bm25Search('auth') const vectorResults = await store.vectorSearch('auth') // Query expansion const expanded = await store.expandQuery('auth flow', { intent: 'user login' }) // Document retrieval const doc = await store.get('docs/readme.md') const body = await store.getDocumentBody('docs/readme.md', { maxLines: 100 }) // Context management await store.addContext('docs', '/api', 'REST API reference documentation') await store.removeContext('docs', '/api') ``` ## 検索パイプラインの詳細 1. **クエリ展開**: 元のクエリ(重み付け×2)+ LLMバリエーション1つ 2. **並列取得**: 各クエリがFTSとベクトルインデックスの両方を検索 3. **上位ランクボーナス**: いずれかのリストで1位のドキュメントには+0.05、2〜3位には+0.02 4. **Top-K選択**: リランキング用に上位30件の候補を選択 5. **再ランキング**: LLMが各ドキュメントをスコアリング(logprobs信頼度によるyes/no) スコア範囲: 0.0〜0.2は関連性が低く、値が高いほど良い一致を示します。 ## モデル設定 デフォルトモデル: - 埋め込み: `embeddinggemma-300M-Q8_0`(約300MB) - リランキング: LLMベース(必要に応じてダウンロード) カスタム埋め込みモデルの例: ```sh export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf" ``` 注: 埋め込みモデルを変更する場合、ベクトルは相互互換性がないため、すべてのコレクションを再埋め込みする必要があります。 ## 要件 - Node.jsまたはBunランタイム - モデルと埋め込み用の十分なローカルストレージ - オプション: より高速なLLM推論のためのGPU/VRAM(モデルはリクエスト間でVRAMにロードされたままになります) ## ライセンス オープンソースソフトウェアです。詳細はリポジトリを参照してください。