Sobre el proyecto

# QMD - Query Markup Documents QMD es un motor de búsqueda en el dispositivo diseñado para bases de conocimiento personales, documentación, notas de reuniones y cualquier contenido basado en Markdown. Se ejecuta completamente en local, combinando búsqueda de texto completo BM25, búsqueda semántica vectorial y reordenamiento basado en LLM para ofrecer resultados de alta calidad sin enviar datos a servicios externos. ## Características principales - **Pipeline de búsqueda híbrida**: Combina BM25 (FTS5), búsqueda por similitud vectorial y reordenamiento con LLM. La expansión de consultas genera subconsultas tipadas (`lex` para palabras clave, `vec` para vectores densos, `hyde` para embeddings de documentos hipotéticos) que se enrutan a los backends apropiados, se fusionan mediante Reciprocal Rank Fusion (RRF) y son reordenadas por un LLM. - **Árbol de contexto**: Añade contexto jerárquico a las colecciones (por ejemplo, `qmd://notes` → "Notas e ideas personales") que se devuelve junto con los documentos coincidentes, ayudando a los LLM a tomar mejores decisiones contextuales. - **Modelos locales**: Utiliza modelos GGUF descargados de HuggingFace y almacenados en caché localmente. El modelo de embeddings por defecto es `embeddinggemma-300M-Q8_0` (~300MB). Se pueden configurar modelos personalizados mediante la variable de entorno `QMD_EMBED_MODEL` (por ejemplo, para corpus multilingües). - **Segmentación consciente de AST**: La segmentación opcional basada en tree-sitter para archivos de código (TypeScript, JavaScript, Python, Go, Rust) produce fragmentos de mayor calidad; otros tipos de archivo utilizan segmentación basada en expresiones regulares. - **Servidor MCP**: Expone un servidor Model Context Protocol con herramientas para consultar, recuperar documentos, recuperación por lotes y comprobación de estado. Soporta transporte stdio y HTTP con características de seguridad (validación de origen/host para prevenir ataques de rebinding DNS). - **SDK**: Acceso programático mediante un SDK de TypeScript/JavaScript con métodos para búsqueda, recuperación de documentos, gestión de contexto y expansión de consultas. ## Inicio rápido ```sh # Instalar globalmente (Node o Bun) npm install -g @tobilu/qmd # o bun install -g @tobilu/qmd # Crear colecciones qmd collection add ~/notes --name notes qmd collection add ~/Documents/meetings --name meetings # Añadir contexto qmd context add qmd://notes "Notas e ideas personales" # Generar embeddings qmd embed # Buscar qmd search "cronograma del proyecto" # Búsqueda rápida por palabras clave qmd vsearch "cómo implementar" # Búsqueda semántica qmd query "proceso de planificación trimestral" # Híbrida + reordenamiento (mejor calidad) ``` ## Comandos CLI - `qmd collection add <ruta> --name <nombre> [--mask <glob>]` — Añadir una colección - `qmd collection show <nombre>` — Mostrar detalles de la colección - `qmd collection include/exclude <nombre>` — Alternar inclusión de la colección - `qmd collection update-cmd <nombre> '<comando>'` — Establecer comando de actualización - `qmd embed [--chunk-strategy auto]` — Generar embeddings vectoriales - `qmd search <consulta> [-c <colección>] [--json] [--files] [--min-score <n>]` — Búsqueda por palabras clave - `qmd vsearch <consulta>` — Búsqueda semántica - `qmd query <consulta>` — Búsqueda híbrida con reordenamiento - `qmd get <ruta|docid>` — Recuperar un documento - `qmd multi-get <glob>` — Recuperar múltiples documentos - `qmd mcp [--http] [--port <n>] [--host <dirección>] [--daemon]` — Iniciar servidor MCP - `qmd status` — Mostrar salud del índice y estado de MCP ## Servidor MCP Herramientas expuestas: - `query` — Búsqueda con subconsultas tipadas, fusión RRF y reordenamiento opcional - `get` — Recuperar documento por ruta, docid o rango de líneas - `multi_get` — Recuperación por lotes mediante glob, lista separada por comas o docids - `status` — Salud del índice e información de colecciones El transporte HTTP (puerto por defecto 8181) proporciona: - `POST /mcp` — MCP Streamable HTTP - `POST /query` (alias `/search`) — Búsqueda estructurada sin protocolo MCP - `GET /health` — Comprobación de disponibilidad Seguridad: Las solicitudes con cabeceras `Origin` que no sean de bucle local se rechazan (403). La validación de `Host` previene el rebinding DNS. Las variables de entorno `QMD_ALLOWED_ORIGINS` y `QMD_ALLOWED_HOSTS` pueden ampliar los orígenes/hosts permitidos. ## Uso del SDK ```js const { QmdStore } = require('@tobilu/qmd') const store = new QmdStore({ dbPath: './qmd.db', collections: { notes: { path: '/ruta/a/notas' } } }) // Búsqueda simple (autoexpandida) const results = await store.search({ query: 'flujo de autenticación' }) // Consulta estructurada con subconsultas tipadas const results2 = await store.search({ queries: [ { type: 'vec', query: 'por qué las conexiones de base de datos expiran bajo carga' }, { type: 'lex', query: 'tiempo de espera de conexión' } ], collections: ['docs', 'notes'] }) // Desactivar reordenamiento para mayor velocidad const fast = await store.search({ query: 'auth', rerank: false }) // Filtrado por metadatos const published = await store.search({ query: 'typescript', filter: { key: 'topics', operator: 'all', value: ['typescript'] } }) // Acceso directo al backend const bm25Results = await store.bm25Search('auth') const vectorResults = await store.vectorSearch('auth') // Expansión de consultas const expanded = await store.expandQuery('flujo auth', { intent: 'inicio de sesión de usuario' }) // Recuperación de documentos const doc = await store.get('docs/readme.md') const body = await store.getDocumentBody('docs/readme.md', { maxLines: 100 }) // Gestión de contexto await store.addContext('docs', '/api', 'Documentación de referencia de la API REST') await store.removeContext('docs', '/api') ``` ## Detalles del pipeline de búsqueda 1. **Expansión de consultas**: Consulta original (ponderada ×2) + 1 variación del LLM 2. **Recuperación paralela**: Cada consulta busca en los índices FTS y vectorial 3. **Bonificación por mejor rango**: Los documentos clasificados en el puesto #1 de cualquier lista reciben +0.05, los puestos #2-3 reciben +0.02 4. **Selección Top-K**: Tomar los 30 mejores candidatos para reordenar 5. **Reordenamiento**: El LLM puntúa cada documento (sí/no con confianza de logprobs) Rangos de puntuación: 0.0–0.2 relevancia baja, valores más altos indican mejores coincidencias. ## Configuración de modelos Modelos por defecto: - Embeddings: `embeddinggemma-300M-Q8_0` (~300MB) - Reordenamiento: basado en LLM (descargado bajo demanda) Ejemplo de modelo de embeddings personalizado: ```sh export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf" ``` Nota: Cambiar los modelos de embeddings requiere re-embedding de todas las colecciones, ya que los vectores no son compatibles entre sí. ## Requisitos - Runtime Node.js o Bun - Almacenamiento local suficiente para modelos y embeddings - Opcional: GPU/VRAM para inferencia LLM más rápida (los modelos permanecen cargados en VRAM entre solicitudes) ## Licencia Software de código abierto. Consulte el repositorio para más detalles.