Об этом проекте

# QMD - Query Markup Documents QMD — это локальный поисковый движок для персональных баз знаний, документации, заметок со встреч и любого контента на основе Markdown. Он работает полностью локально, сочетая полнотекстовый поиск BM25, векторный семантический поиск и реранжирование на основе LLM, что даёт высококачественные результаты без отправки данных во внешние сервисы. ## Основные возможности - **Гибридный поисковый конвейер**: сочетает BM25 (FTS5), векторный поиск по сходству и реранжирование LLM. Расширение запроса генерирует типизированные подзапросы (`lex` для ключевых слов, `vec` для плотных векторов, `hyde` для гипотетических эмбеддингов документов), которые направляются в соответствующие бэкенды, объединяются с помощью Reciprocal Rank Fusion (RRF) и реранжируются LLM. - **Контекстное дерево**: добавляет иерархический контекст к коллекциям (например, `qmd://notes` → «Личные заметки и идеи»), который возвращается вместе с подходящими документами, помогая LLM принимать более обоснованные контекстные решения. - **Локальные модели**: используются GGUF-модели, загружаемые с HuggingFace и кэшируемые локально. Модель эмбеддингов по умолчанию — `embeddinggemma-300M-Q8_0` (~300 МБ). Пользовательские модели задаются через переменную окружения `QMD_EMBED_MODEL` (например, для многоязычных корпусов). - **Чанкинг с учётом AST**: опциональный чанкинг на основе tree-sitter для файлов кода (TypeScript, JavaScript, Python, Go, Rust) даёт более качественные фрагменты; для остальных типов файлов используется чанкинг на основе регулярных выражений. - **MCP-сервер**: предоставляет сервер Model Context Protocol с инструментами для запросов, получения документов, пакетного получения и проверки статуса. Поддерживает транспорты stdio и HTTP с функциями безопасности (проверка origin/host для защиты от DNS-rebinding атак). - **SDK**: программный доступ через TypeScript/JavaScript SDK с методами поиска, получения документов, управления контекстом и расширения запросов. ## Быстрый старт ```sh # Установка глобально (Node или Bun) npm install -g @tobilu/qmd # или bun install -g @tobilu/qmd # Создание коллекций qmd collection add ~/notes --name notes qmd collection add ~/Documents/meetings --name meetings # Добавление контекста qmd context add qmd://notes "Личные заметки и идеи" # Генерация эмбеддингов qmd embed # Поиск qmd search "project timeline" # Быстрый поиск по ключевым словам qmd vsearch "how to deploy" # Семантический поиск qmd query "quarterly planning process" # Гибридный + реранжирование (лучшее качество) ``` ## Команды 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` — пакетное получение по glob, списку через запятую или docid - `status` — состояние индекса и информация о коллекциях HTTP-транспорт (порт по умолчанию 8181) предоставляет: - `POST /mcp` — MCP Streamable HTTP - `POST /query` (алиас `/search`) — структурированный поиск без протокола MCP - `GET /health` — проверка доступности Безопасность: запросы с заголовком `Origin`, не указывающим на loopback, отклоняются (403). Проверка `Host` предотвращает DNS rebinding. Переменные окружения `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' } } }) // Простой поиск (автоматическое расширение) const results = await store.search({ query: 'authentication flow' }) // Структурированный запрос с типизированными подзапросами 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'] }) // Отключение реранжирования для скорости const fast = await store.search({ query: 'auth', rerank: false }) // Фильтрация по метаданным const published = await store.search({ query: 'typescript', filter: { key: 'topics', operator: 'all', value: ['typescript'] } }) // Прямой доступ к бэкенду const bm25Results = await store.bm25Search('auth') const vectorResults = await store.vectorSearch('auth') // Расширение запроса const expanded = await store.expandQuery('auth flow', { intent: 'user login' }) // Получение документа const doc = await store.get('docs/readme.md') const body = await store.getDocumentBody('docs/readme.md', { maxLines: 100 }) // Управление контекстом await store.addContext('docs', '/api', 'REST API reference documentation') await store.removeContext('docs', '/api') ``` ## Детали поискового конвейера 1. **Расширение запроса**: исходный запрос (вес ×2) + 1 вариант от LLM 2. **Параллельное получение**: каждый запрос ищет и в FTS, и в векторном индексе 3. **Бонус за верхнюю позицию**: документы на 1-м месте в любом списке получают +0.05, 2–3 места — +0.02 4. **Выбор Top-K**: берутся 30 лучших кандидатов для реранжирования 5. **Реранжирование**: LLM оценивает каждый документ (да/нет с уверенностью logprobs) Диапазоны оценок: 0.0–0.2 — низкая релевантность, более высокие значения указывают на лучшее соответствие. ## Конфигурация моделей Модели по умолчанию: - Эмбеддинги: `embeddinggemma-300M-Q8_0` (~300 МБ) - Реранжирование: на основе LLM (загружается по требованию) Пример пользовательской модели эмбеддингов: ```sh export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf" ``` Примечание: при смене модели эмбеддингов требуется повторная генерация эмбеддингов всех коллекций, поскольку векторы несовместимы между моделями. ## Требования - Среда выполнения Node.js или Bun - Достаточно локального хранилища для моделей и эмбеддингов - Опционально: GPU/VRAM для ускорения инференса LLM (модели остаются загруженными в VRAM между запросами) ## Лицензия Открытое программное обеспечение. Подробности в репозитории.