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.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.