À propos du projet

# QMD - Query Markup Documents QMD est un moteur de recherche sur appareil conçu pour les bases de connaissances personnelles, la documentation, les notes de réunion et tout contenu basé sur Markdown. Il fonctionne entièrement en local, combinant recherche plein texte BM25, recherche sémantique vectorielle et reclassement par LLM pour fournir des résultats de haute qualité sans envoyer de données à des services externes. ## Fonctionnalités principales - **Pipeline de recherche hybride** : Combine BM25 (FTS5), recherche par similarité vectorielle et reclassement par LLM. L'expansion de requête génère des sous-requêtes typées (`lex` pour les mots-clés, `vec` pour les vecteurs denses, `hyde` pour les plongements de documents hypothétiques) qui sont routées vers les backends appropriés, fusionnées via Reciprocal Rank Fusion (RRF), puis reclassées par un LLM. - **Arbre de contexte** : Ajoute un contexte hiérarchique aux collections (par ex., `qmd://notes` → « Notes et idées personnelles ») renvoyé avec les documents correspondants, ce qui aide les LLM à prendre de meilleures décisions contextuelles. - **Modèles locaux** : Utilise des modèles GGUF téléchargés depuis HuggingFace et mis en cache localement. Le modèle d'embedding par défaut est `embeddinggemma-300M-Q8_0` (~300 Mo). Des modèles personnalisés peuvent être définis via la variable d'environnement `QMD_EMBED_MODEL` (par ex., pour des corpus multilingues). - **Découpage sensible à l'AST** : Un découpage optionnel basé sur tree-sitter pour les fichiers de code (TypeScript, JavaScript, Python, Go, Rust) produit des segments de meilleure qualité ; les autres types de fichiers utilisent un découpage basé sur des expressions régulières. - **Serveur MCP** : Expose un serveur Model Context Protocol avec des outils pour interroger, récupérer des documents, faire des récupérations par lot et vérifier l'état. Prend en charge les transports stdio et HTTP avec des fonctions de sécurité (validation de l'origine/de l'hôte pour prévenir les attaques de rebinding DNS). - **SDK** : Accès programmatique via un SDK TypeScript/JavaScript avec des méthodes pour la recherche, la récupération de documents, la gestion du contexte et l'expansion de requête. ## Démarrage rapide ```sh # Installation globale (Node ou Bun) npm install -g @tobilu/qmd # ou bun install -g @tobilu/qmd # Créer des collections qmd collection add ~/notes --name notes qmd collection add ~/Documents/meetings --name meetings # Ajouter du contexte qmd context add qmd://notes "Personal notes and ideas" # Générer les embeddings qmd embed # Rechercher qmd search "project timeline" # Recherche par mots-clés rapide qmd vsearch "how to deploy" # Recherche sémantique qmd query "quarterly planning process" # Hybride + reclassement (meilleure qualité) ``` ## Commandes CLI - `qmd collection add <path> --name <name> [--mask <glob>]` — Ajouter une collection - `qmd collection show <name>` — Afficher les détails d'une collection - `qmd collection include/exclude <name>` — Activer/désactiver l'inclusion d'une collection - `qmd collection update-cmd <name> '<command>'` — Définir la commande de mise à jour - `qmd embed [--chunk-strategy auto]` — Générer les embeddings vectoriels - `qmd search <query> [-c <collection>] [--json] [--files] [--min-score <n>]` — Recherche par mots-clés - `qmd vsearch <query>` — Recherche sémantique - `qmd query <query>` — Recherche hybride avec reclassement - `qmd get <path|docid>` — Récupérer un document - `qmd multi-get <glob>` — Récupérer plusieurs documents - `qmd mcp [--http] [--port <n>] [--host <addr>] [--daemon]` — Démarrer le serveur MCP - `qmd status` — Afficher la santé de l'index et l'état du MCP ## Serveur MCP Outils exposés : - `query` — Recherche avec sous-requêtes typées, fusion RRF et reclassement optionnel - `get` — Récupère un document par chemin, docid ou plage de lignes - `multi_get` — Récupération par lot via glob, liste séparée par des virgules ou docids - `status` — Santé de l'index et informations sur les collections Le transport HTTP (port par défaut 8181) fournit : - `POST /mcp` — MCP Streamable HTTP - `POST /query` (alias `/search`) — Recherche structurée sans protocole MCP - `GET /health` — Vérification de disponibilité Sécurité : Les requêtes avec des en-têtes `Origin` non-bouclage sont rejetées (403). La validation du champ `Host` empêche le rebinding DNS. Les variables d'environnement `QMD_ALLOWED_ORIGINS` et `QMD_ALLOWED_HOSTS` permettent d'étendre les origines/hôtes autorisés. ## Utilisation du SDK ```js const { QmdStore } = require('@tobilu/qmd') const store = new QmdStore({ dbPath: './qmd.db', collections: { notes: { path: '/path/to/notes' } } }) // Recherche simple (auto-expansion) const results = await store.search({ query: 'authentication flow' }) // Requête structurée avec sous-requêtes typées 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'] }) // Désactiver le reclassement pour la rapidité const fast = await store.search({ query: 'auth', rerank: false }) // Filtrage par métadonnées const published = await store.search({ query: 'typescript', filter: { key: 'topics', operator: 'all', value: ['typescript'] } }) // Accès direct au backend const bm25Results = await store.bm25Search('auth') const vectorResults = await store.vectorSearch('auth') // Expansion de requête const expanded = await store.expandQuery('auth flow', { intent: 'user login' }) // Récupération de document const doc = await store.get('docs/readme.md') const body = await store.getDocumentBody('docs/readme.md', { maxLines: 100 }) // Gestion du contexte await store.addContext('docs', '/api', 'REST API reference documentation') await store.removeContext('docs', '/api') ``` ## Détails du pipeline de recherche 1. **Expansion de requête** : Requête originale (pondérée ×2) + 1 variante LLM 2. **Récupération parallèle** : Chaque requête interroge les index FTS et vectoriels 3. **Bonus de premier rang** : Les documents classés n°1 dans une liste reçoivent +0,05, les n°2-3 reçoivent +0,02 4. **Sélection Top-K** : Prendre les 30 premiers candidats pour le reclassement 5. **Reclassement** : Le LLM score chaque document (oui/non avec confiance logprobs) Plages de scores : 0,0–0,2 pertinence faible, des valeurs plus élevées indiquent de meilleures correspondances. ## Configuration du modèle Modèles par défaut : - Embedding : `embeddinggemma-300M-Q8_0` (~300 Mo) - Reclassement : basé sur LLM (téléchargé à la demande) Exemple de modèle d'embedding personnalisé : ```sh export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf" ``` Remarque : Changer de modèle d'embedding nécessite de ré-embedder toutes les collections car les vecteurs ne sont pas compatibles entre eux. ## Prérequis - Environnement d'exécution Node.js ou Bun - Stockage local suffisant pour les modèles et les embeddings - Optionnel : GPU/VRAM pour une inférence LLM plus rapide (les modèles restent chargés en VRAM entre les requêtes) ## Licence Logiciel open-source. Voir le dépôt pour plus de détails.