Sessions and memory
محرك ذاكرة QMD
QMD هو محرك بحث جانبي يعطي الأولوية للتشغيل المحلي ويعمل إلى جانب OpenClaw. ويجمع بين BM25 والبحث المتجهي وإعادة الترتيب في ملف تنفيذي واحد، ويمكنه فهرسة محتوى يتجاوز ملفات ذاكرة مساحة عملك.
ما الذي يضيفه مقارنةً بالمحرك المضمّن
- إعادة الترتيب وتوسيع الاستعلام لتحسين الاستدعاء.
- فهرسة أدلة إضافية - وثائق المشروع وملاحظات الفريق وأي محتوى على القرص.
- فهرسة نصوص الجلسات - لاستدعاء المحادثات السابقة.
- محلي بالكامل - يعمل مع Plugin المزوّد الرسمي لـ llama.cpp وينزّل نماذج GGUF تلقائيًا.
- رجوع تلقائي - إذا لم يكن QMD متاحًا، يرجع OpenClaw بسلاسة إلى المحرك المضمّن.
بدء الاستخدام
المتطلبات الأساسية
- ثبّت QMD:
npm install -g @tobilu/qmdأوbun install -g @tobilu/qmd - إصدار SQLite يسمح بالامتدادات (
brew install sqliteعلى macOS). - يجب أن يكون QMD ضمن
PATHالخاص بـ Gateway. - يعمل macOS وLinux مباشرةً دون إعداد إضافي. ويحصل Windows على أفضل دعم عبر WSL2.
التمكين
{ memory: { backend: "qmd", },}ينشئ OpenClaw مجلدًا رئيسيًا مستقلاً لـ QMD ضمن
~/.openclaw/agents/<agentId>/qmd/ ويدير دورة حياة المحرك الجانبي
تلقائيًا - إذ يتولى المجموعات والتحديثات وعمليات التضمين نيابةً عنك.
ويفضّل الأشكال الحالية لمجموعات QMD واستعلامات MCP، لكنه يرجع إلى
أعلام أنماط المجموعات البديلة وأسماء أدوات MCP الأقدم عند الحاجة.
كما تعيد المطابقة عند بدء التشغيل إنشاء المجموعات المُدارة القديمة وفق
أنماطها المعيارية عندما تظل مجموعة QMD أقدم تحمل الاسم نفسه موجودة.
كيفية عمل المحرك الجانبي
- ينشئ OpenClaw مجموعات من ملفات ذاكرة مساحة عملك وأي مسارات
memory.qmd.pathsمُعدّة، ثم يشغّلqmd updateعند فتح مدير QMD ودوريًا بعد ذلك (memory.qmd.update.interval، والقيمة الافتراضية5m). تُنفّذ عمليات التحديث عبر عمليات QMD فرعية، وليس عبر مسح لنظام الملفات داخل العملية. كما تشغّل أوضاع البحث الدلاليqmd embed(memory.qmd.update.embedInterval، والقيمة الافتراضية60m). - تتعقب مجموعة مساحة العمل الافتراضية الملف
MEMORY.mdبالإضافة إلى شجرةmemory/. ولا تتم فهرسةmemory.mdالمكتوب بأحرف صغيرة بوصفه ملف ذاكرة جذريًا. - يتجاهل الماسح الخاص بـ QMD المسارات المخفية وأدلة التبعيات والبناء الشائعة
مثل
.gitو.cacheوnode_modulesوvendorوdistوbuild. ولا يهيّئ بدء تشغيل Gateway QMD افتراضيًا (القيمة الافتراضية لـmemory.qmd.update.startupهيoff)، لذا يتجنب التشغيل البارد استيراد بيئة تشغيل الذاكرة أو إنشاء المراقب طويل الأمد قبل استخدام الذاكرة للمرة الأولى. - عيّن
memory.qmd.update.startupإلىidleأوimmediateلتهيئة QMD عند بدء Gateway رغم ذلك. القيمة الافتراضية لـmemory.qmd.update.onBootهيtrueوتُشغّل التحديث الأولي عند بدء التشغيل؛ عيّنها إلىfalseلتخطي ذلك التحديث الفوري (يظل المدير طويل الأمد يُفتح عند إعداد فواصل التحديث أو التضمين، بحيث يواصل QMD امتلاك مراقبه ومؤقتاته الدورية). - تستخدم عمليات البحث
searchModeالمُعدّ (الافتراضي:search؛ ويدعم أيضًاvsearchوquery). يعتمدsearchعلى BM25 فقط، لذا يتخطى OpenClaw اختبارات جاهزية المتجهات الدلالية وصيانة التضمينات في هذا الوضع. وإذا فشل وضع ما، يعيد OpenClaw المحاولة باستخدامqmd query. - عندما تكون قيمة
searchModeهيquery، عيّنmemory.qmd.rerankإلىfalseلاستخدام مسار الاستعلام الهجين في QMD من دون أداة إعادة الترتيب (يتطلب QMD 2.1 أو أحدث). يمرر OpenClaw الخيار--no-rerankإلى مسار CLI المباشر لـ QMD، وrerank: falseإلى أداة استعلام MCP في QMD. - مع إصدارات QMD التي تعلن دعم عوامل تصفية متعددة للمجموعات، يجمع OpenClaw المجموعات ذات المصدر نفسه في استدعاء بحث واحد لـ QMD. وتحتفظ إصدارات QMD الأقدم بمسار الرجوع المتوافق الذي يعالج كل مجموعة على حدة.
- إذا فشل QMD بالكامل، يرجع OpenClaw إلى محرك SQLite المضمّن.
وتتراجع محاولات أدوار المحادثة المتكررة لفترة وجيزة بعد فشل الفتح، كي لا يؤدي
غياب الملف التنفيذي أو تعطل تبعية المحرك الجانبي إلى عاصفة من المحاولات؛
ويظل
openclaw memory statusواستقصاءات CLI أحادية التشغيل يعيدان فحص QMD مباشرةً.
أداء البحث والتوافق
يحافظ OpenClaw على توافق مسار بحث QMD مع تثبيتات QMD الحالية والأقدم.
عند بدء التشغيل، يتحقق OpenClaw مرة واحدة لكل مدير من نص المساعدة الخاص بـ QMD المثبّت. وإذا أعلن الملف التنفيذي دعم عوامل تصفية متعددة للمجموعات، يبحث OpenClaw في جميع المجموعات ذات المصدر نفسه باستخدام أمر واحد:
qmd search "router notes" --json -n 10 -c memory-root-main -c memory-dir-mainيتجنب ذلك بدء عملية QMD فرعية لكل مجموعة ذاكرة دائمة.
وتبقى مجموعات نصوص الجلسات في مجموعة مصدر مستقلة، لذا تظل عمليات البحث المختلطة
بين memory وsessions تمنح أداة تنويع النتائج مدخلات من كلا المصدرين.
لا تقبل إصدارات QMD الأقدم سوى عامل تصفية واحد للمجموعات. وعندما يكتشف OpenClaw أحد هذه الإصدارات، يحتفظ بمسار التوافق ويبحث في كل مجموعة على حدة قبل دمج النتائج وإزالة التكرارات منها.
لفحص العقد المثبّت يدويًا، شغّل:
qmd --help | grep -i collectionتشير مساعدة QMD الحالية إلى استهداف مجموعة واحدة أو أكثر. أما المساعدة الأقدم فعادةً ما تصف مجموعة واحدة.
تجاوزات النماذج
تمر متغيرات بيئة نماذج QMD دون تغيير من عملية Gateway، بحيث يمكنك ضبط QMD على المستوى العام دون إضافة إعداد جديد إلى OpenClaw:
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"export QMD_RERANK_MODEL="/absolute/path/to/reranker.gguf"export QMD_GENERATE_MODEL="/absolute/path/to/generator.gguf"بعد تغيير نموذج التضمين، أعد تشغيل التضمينات كي يتطابق الفهرس مع فضاء المتجهات الجديد.
فهرسة مسارات إضافية
وجّه QMD إلى أدلة إضافية لجعلها قابلة للبحث:
{ memory: { backend: "qmd", qmd: { paths: [{ name: "docs", path: "~/notes", pattern: "**/*.md" }], }, },}تظهر المقتطفات من المسارات الإضافية بالصيغة qmd/<collection>/<relative-path> في
نتائج البحث. ويفهم memory_get هذه البادئة ويقرأ من
جذر المجموعة الصحيح.
فهرسة نصوص الجلسات
فعّل فهرسة الجلسات لاستدعاء المحادثات السابقة. يحتاج QMD إلى مصدر الجلسات العام
memorySearch وإلى مُصدّر نصوص QMD معًا:
{ agents: { defaults: { memorySearch: { experimental: { sessionMemory: true }, sources: ["memory", "sessions"], }, }, }, memory: { backend: "qmd", qmd: { sessions: { enabled: true }, }, },}تُصدّر النصوص على هيئة أدوار منقّحة للمستخدم والمساعد إلى مجموعة QMD
مخصصة ضمن ~/.openclaw/agents/<id>/qmd/sessions/. ولا يؤدي تعيين
memorySearch.experimental.sessionMemory وحده إلى تصدير النصوص إلى
QMD.
تظل نتائج الجلسات خاضعة للتصفية حسب
tools.sessions.visibility. ولا تكشف
الرؤية الافتراضية tree جلسات غير مرتبطة تابعة للوكيل نفسه. وإذا كان ينبغي أن
تكون جلسة أرسلها Gateway قابلة للاستدعاء من جلسة رسالة مباشرة منفصلة،
فعيّن tools.sessions.visibility: "agent" عمدًا.
نطاق البحث
افتراضيًا، لا تظهر نتائج بحث QMD إلا في الجلسات المباشرة (وليس
في محادثات المجموعات أو القنوات). اضبط memory.qmd.scope لتغيير ذلك:
{ memory: { qmd: { scope: { default: "deny", rules: [{ action: "allow", match: { chatType: "direct" } }], }, }, },}المقتطف أعلاه هو القاعدة الافتراضية الفعلية. وعندما يمنع النطاق بحثًا، يسجل OpenClaw تحذيرًا يتضمن القناة ونوع المحادثة المستنتجين، لتسهيل تصحيح النتائج الفارغة.
الاستشهادات
عندما تكون قيمة memory.citations هي auto أو on، يُضاف إلى مقتطفات البحث
تذييل Source: <path>#L<line> (أو #L<start>-L<end>). وفي وضع auto
لا يُضاف التذييل إلا إلى جلسات المحادثة المباشرة. عيّن
memory.citations = "off" لحذف التذييل مع الاستمرار في تمرير المسار إلى
الوكيل داخليًا.
متى تستخدمه
اختر QMD عندما تحتاج إلى:
- إعادة الترتيب للحصول على نتائج أعلى جودة.
- البحث في وثائق المشروع أو الملاحظات خارج مساحة العمل.
- استدعاء محادثات الجلسات السابقة.
- بحث محلي بالكامل دون مفاتيح API.
بالنسبة إلى الإعدادات الأبسط، يعمل المحرك المضمّن جيدًا من دون تبعيات إضافية.
استكشاف الأخطاء وإصلاحها
لم يُعثر على QMD؟ تأكد من وجود الملف التنفيذي ضمن PATH الخاص بـ Gateway. إذا كان OpenClaw
يعمل كخدمة، فأنشئ رابطًا رمزيًا:
sudo ln -s ~/.bun/bin/qmd /usr/local/bin/qmd.
إذا كان qmd --version يعمل في صدفتك، لكن OpenClaw لا يزال يبلغ عن
spawn qmd ENOENT، فمن المرجح أن عملية Gateway لديها PATH مختلف عن
صدفتك التفاعلية. ثبّت مسار الملف التنفيذي صراحةً:
{ memory: { backend: "qmd", qmd: { command: "/absolute/path/to/qmd", }, },}استخدم command -v qmd في البيئة التي ثُبّت فيها QMD، ثم أعد التحقق
باستخدام openclaw memory status --deep.
هل البحث الأول بطيء جدًا؟ ينزّل QMD نماذج GGUF عند أول استخدام. نفّذ
تهيئة مسبقة باستخدام qmd query "test" مع أدلة XDG نفسها التي يستخدمها OpenClaw.
هل توجد عمليات QMD فرعية كثيرة أثناء البحث؟ حدّث QMD إن أمكن. يستخدم OpenClaw
عملية واحدة لعمليات البحث في مجموعات متعددة ذات المصدر نفسه فقط عندما يعلن
QMD المثبّت دعم عوامل تصفية -c متعددة؛ وإلا فإنه يحتفظ بمسار الرجوع الأقدم
الذي يعالج كل مجموعة على حدة لضمان الصحة.
هل لا يزال QMD المعتمد على BM25 فقط يحاول بناء llama.cpp؟ عيّن
memory.qmd.searchMode = "search". يتعامل OpenClaw مع هذا الوضع على أنه
معجمي فقط، ويتخطى استقصاءات حالة متجهات QMD وصيانة التضمينات، ويترك
اختبارات الجاهزية الدلالية لإعدادات vsearch أو query.
هل تنتهي مهلة البحث؟ زِد memory.qmd.limits.timeoutMs (القيمة الافتراضية:
4000ms). عيّنها إلى قيمة أكبر، مثل 120000، للأجهزة الأبطأ.
هل النتائج فارغة في محادثات المجموعات أو القنوات؟ هذا متوقع مع
memory.qmd.scope الافتراضي، الذي لا يسمح إلا بالجلسات المباشرة. أضف قاعدة
allow لأنواع المحادثات group أو channel إذا أردت ظهور نتائج QMD
هناك.
هل أصبح البحث في الذاكرة الجذرية واسعًا جدًا فجأة؟ أعد تشغيل Gateway أو انتظر
مطابقة بدء التشغيل التالية. يعيد OpenClaw إنشاء المجموعات المُدارة القديمة
وفق أنماط MEMORY.md وmemory/ المعيارية عندما
يكتشف تعارضًا في الاسم نفسه.
هل تتسبب المستودعات المؤقتة الظاهرة لمساحة العمل في ENAMETOOLONG أو تعطل الفهرسة؟
يتبع اجتياز QMD ماسح QMD الأساسي بدلًا من قواعد الروابط الرمزية
المضمّنة في OpenClaw. احتفظ بنسخ مستودعات monorepo المؤقتة داخل أدلة
مخفية مثل .tmp/ أو خارج جذور QMD المفهرسة إلى أن يوفّر QMD
اجتيازًا آمنًا من الدورات أو عناصر تحكم صريحة للاستثناء.
الإعداد
للاطلاع على نطاق الإعداد الكامل (memory.qmd.*) وأوضاع البحث وفواصل التحديث
وقواعد النطاق وجميع الخيارات الأخرى، راجع
مرجع إعداد الذاكرة.