عن المشروع
# QMD - استعلام مستندات Markdown
QMD هو محرك بحث على الجهاز مصمم لقواعد المعرفة الشخصية والوثائق وملاحظات الاجتماعات وأي محتوى قائم على Markdown. يعمل محليًا بالكامل، ويجمع بين بحث النص الكامل BM25 والبحث الدلالي المتجه وإعادة الترتيب القائمة على LLM لتقديم نتائج عالية الجودة دون إرسال البيانات إلى خدمات خارجية.
## الميزات الأساسية
- **خط أنابيب البحث الهجين**: يجمع بين BM25 (FTS5) والبحث بتشابه المتجهات وإعادة الترتيب عبر LLM. يولد توسيع الاستعلام استعلامات فرعية مصنفة (`lex` للكلمات المفتاحية، `vec` للمتجهات الكثيفة، `hyde` لتضمينات المستندات الافتراضية) يتم توجيهها إلى الخلفيات المناسبة، ودمجها عبر دمج الرتب المتبادل (RRF)، وإعادة ترتيبها بواسطة LLM.
- **شجرة السياق**: إضافة سياق هرمي إلى المجموعات (مثل `qmd://notes` → "ملاحظات وأفكار شخصية") يتم إرجاعه مع المستندات المطابقة، مما يساعد نماذج LLM على اتخاذ قرارات سياقية أفضل.
- **النماذج المحلية**: يستخدم نماذج GGUF التي تم تنزيلها من HuggingFace وتخزينها محليًا. النموذج الافتراضي للتضمين هو `embeddinggemma-300M-Q8_0` (~300MB). يمكن تعيين نماذج مخصصة عبر متغير البيئة `QMD_EMBED_MODEL` (مثلًا للمجموعات متعددة اللغات).
- **تقسيم واعٍ لشجرة النحو (AST)**: تقسيم اختياري قائم على tree-sitter لملفات الكود (TypeScript وJavaScript وPython وGo وRust) ينتج أجزاء عالية الجودة؛ تستخدم أنواع الملفات الأخرى تقسيمًا قائمًا على التعبيرات النمطية.
- **خادم MCP**: يعرض خادم بروتوكول سياق النموذج (MCP) مع أدوات للاستعلام واسترجاع المستندات والاسترجاع الدفعي وفحص الحالة. يدعم نقل stdio وHTTP مع ميزات أمان (التحقق من الأصل/المضيف لمنع هجمات إعادة ربط DNS).
- **SDK**: وصول برمجي عبر SDK بلغة TypeScript/JavaScript مع طرق للبحث واسترجاع المستندات وإدارة السياق وتوسيع الاستعلام.
## بدء سريع
```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 "الجدول الزمني للمشروع" # بحث سريع بالكلمات المفتاحية
qmd vsearch "كيفية النشر" # بحث دلالي
qmd query "عملية التخطيط الربع سنوي" # هجين + إعادة ترتيب (أفضل جودة)
```
## أوامر 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 أو قائمة مفصولة بفواصل أو docids
- `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' } } })
// بحث بسيط (توسيع تلقائي)
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) + اختلاف واحد من 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` (~300MB)
- إعادة الترتيب: قائم على LLM (يتم تنزيله عند الطلب)
مثال نموذج تضمين مخصص:
```sh
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
```
ملاحظة: تغيير نماذج التضمين يتطلب إعادة تضمين جميع المجموعات لأن المتجهات غير متوافقة عبر النماذج.
## المتطلبات
- Node.js أو Bun runtime
- مساحة تخزين محلية كافية للنماذج والتضمينات
- اختياري: GPU/VRAM لاستدلال LLM أسرع (تبقى النماذج محملة في VRAM عبر الطلبات)
## الترخيص
برنامج مفتوح المصدر. راجع المستودع للحصول على التفاصيل.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.